Actual source code: taoterm.c
1: #include <petsc/private/taoimpl.h>
2: #include <petsc/private/vecimpl.h>
4: PetscClassId TAOTERM_CLASSID;
6: PetscLogEvent TAOTERM_ObjectiveEval;
7: PetscLogEvent TAOTERM_GradientEval;
8: PetscLogEvent TAOTERM_ObjGradEval;
9: PetscLogEvent TAOTERM_HessianEval;
11: const char *const TaoTermParametersModes[] = {"optional", "none", "required", "TaoTermParametersMode", "TAOTERM_PARAMETERS_", NULL};
13: /*@
14: TaoTermDestroy - Destroy a `TaoTerm`.
16: Collective
18: Input Parameter:
19: . term - a `TaoTerm`
21: Level: beginner
23: .seealso: [](sec_tao_term),
24: `TaoTerm`,
25: `TaoTermCreate()`,
26: `TaoTermSetType()`,
27: `TaoTermSetFromOptions()`,
28: `TaoTermSetUp()`,
29: `TaoTermView()`
30: @*/
31: PetscErrorCode TaoTermDestroy(TaoTerm *term)
32: {
33: PetscFunctionBegin;
34: if (!*term) PetscFunctionReturn(PETSC_SUCCESS);
36: if (--((PetscObject)*term)->refct > 0) {
37: *term = NULL;
38: PetscFunctionReturn(PETSC_SUCCESS);
39: }
41: PetscTryTypeMethod(*term, destroy);
42: PetscCall(PetscFree((*term)->H_mattype));
43: PetscCall(PetscFree((*term)->Hpre_mattype));
44: PetscCall(MatDestroy(&(*term)->solution_factory));
45: PetscCall(MatDestroy(&(*term)->parameters_factory));
46: PetscCall(MatDestroy(&(*term)->parameters_factory_orig));
47: PetscCall(PetscHeaderDestroy(term));
48: PetscFunctionReturn(PETSC_SUCCESS);
49: }
51: /*@
52: TaoTermView - View a description of a `TaoTerm`.
54: Collective
56: Input Parameters:
57: + term - a `TaoTerm`
58: - viewer - a `PetscViewer`
60: Level: beginner
62: .seealso: [](sec_tao_term),
63: `TaoTerm`,
64: `TaoTermCreate()`,
65: `TaoTermSetType()`,
66: `TaoTermSetFromOptions()`,
67: `TaoTermSetUp()`,
68: `TaoTermDestroy()`,
69: `PetscViewer`
70: @*/
71: PetscErrorCode TaoTermView(TaoTerm term, PetscViewer viewer)
72: {
73: PetscBool iascii;
75: PetscFunctionBegin;
77: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)term), &viewer));
79: PetscCheckSameComm(term, 1, viewer, 2);
81: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
82: if (iascii) {
83: const char *solution_vec_type;
84: PetscInt N;
85: PetscViewerFormat format;
87: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)term, viewer));
88: PetscCall(PetscViewerGetFormat(viewer, &format));
89: PetscCall(PetscViewerASCIIPushTab(viewer));
90: PetscCall(MatGetVecType(term->solution_factory, &solution_vec_type));
91: PetscCall(MatGetSize(term->solution_factory, &N, NULL));
92: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
93: if (N < 0) PetscCall(PetscViewerASCIIPrintf(viewer, "solution vector space: not set up yet [VecType %s (tao_term_solution_vec_type)]\n", solution_vec_type));
94: else PetscCall(PetscViewerASCIIPrintf(viewer, "solution vector space: N = %" PetscInt_FMT " [VecType %s (tao_term_solution_vec_type)]\n", N, solution_vec_type));
95: } else {
96: if (N < 0) PetscCall(PetscViewerASCIIPrintf(viewer, "solution vector space: not set up yet\n"));
97: else PetscCall(PetscViewerASCIIPrintf(viewer, "solution vector space: N = %" PetscInt_FMT "\n", N));
98: }
99: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL && term->parameters_mode == TAOTERM_PARAMETERS_NONE) {
100: PetscCall(PetscViewerASCIIPrintf(viewer, "parameter vector space: (none)\n"));
101: } else if (term->parameters_mode != TAOTERM_PARAMETERS_NONE) {
102: const char *parameters_vec_type;
103: PetscInt K;
105: PetscCall(MatGetVecType(term->parameters_factory, ¶meters_vec_type));
106: PetscCall(MatGetSize(term->parameters_factory, &K, NULL));
107: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
108: if (K < 0) PetscCall(PetscViewerASCIIPrintf(viewer, "parameter vector space: (%s) not set up yet [VecType %s (tao_term_parameters_vec_type)]\n", TaoTermParametersModes[term->parameters_mode], parameters_vec_type));
109: else PetscCall(PetscViewerASCIIPrintf(viewer, "parameter vector space: (%s) K = %" PetscInt_FMT " [VecType %s (tao_term_parameters_vec_type)]\n", TaoTermParametersModes[term->parameters_mode], K, parameters_vec_type));
110: } else {
111: if (K < 0) PetscCall(PetscViewerASCIIPrintf(viewer, "parameter vector space:%s not set up yet\n", term->parameters_mode == TAOTERM_PARAMETERS_OPTIONAL ? " (optional)" : ""));
112: else PetscCall(PetscViewerASCIIPrintf(viewer, "parameter vector space:%s K = %" PetscInt_FMT "\n", term->parameters_mode == TAOTERM_PARAMETERS_OPTIONAL ? " (optional)" : "", K));
113: }
114: }
115: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
116: PetscBool3 is_fdpossible;
118: PetscCall(TaoTermIsComputeHessianFDPossible(term, &is_fdpossible));
119: if (is_fdpossible == PETSC_BOOL3_FALSE) {
120: if (term->fd_hessian) PetscCall(PetscViewerASCIIPrintf(viewer, "Finite differences for Hessian computation was requested, but ignored.\n"));
121: if (term->ops->createhessianmatrices == TaoTermCreateHessianMatricesDefault) {
122: PetscCall(PetscViewerASCIIPrintf(viewer, "default Hessian MatType (tao_term_hessian_mat_type): %s\n", term->H_mattype ? term->H_mattype : "(undefined)"));
123: if (!term->Hpre_is_H) PetscCall(PetscViewerASCIIPrintf(viewer, "default Hessian preconditioning MatType (tao_term_hessian_pre_mat_type): %s\n", term->Hpre_mattype ? term->Hpre_mattype : "(undefined)"));
124: } else {
125: PetscCall(PetscViewerASCIIPrintf(viewer, "Hessian MatType (tao_term_hessian_mat_type): %s\n", term->H_mattype ? term->H_mattype : "(undefined)"));
126: if (!term->Hpre_is_H) PetscCall(PetscViewerASCIIPrintf(viewer, "Hessian preconditioning MatType (tao_term_hessian_pre_mat_type): %s\n", term->Hpre_mattype ? term->Hpre_mattype : "(undefined)"));
127: }
128: } else {
129: if (term->fd_hessian) PetscCall(PetscViewerASCIIPrintf(viewer, "Using finite differences for Hessian computation\n"));
130: else if (term->ops->createhessianmatrices == TaoTermCreateHessianMatricesDefault) {
131: PetscCall(PetscViewerASCIIPrintf(viewer, "default Hessian MatType (tao_term_hessian_mat_type): %s\n", term->H_mattype ? term->H_mattype : "(undefined)"));
132: if (!term->Hpre_is_H) PetscCall(PetscViewerASCIIPrintf(viewer, "default Hessian preconditioning MatType (tao_term_hessian_pre_mat_type): %s\n", term->Hpre_mattype ? term->Hpre_mattype : "(undefined)"));
133: } else {
134: PetscBool is_h_mffd = PETSC_FALSE;
135: PetscBool is_hpre_mffd = PETSC_FALSE;
137: if (term->H_mattype) PetscCall(PetscStrcmp(term->H_mattype, MATMFFD, &is_h_mffd));
138: if (term->Hpre_mattype) PetscCall(PetscStrcmp(term->Hpre_mattype, MATMFFD, &is_hpre_mffd));
140: PetscCall(PetscViewerASCIIPrintf(viewer, "Hessian MatType (tao_term_hessian_mat_type): %s\n", term->H_mattype ? term->H_mattype : "(undefined)"));
141: if (is_h_mffd) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations used by MFFD=%" PetscInt_FMT "\n", term->ngrad_mffd));
142: if (!term->Hpre_is_H) PetscCall(PetscViewerASCIIPrintf(viewer, "Hessian preconditioning MatType (tao_term_hessian_pre_mat_type): %s\n", term->Hpre_mattype ? term->Hpre_mattype : "(undefined)"));
143: }
144: }
145: }
146: PetscTryTypeMethod(term, view, viewer);
147: if (term->nobj > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT "\n", term->nobj));
148: if (term->ngrad > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT "\n", term->ngrad));
149: if (term->nobjgrad > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT "\n", term->nobjgrad));
150: if (term->nhess > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", term->nhess));
151: PetscCall(PetscViewerASCIIPopTab(viewer));
152: }
153: PetscFunctionReturn(PETSC_SUCCESS);
154: }
156: /*@
157: TaoTermSetUp - Set up a `TaoTerm`.
159: Collective
161: Input Parameter:
162: . term - a `TaoTerm`
164: Level: intermediate
166: .seealso: [](sec_tao_term),
167: `TaoTerm`,
168: `TaoTermCreate()`,
169: `TaoTermSetType()`,
170: `TaoTermSetFromOptions()`,
171: `TaoTermView()`,
172: `TaoTermDestroy()`
173: @*/
174: PetscErrorCode TaoTermSetUp(TaoTerm term)
175: {
176: PetscInt N;
178: PetscFunctionBegin;
180: if (term->setup_called) PetscFunctionReturn(PETSC_SUCCESS);
181: term->setup_called = PETSC_TRUE;
182: PetscTryTypeMethod(term, setup);
183: PetscCall(MatGetSize(term->solution_factory, &N, NULL));
184: if (N < 0) {
185: PetscBool is_shell;
186: Vec sol_template;
188: PetscCall(PetscObjectTypeCompare((PetscObject)term, TAOTERMSHELL, &is_shell));
189: if (is_shell)
190: PetscCheck(term->ops->createsolutionvec, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm solution space not known. You should have called TaoTermSetSolutionSizes(), TaoTermSetSolutionTemplate(), TaoTermSetSolutionLayout(), or TaoTermShellSetCreateSolutionVec()");
191: else
192: PetscCheck(term->ops->createsolutionvec, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm solution space not known. You should have called TaoTermSetSolutionSizes(), TaoTermSetSolutionTemplate(), or TaoTermSetSolutionLayout()");
194: PetscCall(TaoTermCreateSolutionVec(term, &sol_template));
195: PetscCall(TaoTermSetSolutionTemplate(term, sol_template));
196: PetscCall(VecDestroy(&sol_template));
197: }
198: PetscCall(MatSetUp(term->solution_factory));
199: if (term->parameters_mode != TAOTERM_PARAMETERS_NONE) {
200: PetscInt K;
202: PetscCall(MatGetSize(term->parameters_factory, &K, NULL));
203: if (K < 0) {
204: PetscBool is_shell;
205: Vec params_template;
207: PetscCall(PetscObjectTypeCompare((PetscObject)term, TAOTERMSHELL, &is_shell));
208: if (is_shell)
209: PetscCheck(term->ops->createparametersvec, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm parameters space not known. You should have called TaoTermSetParametersSizes(), TaoTermSetParametersTemplate(), TaoTermSetParametersLayout(), or TaoTermShellSetCreateParametersVec()");
210: else
211: PetscCheck(term->ops->createparametersvec, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm parameters space not known. You should have called TaoTermSetParametersSizes(), TaoTermSetParametersTemplate(), or TaoTermSetParametersLayout()");
213: PetscCall(TaoTermCreateParametersVec(term, ¶ms_template));
214: PetscCall(TaoTermSetParametersTemplate(term, params_template));
215: PetscCall(VecDestroy(¶ms_template));
216: }
217: PetscCall(MatSetUp(term->parameters_factory));
218: }
219: PetscFunctionReturn(PETSC_SUCCESS);
220: }
222: /*@
223: TaoTermSetFromOptions - Configure a `TaoTerm` from the PETSc options database
225: Collective
227: Input Parameter:
228: . term - a `TaoTerm`
230: Options Database Keys:
231: + -tao_term_type <type> - l1, halfl2squared; see `TaoTermType` for a complete list
232: . -tao_term_solution_vec_type <type> - the type of vector to use for the solution, see `VecType` for a complete list of vector types
233: . -tao_term_parameters_vec_type <type> - the type of vector to use for the parameters, see `VecType` for a complete list of vector types
234: . -tao_term_parameters_mode <optional,none,required> - `TAOTERM_PARAMETERS_OPTIONAL`, `TAOTERM_PARAMETERS_NONE`, `TAOTERM_PARAMETERS_REQUIRED`
235: . -tao_term_hessian_pre_is_hessian <bool> - Whether `TaoTermCreateHessianMatricesDefault()` should make a separate preconditioning matrix
236: . -tao_term_hessian_mat_type <type> - `MatType` for Hessian matrix created by `TaoTermCreateHessianMatricesDefault()`
237: . -tao_term_hessian_pre_mat_type <type> - `MatType` for approximate Hessian matrix used to construct the preconditioner created by `TaoTermCreateHessianMatricesDefault()`
238: . -tao_term_fd_delta <real> - Increment for finite difference derivative approximations in `TaoTermComputeGradientFD()`
239: . -tao_term_gradient_use_fd <bool> - Use finite differences in `TaoTermComputeGradient()`, overriding other user-provided or built-in routines
240: - -tao_term_hessian_use_fd <bool> - Use finite differences in `TaoTermComputeHessian()`, overriding other user-provided or built-in routines
242: Level: beginner
244: .seealso: [](sec_tao_term),
245: `TaoTerm`,
246: `TaoTermCreate()`,
247: `TaoTermSetType()`,
248: `TaoTermSetUp()`,
249: `TaoTermView()`,
250: `TaoTermDestroy()`
251: @*/
252: PetscErrorCode TaoTermSetFromOptions(TaoTerm term)
253: {
254: const char *deft = TAOTERMSHELL;
255: PetscBool flg;
256: char typeName[256];
257: VecType sol_type, params_type;
258: PetscBool opt;
259: PetscBool grad_use_fd;
260: PetscBool hess_use_fd;
262: PetscFunctionBegin;
264: if (((PetscObject)term)->type_name) deft = ((PetscObject)term)->type_name;
265: PetscObjectOptionsBegin((PetscObject)term);
266: PetscCall(PetscOptionsFList("-tao_term_type", "TaoTerm type", "TaoTermType", TaoTermList, deft, typeName, 256, &flg));
267: if (flg) PetscCall(TaoTermSetType(term, typeName));
268: else PetscCall(TaoTermSetType(term, deft));
269: PetscCall(TaoTermGetSolutionVecType(term, &sol_type));
270: PetscCall(TaoTermGetParametersVecType(term, ¶ms_type));
271: PetscCall(PetscOptionsFList("-tao_term_solution_vec_type", "Solution vector type", "TaoTermSetSolutionVecType", VecList, sol_type, typeName, 256, &opt));
272: if (opt) PetscCall(TaoTermSetSolutionVecType(term, typeName));
273: PetscCall(PetscOptionsFList("-tao_term_parameters_vec_type", "Parameters vector type", "TaoTermSetParametersVecType", VecList, params_type, typeName, 256, &opt));
274: if (opt) PetscCall(TaoTermSetParametersVecType(term, typeName));
275: PetscCall(PetscOptionsEnum("-tao_term_parameters_mode", "Parameters requirement type", "TaoTermSetParametersMode", TaoTermParametersModes, (PetscEnum)term->parameters_mode, (PetscEnum *)&term->parameters_mode, NULL));
276: PetscCall(PetscOptionsBool("-tao_term_hessian_pre_is_hessian", "If the Hessian and its preconditioning matrix should be the same", "TaoTermSetCreateHessianMode", term->Hpre_is_H, &term->Hpre_is_H, NULL));
278: deft = MATAIJ;
279: if (term->H_mattype) deft = term->H_mattype;
280: PetscCall(PetscOptionsFList("-tao_term_hessian_mat_type", "Hessian mat type", "TaoTermSetCreateHessianMode", MatList, deft, typeName, 256, &opt));
281: if (opt) {
282: PetscBool is_mffd, is_shell, is_callbacks;
283: PetscCall(PetscStrcmp(typeName, MATMFFD, &is_mffd));
284: if (is_mffd) {
285: PetscCall(PetscObjectTypeCompare((PetscObject)term, TAOTERMSHELL, &is_shell));
286: PetscCall(PetscObjectTypeCompare((PetscObject)term, TAOTERMCALLBACKS, &is_callbacks));
287: if (is_shell || is_callbacks) {
288: PetscCall(PetscFree(term->H_mattype));
289: PetscCall(PetscStrallocpy(typeName, (char **)&term->H_mattype));
290: } else {
291: PetscCall(PetscInfo(term, "%s: TaoTerm Hessian MatType MFFD requested but TaoTerm type is neither SHELL nor CALLBACKS. Ignoring.\n", ((PetscObject)term)->prefix));
292: }
293: } else {
294: PetscCall(PetscFree(term->H_mattype));
295: PetscCall(PetscStrallocpy(typeName, (char **)&term->H_mattype));
296: }
297: }
299: deft = MATAIJ;
300: if (term->Hpre_mattype) deft = term->Hpre_mattype;
301: PetscCall(PetscOptionsFList("-tao_term_hessian_pre_mat_type", "Hessian preconditioning mat type", "TaoTermSetCreateHessianMode", MatList, deft, typeName, 256, &opt));
302: if (opt) {
303: PetscCall(PetscFree(term->Hpre_mattype));
304: PetscCall(PetscStrallocpy(typeName, (char **)&term->Hpre_mattype));
305: }
307: if (term->Hpre_is_H) {
308: PetscBool mattypes_same;
310: PetscCall(PetscStrcmp(term->H_mattype, term->Hpre_mattype, &mattypes_same));
311: if (!mattypes_same) {
312: PetscCall(PetscInfo(term, "%s: Hpre_is_H, but H_mattype and Hpre_mattype are different. Setting Hpre_mattype to be same as H_mattype\n", ((PetscObject)term)->prefix));
313: PetscCall(PetscFree(term->Hpre_mattype));
314: PetscCall(PetscStrallocpy(term->H_mattype, (char **)&term->Hpre_mattype));
315: }
316: }
318: PetscCall(PetscOptionsBoundedReal("-tao_term_fd_delta", "Finite difference increment", "TaoTermSetFDDelta", term->fd_delta, &term->fd_delta, NULL, PETSC_SMALL));
319: PetscCall(PetscInfo(term, "%s: Finite difference delta set to %g\n", ((PetscObject)term)->prefix, (double)term->fd_delta));
321: grad_use_fd = term->fd_gradient;
322: PetscCall(PetscOptionsBool("-tao_term_gradient_use_fd", "Use finite differences in TaoTermComputeGradient()", "TaoTermComputeGradientSetUseFD", grad_use_fd, &grad_use_fd, NULL));
323: PetscCall(TaoTermComputeGradientSetUseFD(term, grad_use_fd));
325: hess_use_fd = term->fd_hessian;
326: PetscCall(PetscOptionsBool("-tao_term_hessian_use_fd", "Use finite differences in TaoTermComputeHessian()", "TaoTermComputeHessianSetUseFD", hess_use_fd, &hess_use_fd, NULL));
327: PetscCall(TaoTermComputeHessianSetUseFD(term, hess_use_fd));
329: PetscTryTypeMethod(term, setfromoptions, PetscOptionsObject);
330: PetscOptionsEnd();
331: PetscFunctionReturn(PETSC_SUCCESS);
332: }
334: /*@
335: TaoTermSetType - Set the type of a `TaoTerm`
337: Collective
339: Input Parameters:
340: + term - a `TaoTerm`
341: - type - a `TaoTermType`
343: Options Database Keys:
344: . -tao_term_type <type> - l1, halfl2squared, `TaoTermType` for complete list
346: Level: beginner
348: Notes:
349: Use `TaoTermCreateShell()` to define a custom term using your own function definition
351: New types of `TaoTerm` can be created with `TaoTermRegister()`
353: .seealso: [](sec_tao_term),
354: `TaoTerm`,
355: `TaoTermType`,
356: `TaoTermCreate()`,
357: `TaoTermGetType()`,
358: `TaoTermSetFromOptions()`,
359: `TaoTermSetUp()`,
360: `TaoTermView()`,
361: `TaoTermDestroy()`
362: @*/
363: PetscErrorCode TaoTermSetType(TaoTerm term, TaoTermType type)
364: {
365: PetscErrorCode (*create)(TaoTerm);
366: PetscBool issame;
368: PetscFunctionBegin;
371: PetscCall(PetscObjectTypeCompare((PetscObject)term, type, &issame));
372: if (issame) PetscFunctionReturn(PETSC_SUCCESS);
374: PetscCall(PetscFunctionListFind(TaoTermList, type, (void (**)(void))&create));
375: PetscCheck(create, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested TaoTerm type %s", type);
377: /* Destroy the existing term information */
378: PetscTryTypeMethod(term, destroy);
379: term->setup_called = PETSC_FALSE;
380: PetscCall(PetscMemzero(term->ops, sizeof(struct _TaoTermOps)));
382: PetscCall((*create)(term));
383: PetscCall(PetscObjectChangeTypeName((PetscObject)term, type));
384: PetscFunctionReturn(PETSC_SUCCESS);
385: }
387: /*@
388: TaoTermGetType - Get the type of a `TaoTerm`
390: Not collective
392: Input Parameter:
393: . term - a `TaoTerm`
395: Output Parameter:
396: . type - the `TaoTermType`
398: Level: beginner
400: .seealso: [](sec_tao_term),
401: `TaoTerm`,
402: `TaoTermType`,
403: `TaoTermCreate()`,
404: `TaoTermSetType()`,
405: `TaoTermSetFromOptions()`,
406: `TaoTermSetUp()`,
407: `TaoTermView()`,
408: `TaoTermDestroy()`
409: @*/
410: PetscErrorCode TaoTermGetType(TaoTerm term, TaoTermType *type)
411: {
412: PetscFunctionBegin;
414: PetscAssertPointer(type, 2);
415: *type = ((PetscObject)term)->type_name;
416: PetscFunctionReturn(PETSC_SUCCESS);
417: }
419: /*@
420: TaoTermCreate - Create a TaoTerm to use in defining the function `Tao` is to optimize
422: Collective
424: Input Parameter:
425: . comm - communicator for MPI processes that compute the term
427: Output Parameter:
428: . term - a new `TaoTerm`
430: Level: beginner
432: .seealso: [](sec_tao_term),
433: `TaoTerm`,
434: `TaoTermSetType()`,
435: `TaoAddTerm()`,
436: `TaoTermSetFromOptions()`,
437: `TaoTermSetUp()`,
438: `TaoTermView()`,
439: `TaoTermDestroy()`
440: @*/
441: PetscErrorCode TaoTermCreate(MPI_Comm comm, TaoTerm *term)
442: {
443: TaoTerm _term;
444: PetscLayout zero_layout, rlayout, clayout;
446: PetscFunctionBegin;
447: PetscAssertPointer(term, 2);
448: PetscCall(TaoInitializePackage());
449: PetscCall(PetscHeaderCreate(_term, TAOTERM_CLASSID, "TaoTerm", "Objective function term", "Tao", comm, TaoTermDestroy, TaoTermView));
450: PetscCall(MatCreate(comm, &_term->solution_factory));
451: PetscCall(MatSetType(_term->solution_factory, MATDUMMY));
452: PetscCall(MatCreate(comm, &_term->parameters_factory));
453: PetscCall(MatSetType(_term->parameters_factory, MATDUMMY));
454: PetscCall(PetscObjectReference((PetscObject)_term->parameters_factory));
455: _term->parameters_factory_orig = _term->parameters_factory;
456: PetscCall(PetscLayoutCreateFromSizes(comm, 0, 0, 1, &zero_layout));
457: PetscCall(MatGetLayouts(_term->solution_factory, &rlayout, &clayout));
458: PetscCall(MatSetLayouts(_term->solution_factory, rlayout, zero_layout));
459: PetscCall(MatGetLayouts(_term->parameters_factory, &rlayout, &clayout));
460: PetscCall(MatSetLayouts(_term->parameters_factory, rlayout, zero_layout));
461: PetscCall(PetscLayoutDestroy(&zero_layout));
462: _term->ngrad_mffd = 0;
463: _term->nobj = 0;
464: _term->ngrad = 0;
465: _term->nobjgrad = 0;
466: _term->nhess = 0;
467: _term->Hpre_is_H = PETSC_TRUE;
468: _term->fd_delta = 0.5 * PETSC_SQRT_MACHINE_EPSILON;
469: _term->H_mattype = NULL;
470: _term->Hpre_mattype = NULL;
471: *term = _term;
472: PetscFunctionReturn(PETSC_SUCCESS);
473: }
475: /*@
476: TaoTermComputeObjective - Evaluate a `TaoTerm` for a given solution vector and parameter vector
478: Collective
480: Input Parameters:
481: + term - a `TaoTerm` representing a parametric function $f(x; p)$
482: . x - the solution variable $x$ in $f(x; p)$
483: - params - the parameters $p$ in $f(x; p)$ (may be `NULL` if the term is not parametric)
485: Output Parameter:
486: . value - the value of $f(x; p)$
488: Level: developer
490: .seealso: [](sec_tao_term),
491: `TaoTerm`,
492: `TaoTermComputeGradient()`,
493: `TaoTermComputeObjectiveAndGradient()`,
494: `TaoTermComputeHessian()`,
495: `TaoTermShellSetObjective()`
496: @*/
497: PetscErrorCode TaoTermComputeObjective(TaoTerm term, Vec x, Vec params, PetscReal *value)
498: {
499: PetscBool obj, objgrad;
501: PetscFunctionBegin;
504: PetscCheckSameComm(term, 1, x, 2);
505: PetscAssertPointer(value, 4);
506: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_NONE || params == NULL, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters passed to a TaoTerm with TAOTERM_PARAMETERS_NONE");
507: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_REQUIRED || params, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters required but not provided for a TaoTerm with TAOTERM_PARAMETERS_REQUIRED");
508: if (params) {
510: PetscCheckSameComm(term, 1, params, 3);
511: PetscCall(VecLockReadPush(params));
512: }
513: PetscCall(VecLockReadPush(x));
514: PetscCall(TaoTermIsObjectiveDefined(term, &obj));
515: PetscCall(TaoTermIsObjectiveAndGradientDefined(term, &objgrad));
516: if (obj) {
517: PetscCall(PetscLogEventBegin(TAOTERM_ObjectiveEval, term, NULL, NULL, NULL));
518: PetscUseTypeMethod(term, objective, x, params, value);
519: PetscCall(PetscLogEventEnd(TAOTERM_ObjectiveEval, term, NULL, NULL, NULL));
520: term->nobj++;
521: } else if (objgrad) {
522: Vec temp;
524: PetscCall(PetscInfo(term, "%s: Duplicating solution vector in order to call objective/gradient routine\n", ((PetscObject)term)->prefix));
525: PetscCall(VecDuplicate(x, &temp));
526: PetscCall(PetscLogEventBegin(TAOTERM_ObjGradEval, term, NULL, NULL, NULL));
527: PetscUseTypeMethod(term, objectiveandgradient, x, params, value, temp);
528: PetscCall(PetscLogEventEnd(TAOTERM_ObjGradEval, term, NULL, NULL, NULL));
529: PetscCall(VecDestroy(&temp));
530: term->nobjgrad++;
531: } else SETERRQ(PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm does not have an objective function");
532: if (params) PetscCall(VecLockReadPop(params));
533: PetscCall(VecLockReadPop(x));
534: PetscCall(PetscInfo(term, "%s: TaoTerm value: %20.19e\n", ((PetscObject)term)->prefix, (double)(*value)));
535: PetscFunctionReturn(PETSC_SUCCESS);
536: }
538: /*@
539: TaoTermComputeGradient - Evaluate the gradient of a `TaoTerm` for a given solution vector and parameter vector
541: Collective
543: Input Parameters:
544: + term - a `TaoTerm` representing a parametric function $f(x; p)$
545: . x - the solution variable $x$ in $f(x; p)$
546: - params - the parameters $p$ in $f(x; p)$ (may be NULL if the term is not parametric)
548: Output Parameter:
549: . g - the value of $\nabla_x f(x; p)$
551: Level: developer
553: .seealso: [](sec_tao_term),
554: `TaoTerm`,
555: `TaoTermComputeObjective()`,
556: `TaoTermComputeObjectiveAndGradient()`,
557: `TaoTermComputeHessian()`,
558: `TaoTermShellSetGradient()`
559: @*/
560: PetscErrorCode TaoTermComputeGradient(TaoTerm term, Vec x, Vec params, Vec g)
561: {
562: PetscBool objgrad, grad;
564: PetscFunctionBegin;
568: PetscCheckSameComm(term, 1, x, 2);
569: PetscCheckSameComm(term, 1, g, 4);
570: VecCheckSameSize(x, 2, g, 4);
571: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_NONE || params == NULL, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters passed to a TaoTerm with TAOTERM_PARAMETERS_NONE");
572: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_REQUIRED || params, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters required but not provided for a TaoTerm with TAOTERM_PARAMETERS_REQUIRED");
573: if (params) {
575: PetscCheckSameComm(term, 1, params, 3);
576: PetscCall(VecLockReadPush(params));
577: }
578: PetscCall(VecLockReadPush(x));
579: PetscCall(TaoTermIsGradientDefined(term, &grad));
580: PetscCall(TaoTermIsObjectiveAndGradientDefined(term, &objgrad));
581: if (term->fd_gradient) {
582: PetscCall(PetscLogEventBegin(TAOTERM_GradientEval, term, NULL, NULL, NULL));
583: PetscCall(TaoTermComputeGradientFD(term, x, params, g));
584: PetscCall(PetscLogEventEnd(TAOTERM_GradientEval, term, NULL, NULL, NULL));
585: term->ngrad++;
586: } else if (grad) {
587: PetscCall(PetscLogEventBegin(TAOTERM_GradientEval, term, NULL, NULL, NULL));
588: PetscUseTypeMethod(term, gradient, x, params, g);
589: PetscCall(PetscLogEventEnd(TAOTERM_GradientEval, term, NULL, NULL, NULL));
590: term->ngrad++;
591: } else if (objgrad) {
592: PetscReal value;
594: PetscCall(PetscLogEventBegin(TAOTERM_ObjGradEval, term, NULL, NULL, NULL));
595: PetscUseTypeMethod(term, objectiveandgradient, x, params, &value, g);
596: PetscCall(PetscLogEventEnd(TAOTERM_ObjGradEval, term, NULL, NULL, NULL));
597: term->nobjgrad++;
598: } else SETERRQ(PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm does not have a gradient function");
599: if (params) PetscCall(VecLockReadPop(params));
600: PetscCall(VecLockReadPop(x));
601: PetscFunctionReturn(PETSC_SUCCESS);
602: }
604: /*@
605: TaoTermComputeObjectiveAndGradient - Evaluate both the value and gradient of
606: a `TaoTerm` for a given set of solution vector and parameter vector
608: Collective
610: Input Parameters:
611: + term - a `TaoTerm` representing a parametric function $f(x; p)$
612: . x - the solution variable $x$ in $f(x; p)$
613: - params - the parameters $p$ in $f(x; p)$ (may be NULL if the term is not parametric)
615: Output Parameters:
616: + value - the value of $f(x; p)$
617: - g - the value of $\nabla_x f(x; p)$
619: Level: developer
621: .seealso: [](sec_tao_term),
622: `TaoTerm`,
623: `TaoTermComputeObjective()`,
624: `TaoTermComputeGradient()`,
625: `TaoTermComputeHessian()`,
626: `TaoTermShellSetObjectiveAndGradient()`
627: @*/
628: PetscErrorCode TaoTermComputeObjectiveAndGradient(TaoTerm term, Vec x, Vec params, PetscReal *value, Vec g)
629: {
630: PetscBool objgrad, obj, grad;
632: PetscFunctionBegin;
636: PetscAssertPointer(value, 4);
637: PetscCheckSameComm(term, 1, x, 2);
638: PetscCheckSameComm(term, 1, g, 5);
639: VecCheckSameSize(x, 2, g, 5);
640: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_NONE || params == NULL, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters passed to a TaoTerm with TAOTERM_PARAMETERS_NONE");
641: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_REQUIRED || params, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters required but not provided for a TaoTerm with TAOTERM_PARAMETERS_REQUIRED");
642: if (params) {
644: PetscCheckSameComm(term, 1, params, 3);
645: PetscCall(VecLockReadPush(params));
646: }
647: PetscCall(VecLockReadPush(x));
648: PetscCall(TaoTermIsObjectiveDefined(term, &obj));
649: PetscCall(TaoTermIsGradientDefined(term, &grad));
650: PetscCall(TaoTermIsObjectiveAndGradientDefined(term, &objgrad));
651: if (term->fd_gradient) {
652: PetscCall(TaoTermComputeObjective(term, x, params, value));
653: PetscCall(PetscLogEventBegin(TAOTERM_GradientEval, term, NULL, NULL, NULL));
654: PetscCall(TaoTermComputeGradientFD(term, x, params, g));
655: PetscCall(PetscLogEventEnd(TAOTERM_GradientEval, term, NULL, NULL, NULL));
656: term->ngrad++;
657: } else if (objgrad) {
658: PetscCall(PetscLogEventBegin(TAOTERM_ObjGradEval, term, NULL, NULL, NULL));
659: PetscUseTypeMethod(term, objectiveandgradient, x, params, value, g);
660: PetscCall(PetscLogEventEnd(TAOTERM_ObjGradEval, term, NULL, NULL, NULL));
661: term->nobjgrad++;
662: } else if (obj && grad) {
663: PetscCall(PetscLogEventBegin(TAOTERM_ObjectiveEval, term, NULL, NULL, NULL));
664: PetscUseTypeMethod(term, objective, x, params, value);
665: PetscCall(PetscLogEventEnd(TAOTERM_ObjectiveEval, term, NULL, NULL, NULL));
666: term->nobj++;
667: PetscCall(PetscLogEventBegin(TAOTERM_GradientEval, term, NULL, NULL, NULL));
668: PetscUseTypeMethod(term, gradient, x, params, g);
669: PetscCall(PetscLogEventEnd(TAOTERM_GradientEval, term, NULL, NULL, NULL));
670: term->ngrad++;
671: } else SETERRQ(PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm does not have objective and gradient function");
672: if (params) PetscCall(VecLockReadPop(params));
673: PetscCall(VecLockReadPop(x));
674: PetscCall(PetscInfo(term, "%s: TaoTerm value: %20.19e\n", ((PetscObject)term)->prefix, (double)(*value)));
675: PetscFunctionReturn(PETSC_SUCCESS);
676: }
678: /*@
679: TaoTermComputeHessian - Evaluate the Hessian of a `TaoTerm`
680: (with respect to the solution variables) for a given solution vector and parameter vector
682: Collective
684: Input Parameters:
685: + term - a `TaoTerm` representing a parametric function $f(x; p)$
686: . x - the solution variable $x$ in $f(x; p)$
687: - params - the parameters $p$ in $f(x; p)$ (may be `NULL` if the term is not parametric)
689: Output Parameters:
690: + H - Hessian matrix $\nabla_x^2 f(x;p)$
691: - Hpre - an (approximate) Hessian from which the preconditioner will be constructed, often the same as `H`
693: Level: developer
695: Note:
696: If there is no separate matrix from which to construct the preconditioner, then `TaoTermComputeHessian(term, x, params, H, NULL)`
697: and `TaoTermComputeHessian(term, x, params, H, H)` are equivalent.
699: .seealso: [](sec_tao_term),
700: `TaoTerm`,
701: `TaoTermComputeObjective()`,
702: `TaoTermComputeGradient()`,
703: `TaoTermComputeObjectiveAndGradient()`,
704: `TaoTermShellSetHessian()`
705: @*/
706: PetscErrorCode TaoTermComputeHessian(TaoTerm term, Vec x, Vec params, Mat H, Mat Hpre)
707: {
708: PetscBool is_mffd = PETSC_FALSE;
709: PetscBool3 is_fdpossible = PETSC_BOOL3_UNKNOWN;
711: PetscFunctionBegin;
714: PetscCheckSameComm(term, 1, x, 2);
715: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_NONE || params == NULL, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters passed to a TaoTerm with TAOTERM_PARAMETERS_NONE");
716: PetscCheck(term->parameters_mode != TAOTERM_PARAMETERS_REQUIRED || params, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "Parameters required but not provided for a TaoTerm with TAOTERM_PARAMETERS_REQUIRED");
717: if (params) {
719: PetscCheckSameComm(term, 1, params, 3);
720: PetscCall(VecLockReadPush(params));
721: }
722: PetscCall(VecLockReadPush(x));
723: if (H) {
725: PetscCheckSameComm(term, 1, H, 4);
726: }
727: if (Hpre) {
729: PetscCheckSameComm(term, 1, Hpre, 5);
730: }
731: if (H) PetscCall(PetscObjectTypeCompare((PetscObject)H, MATMFFD, &is_mffd));
732: PetscCall(TaoTermIsComputeHessianFDPossible(term, &is_fdpossible));
733: PetscCall(PetscLogEventBegin(TAOTERM_HessianEval, term, NULL, NULL, NULL));
734: if (is_fdpossible == PETSC_BOOL3_FALSE) {
735: PetscUseTypeMethod(term, hessian, x, params, H, Hpre);
736: } else if (term->fd_hessian) {
737: if (is_fdpossible == PETSC_BOOL3_UNKNOWN) PetscCall(PetscInfo(term, "%s: Whether TaoTermComputeHessianFD is possible is unknown. Trying anyway.\n", ((PetscObject)term)->prefix));
738: PetscCall(TaoTermComputeHessianFD(term, x, params, H, Hpre));
739: } else if (is_mffd) {
740: if (is_fdpossible == PETSC_BOOL3_UNKNOWN) PetscCall(PetscInfo(term, "%s: Whether TaoTermComputeHessianMFFD is possible is unknown. Trying anyway.\n", ((PetscObject)term)->prefix));
741: PetscCall(TaoTermComputeHessianMFFD(term, x, params, H, Hpre));
742: } else {
743: if (term->ops->hessian) PetscUseTypeMethod(term, hessian, x, params, H, Hpre);
744: else
745: SETERRQ(PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "TaoTerm does not have TaoTermComputeHessian routine, and cannot use finite differences for Hessian computation. Either set Hessian MatType to MATMFFD, or call TaoTermComputeHessianSetUseFD()");
746: }
747: PetscCall(PetscLogEventEnd(TAOTERM_HessianEval, term, NULL, NULL, NULL));
748: term->nhess++;
749: if (params) PetscCall(VecLockReadPop(params));
750: PetscCall(VecLockReadPop(x));
751: PetscFunctionReturn(PETSC_SUCCESS);
752: }
754: /*@
755: TaoTermIsComputeHessianFDPossible - Whether this term can compute Hessian with finite differences
756: with either `-tao_term_hessian_use_fd`, `TaoTermComputeHessianSetUseFD()`, or `MATMFFD`.
758: Not collective
760: Input Parameter:
761: . term - a `TaoTerm`
763: Output Parameter:
764: . is_fdpossible - whether Hessian computation with finite differences is possible
766: Level: developer
768: .seealso: [](sec_tao_term),
769: `TaoTerm`,
770: `TaoTermComputeObjective()`,
771: `TaoTermShellSetObjective()`,
772: `TaoTermIsGradientDefined()`,
773: `TaoTermIsObjectiveAndGradientDefined()`,
774: `TaoTermIsHessianDefined()`
775: @*/
776: PetscErrorCode TaoTermIsComputeHessianFDPossible(TaoTerm term, PetscBool3 *is_fdpossible)
777: {
778: PetscFunctionBegin;
780: PetscAssertPointer(is_fdpossible, 2);
781: if (term->ops->iscomputehessianfdpossible) PetscUseTypeMethod(term, iscomputehessianfdpossible, is_fdpossible);
782: else *is_fdpossible = PETSC_BOOL3_UNKNOWN;
783: PetscFunctionReturn(PETSC_SUCCESS);
784: }
786: /*@
787: TaoTermIsObjectiveDefined - Whether a standalone objective operation is defined for this `TaoTerm`
789: Not collective
791: Input Parameter:
792: . term - a `TaoTerm`
794: Output Parameter:
795: . is_defined - whether the objective is defined
797: Note:
798: This function strictly checks whether a dedicated objective operation is defined. It does not check whether the
799: objective could be computed via other operations (e.g., an objective-and-gradient callback). `TaoTermComputeObjective()`
800: may still succeed even if this function returns `PETSC_FALSE`, by falling back to `TaoTermComputeObjectiveAndGradient()`.
802: Level: developer
804: .seealso: [](sec_tao_term),
805: `TaoTerm`,
806: `TaoTermComputeObjective()`,
807: `TaoTermShellSetObjective()`,
808: `TaoTermIsGradientDefined()`,
809: `TaoTermIsObjectiveAndGradientDefined()`,
810: `TaoTermIsHessianDefined()`
811: @*/
812: PetscErrorCode TaoTermIsObjectiveDefined(TaoTerm term, PetscBool *is_defined)
813: {
814: PetscFunctionBegin;
816: PetscAssertPointer(is_defined, 2);
817: if (term->ops->isobjectivedefined) PetscUseTypeMethod(term, isobjectivedefined, is_defined);
818: else *is_defined = (term->ops->objective != NULL) ? PETSC_TRUE : PETSC_FALSE;
819: PetscFunctionReturn(PETSC_SUCCESS);
820: }
822: /*@
823: TaoTermIsGradientDefined - Whether a standalone gradient operation is defined for this `TaoTerm`
825: Not collective
827: Input Parameter:
828: . term - a `TaoTerm`
830: Output Parameter:
831: . is_defined - whether the gradient is defined
833: Note:
834: This function strictly checks whether a dedicated gradient operation is defined. It does not check whether the
835: gradient could be computed via other operations (e.g., an objective-and-gradient callback or finite differences).
836: `TaoTermComputeGradient()` may still succeed even if this function returns `PETSC_FALSE`, by falling back to
837: `TaoTermComputeObjectiveAndGradient()` or finite-difference approximation.
839: Level: developer
841: .seealso: [](sec_tao_term),
842: `TaoTerm`,
843: `TaoTermComputeGradient()`,
844: `TaoTermShellSetGradient()`,
845: `TaoTermIsObjectiveDefined()`,
846: `TaoTermIsObjectiveAndGradientDefined()`,
847: `TaoTermIsHessianDefined()`
848: @*/
849: PetscErrorCode TaoTermIsGradientDefined(TaoTerm term, PetscBool *is_defined)
850: {
851: PetscFunctionBegin;
853: PetscAssertPointer(is_defined, 2);
854: if (term->ops->isgradientdefined) PetscUseTypeMethod(term, isgradientdefined, is_defined);
855: else *is_defined = (term->ops->gradient != NULL) ? PETSC_TRUE : PETSC_FALSE;
856: PetscFunctionReturn(PETSC_SUCCESS);
857: }
859: /*@
860: TaoTermIsObjectiveAndGradientDefined - Whether a combined objective-and-gradient operation is defined for this `TaoTerm`
862: Not collective
864: Input Parameter:
865: . term - a `TaoTerm`
867: Output Parameter:
868: . is_defined - whether the objective/gradient is defined
870: Note:
871: This function strictly checks whether a dedicated combined objective-and-gradient operation is defined. It does not
872: check whether the objective and gradient could be computed via separate objective and gradient operations.
873: `TaoTermComputeObjectiveAndGradient()` may still succeed even if this function returns `PETSC_FALSE`, by falling back
874: to separate `TaoTermComputeObjective()` and `TaoTermComputeGradient()` calls.
876: Level: developer
878: .seealso: [](sec_tao_term),
879: `TaoTerm`,
880: `TaoTermComputeObjectiveAndGradient()`,
881: `TaoTermShellSetObjectiveAndGradient()`,
882: `TaoTermIsObjectiveDefined()`,
883: `TaoTermIsGradientDefined()`,
884: `TaoTermIsHessianDefined()`
885: @*/
886: PetscErrorCode TaoTermIsObjectiveAndGradientDefined(TaoTerm term, PetscBool *is_defined)
887: {
888: PetscFunctionBegin;
890: PetscAssertPointer(is_defined, 2);
891: if (term->ops->isobjectiveandgradientdefined) PetscUseTypeMethod(term, isobjectiveandgradientdefined, is_defined);
892: else *is_defined = (term->ops->objectiveandgradient != NULL) ? PETSC_TRUE : PETSC_FALSE;
893: PetscFunctionReturn(PETSC_SUCCESS);
894: }
896: /*@
897: TaoTermIsHessianDefined - Whether a Hessian operation is defined for this `TaoTerm`
899: Not collective
901: Input Parameter:
902: . term - a `TaoTerm`
904: Output Parameter:
905: . is_defined - whether the Hessian is defined
907: Note:
908: This function strictly checks whether a dedicated Hessian operation is defined. It does not check whether the
909: Hessian could be computed via finite differences. `TaoTermComputeHessian()` may still succeed even if this function
910: returns `PETSC_FALSE`, if finite-difference Hessian computation has been enabled.
912: Level: developer
914: .seealso: [](sec_tao_term),
915: `TaoTerm`,
916: `TaoTermComputeHessian()`,
917: `TaoTermShellSetHessian()`,
918: `TaoTermIsObjectiveDefined()`,
919: `TaoTermIsGradientDefined()`,
920: `TaoTermIsObjectiveAndGradientDefined()`
921: @*/
922: PetscErrorCode TaoTermIsHessianDefined(TaoTerm term, PetscBool *is_defined)
923: {
924: PetscFunctionBegin;
926: PetscAssertPointer(is_defined, 2);
927: if (term->ops->ishessiandefined) PetscUseTypeMethod(term, ishessiandefined, is_defined);
928: else *is_defined = (term->ops->hessian != NULL) ? PETSC_TRUE : PETSC_FALSE;
929: PetscFunctionReturn(PETSC_SUCCESS);
930: }
932: /*@
933: TaoTermIsCreateHessianMatricesDefined - Whether this term can call `TaoTermCreateHessianMatrices()`.
935: Not collective
937: Input Parameter:
938: . term - a `TaoTerm`
940: Output Parameter:
941: . is_defined - whether the term can create new Hessian matrices
943: Level: developer
945: .seealso: [](sec_tao_term),
946: `TaoTerm`,
947: `TaoTermCreateHessianMatrices()`,
948: `TaoTermShellSetCreateHessianMatrices()`,
949: `TaoTermIsObjectiveDefined()`,
950: `TaoTermIsGradientDefined()`,
951: `TaoTermIsObjectiveAndGradientDefined()`,
952: `TaoTermIsHessianDefined()`
953: @*/
954: PetscErrorCode TaoTermIsCreateHessianMatricesDefined(TaoTerm term, PetscBool *is_defined)
955: {
956: PetscFunctionBegin;
958: PetscAssertPointer(is_defined, 2);
959: if (term->ops->iscreatehessianmatricesdefined) PetscUseTypeMethod(term, iscreatehessianmatricesdefined, is_defined);
960: else *is_defined = (term->ops->createhessianmatrices != NULL) ? PETSC_TRUE : PETSC_FALSE;
961: PetscFunctionReturn(PETSC_SUCCESS);
962: }
964: /*@
965: TaoTermSetSolutionSizes - Set the sizes describing the layout of the solution vector space of a `TaoTerm`.
967: Logically collective
969: Input Parameters:
970: + term - a `TaoTerm`
971: . n - the size of a solution vector on the current MPI process (or `PETSC_DECIDE`)
972: . N - the global size of a solution vector (or `PETSC_DECIDE`)
973: - bs - the block size of a solution vector (must be >= 1)
975: Level: beginner
977: Notes:
978: The "solution space" of a `TaoTerm` is the vector space of the optimization variable $x$ in
979: $f(x; p)$. This is distinct from the "parameter space" (the space of the fixed data $p$, set
980: with `TaoTermSetParametersSizes()`). Some `TaoTermType`s require the solution and parameter
981: spaces to be related (e.g., have the same size); see the documentation for each type.
983: When a mapping matrix $A$ is used to add a term to a `Tao` via `TaoAddTerm()`, the mapping
984: transforms the `Tao` solution vector into this term's solution space. For example, if the
985: `Tao` solution vector is $x \in \mathbb{R}^n$ and the mapping matrix is $A \in \mathbb{R}^{m \times n}$,
986: then the term evaluates $f(Ax; p)$ with $Ax \in \mathbb{R}^m$. The term's solution space is
987: therefore $\mathbb{R}^m$, and `TaoTermView()` will report $N = m$ for this term.
989: Alternatively, one may use `TaoTermSetSolutionLayout()` or `TaoTermSetSolutionTemplate()` to define the vector sizes.
991: .seealso: [](sec_tao_term),
992: `TaoTerm`,
993: `TaoTermGetSolutionSizes()`,
994: `TaoTermSetSolutionTemplate()`,
995: `TaoTermGetSolutionVecType()`,
996: `TaoTermSetSolutionVecType()`,
997: `TaoTermGetSolutionLayout()`,
998: `TaoTermSetSolutionLayout()`,
999: `TaoTermCreateSolutionVec()`
1000: @*/
1001: PetscErrorCode TaoTermSetSolutionSizes(TaoTerm term, PetscInt n, PetscInt N, PetscInt bs)
1002: {
1003: PetscLayout layout;
1005: PetscFunctionBegin;
1007: PetscCall(MatGetLayouts(term->solution_factory, &layout, NULL));
1008: PetscCall(PetscLayoutSetLocalSize(layout, n));
1009: PetscCall(PetscLayoutSetSize(layout, N));
1010: PetscCall(PetscLayoutSetBlockSize(layout, bs));
1011: PetscFunctionReturn(PETSC_SUCCESS);
1012: }
1014: /*@
1015: TaoTermGetSolutionSizes - Get the sizes describing the layout of the solution vector space of a `TaoTerm`.
1017: Not collective
1019: Input Parameter:
1020: . term - a `TaoTerm`
1022: Output Parameters:
1023: + n - (optional) the size of a solution vector on the current MPI process
1024: . N - (optional) the global size of a solution vector
1025: - bs - (optional) the block size of a solution vector
1027: Level: beginner
1029: .seealso: [](sec_tao_term),
1030: `TaoTerm`,
1031: `TaoTermSetSolutionSizes()`,
1032: `TaoTermSetSolutionTemplate()`,
1033: `TaoTermGetSolutionVecType()`,
1034: `TaoTermSetSolutionVecType()`,
1035: `TaoTermGetSolutionLayout()`,
1036: `TaoTermSetSolutionLayout()`,
1037: `TaoTermCreateSolutionVec()`
1038: @*/
1039: PetscErrorCode TaoTermGetSolutionSizes(TaoTerm term, PetscInt *n, PetscInt *N, PetscInt *bs)
1040: {
1041: PetscFunctionBegin;
1043: if (n) PetscCall(MatGetLocalSize(term->solution_factory, n, NULL));
1044: if (N) PetscCall(MatGetSize(term->solution_factory, N, NULL));
1045: if (bs) PetscCall(MatGetBlockSizes(term->solution_factory, bs, NULL));
1046: PetscFunctionReturn(PETSC_SUCCESS);
1047: }
1049: /*@
1050: TaoTermSetParametersSizes - Set the sizes describing the layout of the parameter vector space of a `TaoTerm`.
1052: Logically collective
1054: Input Parameters:
1055: + term - a `TaoTerm`
1056: . k - the size of a parameter vector on the current MPI process (or `PETSC_DECIDE`)
1057: . K - the global size of a parameter vector (or `PETSC_DECIDE`)
1058: - bs - the block size of a parameter vector (must be >= 1)
1060: Level: beginner
1062: Notes:
1063: The "parameter space" of a `TaoTerm` is the vector space of the fixed data $p$ in $f(x; p)$.
1064: Parameters are not optimized over. This is distinct from the "solution space" (set with
1065: `TaoTermSetSolutionSizes()`), which is the space of the optimization variable $x$.
1066: Some `TaoTermType`s require the solution and parameter spaces to be related (e.g., have the same size);
1067: see the documentation for each type.
1069: Alternatively, one may use `TaoTermSetParametersLayout()` or `TaoTermSetParametersTemplate()` to define the vector sizes.
1071: .seealso: [](sec_tao_term),
1072: `TaoTerm`,
1073: `TaoTermGetParametersSizes()`,
1074: `TaoTermSetParametersTemplate()`,
1075: `TaoTermGetParametersVecType()`,
1076: `TaoTermSetParametersVecType()`,
1077: `TaoTermGetParametersLayout()`,
1078: `TaoTermSetParametersLayout()`,
1079: `TaoTermCreateParametersVec()`
1080: @*/
1081: PetscErrorCode TaoTermSetParametersSizes(TaoTerm term, PetscInt k, PetscInt K, PetscInt bs)
1082: {
1083: PetscLayout layout;
1085: PetscFunctionBegin;
1087: PetscCall(MatGetLayouts(term->parameters_factory, &layout, NULL));
1088: PetscCall(PetscLayoutSetLocalSize(layout, k));
1089: PetscCall(PetscLayoutSetSize(layout, K));
1090: PetscCall(PetscLayoutSetBlockSize(layout, bs));
1091: PetscFunctionReturn(PETSC_SUCCESS);
1092: }
1094: /*@
1095: TaoTermGetParametersSizes - Get the sizes describing the layout of the parameter vector space of a `TaoTerm`.
1097: Not collective
1099: Input Parameter:
1100: . term - a `TaoTerm`
1102: Output Parameters:
1103: + k - (optional) the size of a parameter vector on the current MPI process
1104: . K - (optional) the global size of a parameter vector
1105: - bs - (optional) the block size of a parameter vector
1107: Level: beginner
1109: .seealso: [](sec_tao_term),
1110: `TaoTerm`,
1111: `TaoTermSetParametersSizes()`,
1112: `TaoTermSetParametersTemplate()`,
1113: `TaoTermGetParametersVecType()`,
1114: `TaoTermSetParametersVecType()`,
1115: `TaoTermGetParametersLayout()`,
1116: `TaoTermSetParametersLayout()`,
1117: `TaoTermCreateParametersVec()`
1118: @*/
1119: PetscErrorCode TaoTermGetParametersSizes(TaoTerm term, PetscInt *k, PetscInt *K, PetscInt *bs)
1120: {
1121: PetscFunctionBegin;
1123: if (k) PetscCall(MatGetLocalSize(term->parameters_factory, k, NULL));
1124: if (K) PetscCall(MatGetSize(term->parameters_factory, K, NULL));
1125: if (bs) PetscCall(MatGetBlockSizes(term->parameters_factory, bs, NULL));
1126: PetscFunctionReturn(PETSC_SUCCESS);
1127: }
1129: /*@
1130: TaoTermSetParametersLayout - Set the layout describing the parameter vector of `TaoTerm`.
1132: Collective
1134: Input Parameters:
1135: + term - a `TaoTerm`
1136: - parameters_layout - the `PetscLayout` for the parameter space
1138: Level: intermediate
1140: Notes:
1141: The "parameter space" of a `TaoTerm` is the vector space of the fixed data $p$ in $f(x; p)$.
1142: Parameters are not optimized over. This is distinct from the "solution space" (set with
1143: `TaoTermSetSolutionSizes()`), which is the space of the optimization variable $x$.
1144: Some `TaoTermType`s require the solution and parameter spaces to be related (e.g., have the same size);
1145: see the documentation for each type.
1147: Alternatively, one may use `TaoTermSetParametersSizes()` or `TaoTermSetParametersTemplate()` to define the vector sizes.
1149: .seealso: [](sec_tao_term),
1150: `TaoTerm`,
1151: `TaoTermGetParametersVecType()`,
1152: `TaoTermSetParametersVecType()`,
1153: `TaoTermGetParametersLayout()`,
1154: `TaoTermSetSolutionTemplate()`,
1155: `TaoTermSetParametersTemplate()`,
1156: `TaoTermCreateParametersVec()`
1157: @*/
1158: PetscErrorCode TaoTermSetParametersLayout(TaoTerm term, PetscLayout parameters_layout)
1159: {
1160: PetscLayout rlayout, clayout;
1162: PetscFunctionBegin;
1164: PetscCall(MatGetLayouts(term->parameters_factory, &rlayout, &clayout));
1165: PetscCall(MatSetLayouts(term->parameters_factory, parameters_layout, clayout));
1166: PetscFunctionReturn(PETSC_SUCCESS);
1167: }
1169: /*@
1170: TaoTermGetParametersLayout - Get the layouts describing the parameter vectors of a `TaoTerm`.
1172: Not collective
1174: Input Parameter:
1175: . term - a `TaoTerm`
1177: Output Parameter:
1178: . parameters_layout - the `PetscLayout` for the parameter space
1180: Level: intermediate
1182: .seealso: [](sec_tao_term),
1183: `TaoTerm`,
1184: `TaoTermGetParametersVecType()`,
1185: `TaoTermSetParametersVecType()`,
1186: `TaoTermSetParametersLayout()`,
1187: `TaoTermSetSolutionTemplate()`,
1188: `TaoTermSetParametersTemplate()`,
1189: `TaoTermCreateParametersVec()`
1190: @*/
1191: PetscErrorCode TaoTermGetParametersLayout(TaoTerm term, PetscLayout *parameters_layout)
1192: {
1193: PetscFunctionBegin;
1195: PetscAssertPointer(parameters_layout, 2);
1196: PetscCall(MatGetLayouts(term->parameters_factory, parameters_layout, NULL));
1197: PetscFunctionReturn(PETSC_SUCCESS);
1198: }
1200: /*@
1201: TaoTermSetSolutionLayout - Set the layout describing the solution vector of `TaoTerm`.
1203: Collective
1205: Input Parameters:
1206: + term - a `TaoTerm`
1207: - solution_layout - the `PetscLayout` for the solution space
1209: Level: intermediate
1211: Notes:
1212: The "solution space" of a `TaoTerm` is the vector space of the optimization variable $x$ in
1213: $f(x; p)$. This is distinct from the "parameter space" (the space of the fixed data $p$, set
1214: with `TaoTermSetParametersSizes()`). Some `TaoTermType`s require the solution and parameter
1215: spaces to be related (e.g., have the same size); see the documentation for each type.
1217: When a mapping matrix $A$ is used to add a term to a `Tao` via `TaoAddTerm()`, the mapping
1218: transforms the `Tao` solution vector into this term's solution space. For example, if the
1219: `Tao` solution vector is $x \in \mathbb{R}^n$ and the mapping matrix is $A \in \mathbb{R}^{m \times n}$,
1220: then the term evaluates $f(Ax; p)$ with $Ax \in \mathbb{R}^m$. The term's solution space is
1221: therefore $\mathbb{R}^m$, and `TaoTermView()` will report $N = m$ for this term.
1223: Alternatively, one may use `TaoTermSetSolutionSizes()` or `TaoTermSetSolutionTemplate()` to define the vector sizes.
1225: .seealso: [](sec_tao_term),
1226: `TaoTerm`,
1227: `TaoTermGetSolutionVecType()`,
1228: `TaoTermSetSolutionVecType()`,
1229: `TaoTermGetSolutionLayout()`,
1230: `TaoTermSetSolutionTemplate()`,
1231: `TaoTermSetParametersTemplate()`,
1232: `TaoTermCreateSolutionVec()`
1233: @*/
1234: PetscErrorCode TaoTermSetSolutionLayout(TaoTerm term, PetscLayout solution_layout)
1235: {
1236: PetscLayout rlayout, clayout;
1238: PetscFunctionBegin;
1240: PetscCall(MatGetLayouts(term->solution_factory, &rlayout, &clayout));
1241: PetscCall(MatSetLayouts(term->solution_factory, solution_layout, clayout));
1242: PetscFunctionReturn(PETSC_SUCCESS);
1243: }
1245: /*@
1246: TaoTermGetSolutionLayout - Get the layouts describing the solution vectors of a `TaoTerm`.
1248: Not collective
1250: Input Parameter:
1251: . term - a `TaoTerm`
1253: Output Parameter:
1254: . solution_layout - the `PetscLayout` for the solution space
1256: Level: intermediate
1258: .seealso: [](sec_tao_term),
1259: `TaoTerm`,
1260: `TaoTermGetSolutionVecType()`,
1261: `TaoTermSetSolutionVecType()`,
1262: `TaoTermSetSolutionLayout()`,
1263: `TaoTermSetSolutionTemplate()`,
1264: `TaoTermSetParametersTemplate()`,
1265: `TaoTermCreateSolutionVec()`
1266: @*/
1267: PetscErrorCode TaoTermGetSolutionLayout(TaoTerm term, PetscLayout *solution_layout)
1268: {
1269: PetscFunctionBegin;
1271: PetscAssertPointer(solution_layout, 2);
1272: PetscCall(MatGetLayouts(term->solution_factory, solution_layout, NULL));
1273: PetscFunctionReturn(PETSC_SUCCESS);
1274: }
1276: /*@
1277: TaoTermSetSolutionTemplate - Set the solution vector space to match a template vector
1279: Collective
1281: Input Parameters:
1282: + term - a `TaoTerm`
1283: - sol_template - a vector with the desired size, layout, and `VecType` of solution vectors for `TaoTerm`
1285: Level: intermediate
1287: Notes:
1288: The "solution space" of a `TaoTerm` is the vector space of the optimization variable $x$ in
1289: $f(x; p)$. This is distinct from the "parameter space" (the space of the fixed data $p$, set
1290: with `TaoTermSetParametersSizes()`). Some `TaoTermType`s require the solution and parameter
1291: spaces to be related (e.g., have the same size); see the documentation for each type.
1293: When a mapping matrix $A$ is used to add a term to a `Tao` via `TaoAddTerm()`, the mapping
1294: transforms the `Tao` solution vector into this term's solution space. For example, if the
1295: `Tao` solution vector is $x \in \mathbb{R}^n$ and the mapping matrix is $A \in \mathbb{R}^{m \times n}$,
1296: then the term evaluates $f(Ax; p)$ with $Ax \in \mathbb{R}^m$. The term's solution space is
1297: therefore $\mathbb{R}^m$, and `TaoTermView()` will report $N = m$ for this term.
1299: Alternatively, one may use `TaoTermSetSolutionSizes()` or `TaoTermSetSolutionLayout()` to define the vector sizes.
1301: .seealso: [](sec_tao_term),
1302: `TaoTerm`,
1303: `TaoTermGetSolutionVecType()`,
1304: `TaoTermSetSolutionVecType()`,
1305: `TaoTermSetParametersTemplate()`,
1306: `TaoTermGetSolutionLayout()`,
1307: `TaoTermSetSolutionLayout()`,
1308: `TaoTermCreateSolutionVec()`
1309: @*/
1310: PetscErrorCode TaoTermSetSolutionTemplate(TaoTerm term, Vec sol_template)
1311: {
1312: PetscLayout layout, clayout;
1313: VecType vec_type;
1315: PetscFunctionBegin;
1318: PetscCheckSameComm(term, 1, sol_template, 2);
1319: PetscCall(VecGetType(sol_template, &vec_type));
1320: PetscCall(VecGetLayout(sol_template, &layout));
1321: PetscCall(MatGetLayouts(term->solution_factory, NULL, &clayout));
1322: PetscCall(MatSetLayouts(term->solution_factory, layout, clayout));
1323: PetscCall(MatSetVecType(term->solution_factory, vec_type));
1324: PetscFunctionReturn(PETSC_SUCCESS);
1325: }
1327: /*@
1328: TaoTermSetParametersTemplate - Set the parameter vector space to match a template vector
1330: Collective
1332: Input Parameters:
1333: + term - a `TaoTerm`
1334: - params_template - a vector with the desired size, layout, and `VecType` of parameter vectors for `TaoTerm`
1336: Level: intermediate
1338: Notes:
1339: The "parameter space" of a `TaoTerm` is the vector space of the fixed data $p$ in $f(x; p)$.
1340: Parameters are not optimized over. This is distinct from the "solution space" (set with
1341: `TaoTermSetSolutionSizes()`), which is the space of the optimization variable $x$.
1342: Some `TaoTermType`s require the solution and parameter spaces to be related (e.g., have the same size);
1343: see the documentation for each type.
1345: Alternatively, one may use `TaoTermSetParametersSizes()` or `TaoTermSetParametersLayout()` to define the vector sizes.
1347: .seealso: [](sec_tao_term),
1348: `TaoTerm`,
1349: `TaoTermGetParametersVecType()`,
1350: `TaoTermSetParametersVecType()`,
1351: `TaoTermSetSolutionTemplate()`,
1352: `TaoTermGetParametersLayout()`,
1353: `TaoTermSetParametersLayout()`,
1354: `TaoTermCreateSolutionVec()`
1355: @*/
1356: PetscErrorCode TaoTermSetParametersTemplate(TaoTerm term, Vec params_template)
1357: {
1358: PetscLayout layout, clayout;
1359: VecType vec_type;
1361: PetscFunctionBegin;
1364: PetscCheckSameComm(term, 1, params_template, 2);
1365: PetscCall(VecGetType(params_template, &vec_type));
1366: PetscCall(VecGetLayout(params_template, &layout));
1367: PetscCall(MatGetLayouts(term->parameters_factory, NULL, &clayout));
1368: PetscCall(MatSetLayouts(term->parameters_factory, layout, clayout));
1369: PetscCall(MatSetVecType(term->parameters_factory, vec_type));
1370: PetscFunctionReturn(PETSC_SUCCESS);
1371: }
1373: /*@
1374: TaoTermSetSolutionVecType - Set the vector types of the solution vector of a `TaoTerm`
1376: Logically collective
1378: Input Parameters:
1379: + term - a `TaoTerm`
1380: - solution_type - the `VecType` for the solution space
1382: Options Database Keys:
1383: . -tao_term_solution_vec_type <type> - `VecType` for complete list of vector types
1385: Level: advanced
1387: .seealso: [](sec_tao_term),
1388: `TaoTerm`,
1389: `TaoTermGetSolutionVecType()`,
1390: `TaoTermSetSolutionLayout()`,
1391: `TaoTermGetSolutionLayout()`,
1392: `TaoTermSetSolutionTemplate()`,
1393: `TaoTermSetParametersTemplate()`,
1394: `TaoTermCreateSolutionVec()`
1395: @*/
1396: PetscErrorCode TaoTermSetSolutionVecType(TaoTerm term, VecType solution_type)
1397: {
1398: PetscFunctionBegin;
1400: if (solution_type) PetscCall(MatSetVecType(term->solution_factory, solution_type));
1401: PetscFunctionReturn(PETSC_SUCCESS);
1402: }
1404: /*@
1405: TaoTermSetParametersVecType - Set the vector types of the parameters vector of a `TaoTerm`
1407: Logically collective
1409: Input Parameters:
1410: + term - a `TaoTerm`
1411: - parameters_type - the `VecType` for the parameters space
1413: Options Database Keys:
1414: . -tao_term_parameters_vec_type <type> - `VecType` for complete list of vector types
1416: Level: advanced
1418: .seealso: [](sec_tao_term),
1419: `TaoTerm`,
1420: `TaoTermGetParametersVecType()`,
1421: `TaoTermSetParametersLayout()`,
1422: `TaoTermGetParametersLayout()`,
1423: `TaoTermSetParametersTemplate()`,
1424: `TaoTermCreateParametersVec()`
1425: @*/
1426: PetscErrorCode TaoTermSetParametersVecType(TaoTerm term, VecType parameters_type)
1427: {
1428: PetscFunctionBegin;
1430: if (parameters_type) PetscCall(MatSetVecType(term->parameters_factory, parameters_type));
1431: PetscFunctionReturn(PETSC_SUCCESS);
1432: }
1434: /*@
1435: TaoTermGetSolutionVecType - Get the vector types of the solution vector of a `TaoTerm`
1437: Not collective
1439: Input Parameter:
1440: . term - a `TaoTerm`
1442: Output Parameter:
1443: . solution_type - the `VecType` for the solution space
1445: Level: advanced
1447: .seealso: [](sec_tao_term),
1448: `TaoTerm`,
1449: `TaoTermSetSolutionVecType()`,
1450: `TaoTermGetSolutionLayout()`,
1451: `TaoTermSetSolutionLayout()`,
1452: `TaoTermSetSolutionTemplate()`,
1453: `TaoTermSetParametersTemplate()`,
1454: `TaoTermCreateSolutionVec()`
1455: @*/
1456: PetscErrorCode TaoTermGetSolutionVecType(TaoTerm term, VecType *solution_type)
1457: {
1458: PetscFunctionBegin;
1460: PetscAssertPointer(solution_type, 2);
1461: PetscCall(MatGetVecType(term->solution_factory, solution_type));
1462: PetscFunctionReturn(PETSC_SUCCESS);
1463: }
1465: /*@
1466: TaoTermGetParametersVecType - Get the vector types of the parameter vector of a `TaoTerm`
1468: Not collective
1470: Input Parameter:
1471: . term - a `TaoTerm`
1473: Output Parameter:
1474: . parameters_type - the `VecType` for the parameter space
1476: Level: advanced
1478: .seealso: [](sec_tao_term),
1479: `TaoTerm`,
1480: `TaoTermSetParametersVecType()`,
1481: `TaoTermGetParametersLayout()`,
1482: `TaoTermSetParametersLayout()`,
1483: `TaoTermSetSolutionTemplate()`,
1484: `TaoTermSetParametersTemplate()`,
1485: `TaoTermCreateParametersVec()`
1486: @*/
1487: PetscErrorCode TaoTermGetParametersVecType(TaoTerm term, VecType *parameters_type)
1488: {
1489: PetscFunctionBegin;
1491: PetscAssertPointer(parameters_type, 2);
1492: PetscCall(MatGetVecType(term->parameters_factory, parameters_type));
1493: PetscFunctionReturn(PETSC_SUCCESS);
1494: }
1496: /*@
1497: TaoTermCreateSolutionVec - Create a solution vector for a `TaoTerm`
1499: Collective
1501: Input Parameter:
1502: . term - a `TaoTerm`
1504: Output Parameter:
1505: . solution - a compatible solution vector for `term`
1507: Level: advanced
1509: Note:
1510: Before a `TaoTerm` can create a solution vector, you must do one of the following\:
1512: * Call `TaoTermSetSolutionSizes()` to describe the size and parallel layout of a solution vector.
1513: * Call `TaoTermSetSolutionLayout()` to directly set `PetscLayout`s for the solution vector.
1514: * Call `TaoTermSetSolutionTemplate()` to set the solution vector spaces to match existing `Vec`.
1515: * If the `TaoTerm` is a `TAOTERMSHELL`, you can call `TaoTermShellSetCreateSolutionVec()` to use
1516: your own code for creating vectors.
1518: You can also call `TaoTermSetSolutionVecType()` to set the type of vector created (e.g. `VECCUDA`).
1520: .seealso: [](sec_tao_term),
1521: `TaoTerm`,
1522: `TaoTermShellSetCreateSolutionVec()`,
1523: `TaoTermGetSolutionSizes()`,
1524: `TaoTermSetSolutionSizes()`,
1525: `TaoTermSetSolutionTemplate()`,
1526: `TaoTermGetSolutionVecType()`,
1527: `TaoTermSetSolutionVecType()`,
1528: `TaoTermGetSolutionLayout()`,
1529: `TaoTermSetSolutionLayout()`,
1530: `TaoTermCreateHessianMatrices()`
1531: @*/
1532: PetscErrorCode TaoTermCreateSolutionVec(TaoTerm term, Vec *solution)
1533: {
1534: PetscFunctionBegin;
1536: PetscAssertPointer(solution, 2);
1537: if (term->ops->createsolutionvec) {
1538: PetscUseTypeMethod(term, createsolutionvec, solution);
1539: } else {
1540: PetscCall(MatCreateVecs(term->solution_factory, NULL, solution));
1541: }
1542: PetscFunctionReturn(PETSC_SUCCESS);
1543: }
1545: /*@
1546: TaoTermCreateParametersVec - Create a parameter vector for a `TaoTerm`
1548: Collective
1550: Input Parameter:
1551: . term - a `TaoTerm`
1553: Output Parameter:
1554: . parameters - a compatible parameter vector for `term`
1556: Level: advanced
1558: Notes:
1559: Before a `TaoTerm` can create a parameter vector, you must do one of the following\:
1561: * Call `TaoTermSetParametersSizes()` to describe the size and parallel layout of a parameters vector.
1562: * Call `TaoTermSetParametersLayout()` to directly set `PetscLayout`s for the parameters vector.
1563: * Call `TaoTermSetParametersTemplate()` to set the parameters vector spaces to match existing `Vec`.
1564: * If the `TaoTerm` is a `TAOTERMSHELL`, you can call `TaoTermShellSetCreateParametersVec()` to use your
1565: own code for creating vectors.
1567: You can also call `TaoTermSetParametersVecType()` to set the type of vector created (e.g. `VECCUDA`).
1569: .seealso: [](sec_tao_term),
1570: `TaoTerm`,
1571: `TaoTermShellSetCreateParametersVec()`,
1572: `TaoTermGetParametersSizes()`,
1573: `TaoTermSetParametersSizes()`,
1574: `TaoTermSetParametersTemplate()`,
1575: `TaoTermGetParametersVecType()`,
1576: `TaoTermSetParametersVecType()`,
1577: `TaoTermGetParametersLayout()`,
1578: `TaoTermSetParametersLayout()`,
1579: `TaoTermCreateHessianMatrices()`
1580: @*/
1581: PetscErrorCode TaoTermCreateParametersVec(TaoTerm term, Vec *parameters)
1582: {
1583: PetscFunctionBegin;
1585: PetscAssertPointer(parameters, 2);
1586: if (term->ops->createparametersvec) {
1587: PetscUseTypeMethod(term, createparametersvec, parameters);
1588: } else {
1589: PetscCall(MatCreateVecs(term->parameters_factory, NULL, parameters));
1590: }
1591: PetscFunctionReturn(PETSC_SUCCESS);
1592: }
1594: /*@
1595: TaoTermCreateHessianMatrices - Create the matrices that can be inputs to `TaoTermComputeHessian()`
1597: Collective
1599: Input Parameter:
1600: . term - a `TaoTerm`
1602: Output Parameters:
1603: + H - (optional) a matrix that can store the Hessian computed in `TaoTermComputeHessian()`
1604: - Hpre - (optional) a matrix from which a preconditioner can be computed in `TaoTermComputeHessian()`
1606: Level: advanced
1608: Note:
1609: Before Hessian matrices can be created, the size of the solution vector space
1610: must be set (see the ways this can be done in `TaoTermCreateSolutionVec()`). If the
1611: term is a `TAOTERMSHELL`, `TaoTermShellSetCreateHessianMatrices()` must be
1612: called. Most `TaoTerm`s use `TaoTermCreateHessianMatricesDefault()` to create
1613: their Hessian matrices: the behavior of that function can be controlled by
1614: `TaoTermSetCreateHessianMode()`.
1616: .seealso: [](sec_tao_term),
1617: `TaoTerm`,
1618: `TaoTermComputeHessian()`,
1619: `TaoTermShellSetCreateHessianMatrices()`,
1620: `TaoTermCreateSolutionVec()`,
1621: `TaoTermCreateHessianMatricesDefault()`,
1622: `TaoTermGetCreateHessianMode()`,
1623: `TaoTermSetCreateHessianMode()`,
1624: `TaoTermIsCreateHessianMatricesDefined()`
1625: @*/
1626: PetscErrorCode TaoTermCreateHessianMatrices(TaoTerm term, Mat *H, Mat *Hpre)
1627: {
1628: PetscFunctionBegin;
1630: if (H) PetscAssertPointer(H, 2);
1631: if (Hpre) PetscAssertPointer(Hpre, 3);
1632: PetscUseTypeMethod(term, createhessianmatrices, H, Hpre);
1633: PetscFunctionReturn(PETSC_SUCCESS);
1634: }
1636: /*@
1637: TaoTermCreateHessianMatricesDefault - Default routine for creating Hessian matrices that can be used by many `TaoTerm` implementations
1639: Collective
1641: Input Parameter:
1642: . term - a `TaoTerm`
1644: Output Parameters:
1645: + H - (optional) a matrix that can store the Hessian computed in `TaoTermComputeHessian()`
1646: - Hpre - (optional) a matrix from which a preconditioner can be computed in `TaoTermComputeHessian()`
1648: Level: developer
1650: Developer Note:
1651: The behavior of this routine is determined by `TaoTermSetCreateHessianMode()`.
1652: If `Hpre_is_H`, then the same matrix will be returned for `H` and `Hpre`,
1653: otherwise they will be separate matrices, with the matrix types `H_mattype` and `Hpre_mattype`.
1654: If either type is `MATMFFD`, then it will create a shell matrix with `TaoTermCreateHessianMFFD()`.
1656: .seealso: [](sec_tao_term),
1657: `TaoTerm`,
1658: `TaoTermComputeHessian()`,
1659: `TaoTermCreateHessianMatrices()`,
1660: `TaoTermGetCreateHessianMode()`,
1661: `TaoTermSetCreateHessianMode()`
1662: @*/
1663: PetscErrorCode TaoTermCreateHessianMatricesDefault(TaoTerm term, Mat *H, Mat *Hpre)
1664: {
1665: PetscBool Hpre_is_H;
1666: MatType H_mattype;
1667: MatType Hpre_mattype;
1669: PetscFunctionBegin;
1671: PetscCall(TaoTermGetCreateHessianMode(term, &Hpre_is_H, &H_mattype, &Hpre_mattype));
1673: if (H || (Hpre && Hpre_is_H)) PetscCall(TaoTermCreateHessianMatricesDefault_H_Internal(term, H, Hpre, Hpre_is_H, H_mattype));
1674: if (Hpre && !Hpre_is_H) PetscCall(TaoTermCreateHessianMatricesDefault_Hpre_Internal(term, H, Hpre, Hpre_is_H, Hpre_mattype));
1675: PetscFunctionReturn(PETSC_SUCCESS);
1676: }
1678: /*@
1679: TaoTermSetCreateHessianMode - Determine the behavior of `TaoTermCreateHessianMatricesDefault()`.
1681: Logically collective
1683: Input Parameters:
1684: + term - a `TaoTerm`
1685: . Hpre_is_H - should `TaoTermCreateHessianMatricesDefault()` make one matrix for `H` and `Hpre`?
1686: . H_mattype - the `MatType` to create for `H`
1687: - Hpre_mattype - the `MatType` to create for `Hpre`
1689: Options Database Keys:
1690: + -tao_term_hessian_pre_is_hessian <bool> - Whether `TaoTermCreateHessianMatrices()` should make a separate matrix for constructing the preconditioner
1691: . -tao_term_hessian_mat_type <type> - `MatType` for Hessian matrix created by `TaoTermCreateHessianMatrices()`
1692: - -tao_term_hessian_pre_mat_type <type> - `MatType` for matrix from which a preconditioner can be created by `TaoTermCreateHessianMatrices()`
1694: Level: developer
1696: .seealso: [](sec_tao_term),
1697: `TaoTerm`,
1698: `TaoTermComputeHessian()`,
1699: `TaoTermCreateHessianMatrices()`,
1700: `TaoTermCreateHessianMatricesDefault()`,
1701: `TaoTermGetCreateHessianMode()`
1702: @*/
1703: PetscErrorCode TaoTermSetCreateHessianMode(TaoTerm term, PetscBool Hpre_is_H, MatType H_mattype, MatType Hpre_mattype)
1704: {
1705: PetscBool is_hsame, is_hpresame;
1707: PetscFunctionBegin;
1709: term->Hpre_is_H = Hpre_is_H;
1710: PetscCall(PetscStrcmp(term->H_mattype, H_mattype, &is_hsame));
1711: PetscCall(PetscStrcmp(term->Hpre_mattype, Hpre_mattype, &is_hpresame));
1712: if (!is_hsame) {
1713: PetscCall(PetscFree(term->H_mattype));
1714: if (H_mattype) PetscCall(PetscStrallocpy(H_mattype, (char **)&term->H_mattype));
1715: }
1716: if (!is_hpresame) {
1717: PetscCall(PetscFree(term->Hpre_mattype));
1718: if (Hpre_mattype) PetscCall(PetscStrallocpy(Hpre_mattype, (char **)&term->Hpre_mattype));
1719: }
1720: PetscFunctionReturn(PETSC_SUCCESS);
1721: }
1723: /*@
1724: TaoTermGetCreateHessianMode - Get the behavior of `TaoTermCreateHessianMatricesDefault()`.
1726: Not collective
1728: Input Parameter:
1729: . term - a `TaoTerm`
1731: Output Parameters:
1732: + Hpre_is_H - (optional) should `TaoTermCreateHessianMatricesDefault()` make one matrix for `H` and `Hpre`?
1733: . H_mattype - (optional) the `MatType` to create for `H`
1734: - Hpre_mattype - (optional) the `MatType` to create for `Hpre`
1736: Level: developer
1738: .seealso: [](sec_tao_term),
1739: `TaoTerm`,
1740: `TaoTermComputeHessian()`,
1741: `TaoTermCreateHessianMatrices()`,
1742: `TaoTermCreateHessianMatricesDefault()`,
1743: `TaoTermSetCreateHessianMode()`
1744: @*/
1745: PetscErrorCode TaoTermGetCreateHessianMode(TaoTerm term, PetscBool *Hpre_is_H, MatType *H_mattype, MatType *Hpre_mattype)
1746: {
1747: PetscFunctionBegin;
1749: if (Hpre_is_H) *Hpre_is_H = term->Hpre_is_H;
1750: if (H_mattype) *H_mattype = term->fd_hessian ? MATAIJ : term->H_mattype;
1751: if (Hpre_mattype) *Hpre_mattype = term->fd_hessian ? MATAIJ : term->Hpre_mattype;
1752: PetscFunctionReturn(PETSC_SUCCESS);
1753: }
1755: /*@
1756: TaoTermDuplicate - Duplicate a `TaoTerm`
1758: Collective
1760: Input Parameters:
1761: + term - a `TaoTerm`
1762: - opt - `TAOTERM_DUPLICATE_SIZEONLY` or `TAOTERM_DUPLICATE_TYPE`
1764: Output Parameter:
1765: . newterm - the duplicate `TaoTerm`
1767: Notes:
1768: This function duplicates the solution space layout and vector type, but does not duplicate
1769: parameters-related configuration such as the parameters layout, `TaoTermParametersMode`,
1770: Hessian matrix types, or finite-difference settings. These must be set separately on the
1771: new `TaoTerm` if needed.
1773: If `TAOTERM_DUPLICATE_SIZEONLY` is used, then the duplicated term must have proper `TaoTermType`
1774: set with `TaoTermSetType()`.
1776: Level: intermediate
1778: .seealso: [](sec_tao_term),
1779: `TaoTerm`,
1780: `TaoTermDuplicateOption`
1781: @*/
1782: PetscErrorCode TaoTermDuplicate(TaoTerm term, TaoTermDuplicateOption opt, TaoTerm *newterm)
1783: {
1784: VecType solution_vec_type;
1785: PetscLayout rlayout, clayout;
1786: PetscBool is_shell;
1788: PetscFunctionBegin;
1790: PetscAssertPointer(newterm, 3);
1791: PetscCall(TaoTermCreate(PetscObjectComm((PetscObject)term), newterm));
1792: PetscCall(PetscObjectTypeCompare((PetscObject)term, TAOTERMSHELL, &is_shell));
1793: // Check if createsolutionvec is available first (for TaoTermShell)
1794: if (is_shell && term->ops->createsolutionvec) {
1795: Vec sol_template;
1797: PetscCall(TaoTermCreateSolutionVec(term, &sol_template));
1798: PetscCall(TaoTermSetSolutionTemplate(*newterm, sol_template));
1799: PetscCall(VecDestroy(&sol_template));
1800: } else {
1801: PetscCall(MatGetVecType(term->solution_factory, &solution_vec_type));
1802: PetscCall(MatGetLayouts(term->solution_factory, &rlayout, &clayout));
1803: PetscCall(MatSetVecType((*newterm)->solution_factory, solution_vec_type));
1804: PetscCall(MatSetLayouts((*newterm)->solution_factory, rlayout, clayout));
1805: }
1806: if (opt == TAOTERM_DUPLICATE_TYPE) {
1807: TaoTermType type;
1809: PetscCall(TaoTermGetType(term, &type));
1810: PetscCall(TaoTermSetType(*newterm, type));
1811: }
1812: PetscFunctionReturn(PETSC_SUCCESS);
1813: }
1815: /*@
1816: TaoTermSetParametersMode - Sets the way a `TaoTerm` can accept parameters
1818: Logically collective
1820: Input Parameters:
1821: + term - a `TaoTerm`
1822: - parameters_mode - `TAOTERM_PARAMETERS_OPTIONAL`, `TAOTERM_PARAMETERS_NONE`, `TAOTERM_PARAMETERS_REQUIRED`
1824: Options Database Keys:
1825: . -tao_term_parameters_mode <optional,none,required> - `TAOTERM_PARAMETERS_OPTIONAL`, `TAOTERM_PARAMETERS_NONE`, `TAOTERM_PARAMETERS_REQUIRED`
1827: Level: advanced
1829: .seealso: [](sec_tao_term),
1830: `TaoTerm`,
1831: `TaoTermParametersMode`,
1832: `TaoTermGetParametersMode()`
1833: @*/
1834: PetscErrorCode TaoTermSetParametersMode(TaoTerm term, TaoTermParametersMode parameters_mode)
1835: {
1836: PetscFunctionBegin;
1839: term->parameters_mode = parameters_mode;
1840: PetscFunctionReturn(PETSC_SUCCESS);
1841: }
1843: /*@
1844: TaoTermGetParametersMode - Gets the way a `TaoTerm` can accept parameters
1846: Not collective
1848: Input Parameter:
1849: . term - a `TaoTerm`
1851: Output Parameter:
1852: . parameters_mode - `TAOTERM_PARAMETERS_OPTIONAL`, `TAOTERM_PARAMETERS_NONE`, `TAOTERM_PARAMETERS_REQUIRED`
1854: Level: intermediate
1856: .seealso: [](sec_tao_term),
1857: `TaoTerm`,
1858: `TaoTermParametersMode`,
1859: `TaoTermSetParametersMode()`
1860: @*/
1861: PetscErrorCode TaoTermGetParametersMode(TaoTerm term, TaoTermParametersMode *parameters_mode)
1862: {
1863: PetscFunctionBegin;
1865: PetscAssertPointer(parameters_mode, 2);
1866: *parameters_mode = term->parameters_mode;
1867: PetscFunctionReturn(PETSC_SUCCESS);
1868: }
1870: /*@
1871: TaoTermGetFDDelta - Get the increment used for finite difference derivative approximations in methods like `TaoTermComputeGradientFD()`
1873: Not collective
1875: Input Parameter:
1876: . term - a `TaoTerm`
1878: Output Parameter:
1879: . delta - the finite difference increment
1881: Options Database Key:
1882: . -tao_term_fd_delta <delta> - the above increment
1884: Level: advanced
1886: .seealso: [](sec_tao_term),
1887: `TaoTerm`,
1888: `TaoTermSetFDDelta()`,
1889: `TaoTermComputeGradientFD()`,
1890: `TaoTermComputeGradientSetUseFD()`,
1891: `TaoTermComputeGradientGetUseFD()`
1892: @*/
1893: PetscErrorCode TaoTermGetFDDelta(TaoTerm term, PetscReal *delta)
1894: {
1895: PetscFunctionBegin;
1897: PetscAssertPointer(delta, 2);
1898: *delta = term->fd_delta;
1899: PetscFunctionReturn(PETSC_SUCCESS);
1900: }
1902: /*@
1903: TaoTermSetFDDelta - Set the increment used for finite difference derivative approximations in methods like `TaoTermComputeGradientFD()`
1905: Logically collective
1907: Input Parameters:
1908: + term - a `TaoTerm`
1909: - delta - the finite difference increment
1911: Options Database Key:
1912: . -tao_term_fd_delta <delta> - the above increment
1914: Level: advanced
1916: .seealso: [](sec_tao_term),
1917: `TaoTerm`,
1918: `TaoTermGetFDDelta()`,
1919: `TaoTermComputeGradientFD()`,
1920: `TaoTermComputeGradientSetUseFD()`,
1921: `TaoTermComputeGradientGetUseFD()`,
1922: `TaoTermComputeHessianFD()`,
1923: `TaoTermComputeHessianSetUseFD()`,
1924: `TaoTermComputeHessianGetUseFD()`
1925: @*/
1926: PetscErrorCode TaoTermSetFDDelta(TaoTerm term, PetscReal delta)
1927: {
1928: PetscFunctionBegin;
1931: PetscCheck(delta > 0.0, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_OUTOFRANGE, "finite difference increment must be positive");
1932: term->fd_delta = delta;
1933: PetscFunctionReturn(PETSC_SUCCESS);
1934: }
1936: /*@
1937: TaoTermComputeGradientSetUseFD - Set whether to use finite differences instead of the user-provided or built-in gradient method in `TaoTermComputeGradient()`.
1939: Logically collective
1941: Input Parameters:
1942: + term - a `TaoTerm`
1943: - use_fd - `PETSC_TRUE` to use finite differences, `PETSC_FALSE` to use the user-provided or built-in gradient method
1945: Options Database Keys:
1946: . -tao_term_gradient_use_fd <bool> - use finite differences for gradient computation
1948: Level: advanced
1950: .seealso: [](sec_tao_term),
1951: `TaoTerm`,
1952: `TaoTermGetFDDelta()`,
1953: `TaoTermSetFDDelta()`,
1954: `TaoTermComputeGradientFD()`,
1955: `TaoTermComputeGradientGetUseFD()`,
1956: `TaoTermComputeHessianFD()`,
1957: `TaoTermComputeHessianSetUseFD()`,
1958: `TaoTermComputeHessianGetUseFD()`
1959: @*/
1960: PetscErrorCode TaoTermComputeGradientSetUseFD(TaoTerm term, PetscBool use_fd)
1961: {
1962: PetscFunctionBegin;
1965: term->fd_gradient = use_fd;
1966: PetscFunctionReturn(PETSC_SUCCESS);
1967: }
1969: /*@
1970: TaoTermComputeGradientGetUseFD - Get whether finite differences are used in `TaoTermComputeGradient()`.
1972: Not collective
1974: Input Parameter:
1975: . term - a `TaoTerm`
1977: Output Parameter:
1978: . use_fd - `PETSC_TRUE` if finite differences are used
1980: Level: advanced
1982: .seealso: [](sec_tao_term),
1983: `TaoTerm`,
1984: `TaoTermGetFDDelta()`,
1985: `TaoTermSetFDDelta()`,
1986: `TaoTermComputeGradientFD()`,
1987: `TaoTermComputeGradientSetUseFD()`,
1988: `TaoTermComputeHessianFD()`,
1989: `TaoTermComputeHessianSetUseFD()`,
1990: `TaoTermComputeHessianGetUseFD()`
1991: @*/
1992: PetscErrorCode TaoTermComputeGradientGetUseFD(TaoTerm term, PetscBool *use_fd)
1993: {
1994: PetscFunctionBegin;
1996: PetscAssertPointer(use_fd, 2);
1997: *use_fd = term->fd_gradient;
1998: PetscFunctionReturn(PETSC_SUCCESS);
1999: }
2001: /*@
2002: TaoTermComputeHessianSetUseFD - Set whether to use finite differences instead of the user-provided or built-in methods in `TaoTermComputeHessian()`.
2004: Logically collective
2006: Input Parameters:
2007: + term - a `TaoTerm`
2008: - use_fd - `PETSC_TRUE` to use finite differences, `PETSC_FALSE` to use the user-provided or built-in Hessian method
2010: Options Database Keys:
2011: . -tao_term_hessian_use_fd <bool> - use finite differences for Hessian computation
2013: Level: advanced
2015: .seealso: [](sec_tao_term),
2016: `TaoTerm`,
2017: `TaoTermGetFDDelta()`,
2018: `TaoTermSetFDDelta()`,
2019: `TaoTermComputeGradientFD()`,
2020: `TaoTermComputeGradientSetUseFD()`,
2021: `TaoTermComputeGradientGetUseFD()`,
2022: `TaoTermComputeHessianFD()`,
2023: `TaoTermComputeHessianGetUseFD()`
2024: @*/
2025: PetscErrorCode TaoTermComputeHessianSetUseFD(TaoTerm term, PetscBool use_fd)
2026: {
2027: PetscFunctionBegin;
2030: term->fd_hessian = use_fd;
2031: PetscFunctionReturn(PETSC_SUCCESS);
2032: }
2034: /*@
2035: TaoTermComputeHessianGetUseFD - Get whether finite differences are used in `TaoTermComputeHessian()`.
2037: Not collective
2039: Input Parameter:
2040: . term - a `TaoTerm`
2042: Output Parameter:
2043: . use_fd - `PETSC_TRUE` if finite differences are used
2045: Level: advanced
2047: .seealso: [](sec_tao_term),
2048: `TaoTerm`,
2049: `TaoTermGetFDDelta()`,
2050: `TaoTermSetFDDelta()`,
2051: `TaoTermComputeGradientFD()`,
2052: `TaoTermComputeGradientSetUseFD()`,
2053: `TaoTermComputeGradientGetUseFD()`,
2054: `TaoTermComputeHessianFD()`,
2055: `TaoTermComputeHessianSetUseFD()`
2056: @*/
2057: PetscErrorCode TaoTermComputeHessianGetUseFD(TaoTerm term, PetscBool *use_fd)
2058: {
2059: PetscFunctionBegin;
2061: PetscAssertPointer(use_fd, 2);
2062: *use_fd = term->fd_hessian;
2063: PetscFunctionReturn(PETSC_SUCCESS);
2064: }