Actual source code: taosolver.c
1: #include <petsc/private/taoimpl.h>
2: #include <petsc/private/snesimpl.h>
3: #include <petsc/private/kspimpl.h>
4: #include <petscdmshell.h>
6: PetscBool TaoRegisterAllCalled = PETSC_FALSE;
7: PetscFunctionList TaoList = NULL;
9: PetscClassId TAO_CLASSID = 0;
11: PetscLogEvent TAO_Solve;
12: PetscLogEvent TAO_ResidualEval;
13: PetscLogEvent TAO_JacobianEval;
14: PetscLogEvent TAO_ConstraintsEval;
16: const char *const TaoSubsetTypes[] = {"subvec", "mask", "matrixfree", "TaoSubsetType", "TAO_SUBSET_", NULL};
18: struct _n_TaoMonitorDrawCtx {
19: PetscViewer viewer;
20: PetscInt howoften; /* when > 0 uses iteration % howoften, when negative only final solution plotted */
21: };
23: static PetscErrorCode KSPPreSolve_TAOEW_Private(KSP ksp, Vec b, Vec x, PetscCtx ctx)
24: {
25: Tao tao = (Tao)ctx;
26: SNES snes_ewdummy = tao->snes_ewdummy;
28: PetscFunctionBegin;
29: if (!snes_ewdummy) PetscFunctionReturn(PETSC_SUCCESS);
30: /* populate snes_ewdummy struct values used in KSPPreSolve_SNESEW */
31: snes_ewdummy->vec_func = b;
32: snes_ewdummy->rtol = tao->gttol;
33: snes_ewdummy->iter = tao->niter;
34: PetscCall(VecNorm(b, NORM_2, &snes_ewdummy->norm));
35: PetscCall(KSPPreSolve_SNESEW(ksp, b, x, snes_ewdummy));
36: snes_ewdummy->vec_func = NULL;
37: PetscFunctionReturn(PETSC_SUCCESS);
38: }
40: static PetscErrorCode KSPPostSolve_TAOEW_Private(KSP ksp, Vec b, Vec x, PetscCtx ctx)
41: {
42: Tao tao = (Tao)ctx;
43: SNES snes_ewdummy = tao->snes_ewdummy;
45: PetscFunctionBegin;
46: if (!snes_ewdummy) PetscFunctionReturn(PETSC_SUCCESS);
47: PetscCall(KSPPostSolve_SNESEW(ksp, b, x, snes_ewdummy));
48: PetscFunctionReturn(PETSC_SUCCESS);
49: }
51: static PetscErrorCode TaoSetUpEW_Private(Tao tao)
52: {
53: SNESKSPEW *kctx;
54: const char *ewprefix;
56: PetscFunctionBegin;
57: if (!tao->ksp) PetscFunctionReturn(PETSC_SUCCESS);
58: if (tao->ksp_ewconv) {
59: if (!tao->snes_ewdummy) PetscCall(SNESCreate(PetscObjectComm((PetscObject)tao), &tao->snes_ewdummy));
60: tao->snes_ewdummy->ksp_ewconv = PETSC_TRUE;
62: tao->ksp->presolve_ew = KSPPreSolve_TAOEW_Private;
63: tao->ksp->prectx_ew = tao;
64: tao->ksp->postsolve_ew = KSPPostSolve_TAOEW_Private;
65: tao->ksp->postctx_ew = tao;
67: PetscCall(KSPGetOptionsPrefix(tao->ksp, &ewprefix));
68: kctx = (SNESKSPEW *)tao->snes_ewdummy->kspconvctx;
69: PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_FALSE, PetscObjectComm((PetscObject)tao), ewprefix));
70: } else PetscCall(SNESDestroy(&tao->snes_ewdummy));
71: PetscFunctionReturn(PETSC_SUCCESS);
72: }
74: /*@
75: TaoParametersInitialize - Sets the base defaults for parameters in `tao`, updating a parameter's current value when it matches its previously recorded default.
77: Logically collective
79: Input Parameter:
80: . tao - the `Tao` object
82: Level: developer
84: Notes:
86: The base defaults are the non-type-specific values established when the `Tao` is created. A `TaoType` constructor may subsequently replace them with type-specific defaults.
88: Developer Notes:
90: `TaoCreate()` calls this routine to establish the base defaults. `TaoSetType()` calls it before constructing a new `TaoType`, so the recorded defaults associated with the previous type are replaced before the new type installs its own defaults.
92: Default tracking is based on value equality, not on whether a setter was called. Consequently, an explicitly assigned value that equals the recorded default may be updated when the type changes.
94: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoDestroy()`, `PetscObjectParameterSetDefault()`
95: @*/
96: PetscErrorCode TaoParametersInitialize(Tao tao)
97: {
98: PetscObjectParameterSetDefault(tao, max_it, 10000);
99: PetscObjectParameterSetDefault(tao, max_funcs, PETSC_UNLIMITED);
100: PetscObjectParameterSetDefault(tao, gatol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
101: PetscObjectParameterSetDefault(tao, grtol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
102: PetscObjectParameterSetDefault(tao, crtol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
103: PetscObjectParameterSetDefault(tao, catol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
104: PetscObjectParameterSetDefault(tao, gttol, 0.0);
105: PetscObjectParameterSetDefault(tao, steptol, 0.0);
106: PetscObjectParameterSetDefault(tao, fmin, PETSC_NINFINITY);
107: PetscObjectParameterSetDefault(tao, trust0, PETSC_INFINITY);
108: return PETSC_SUCCESS;
109: }
111: /*@
112: TaoCreate - Creates a Tao solver
114: Collective
116: Input Parameter:
117: . comm - MPI communicator
119: Output Parameter:
120: . newtao - the new `Tao` context
122: Options Database Key:
123: . -tao_type - select which method Tao should use
125: Level: beginner
127: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoDestroy()`, `TaoSetFromOptions()`, `TaoSetType()`
128: @*/
129: PetscErrorCode TaoCreate(MPI_Comm comm, Tao *newtao)
130: {
131: Tao tao;
133: PetscFunctionBegin;
134: PetscAssertPointer(newtao, 2);
135: PetscCall(TaoInitializePackage());
136: PetscCall(TaoLineSearchInitializePackage());
138: PetscCall(PetscHeaderCreate(tao, TAO_CLASSID, "Tao", "Optimization solver", "Tao", comm, TaoDestroy, TaoView));
139: PetscCall(TaoParametersInitialize(tao));
140: tao->hist_reset = PETSC_TRUE;
142: tao->ops->convergencetest = TaoDefaultConvergenceTest;
144: PetscCall(TaoTermCreateCallbacks(tao, &tao->callbacks));
145: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao->callbacks, "callbacks_"));
146: PetscCall(TaoTermMappingSetData(&tao->objective_term, NULL, 1.0, tao->callbacks, NULL));
147: PetscCall(TaoResetStatistics(tao));
148: *newtao = tao;
149: PetscFunctionReturn(PETSC_SUCCESS);
150: }
152: /*@
153: TaoSolve - Solves an optimization problem min F(x) s.t. l <= x <= u
155: Collective
157: Input Parameter:
158: . tao - the `Tao` context
160: Level: beginner
162: Notes:
163: The user must set up the `Tao` object with calls to `TaoSetSolution()`, `TaoSetObjective()`, `TaoSetGradient()`, and (if using 2nd order method) `TaoSetHessian()`.
165: You should call `TaoGetConvergedReason()` or run with `-tao_converged_reason` to determine if the optimization algorithm actually succeeded or
166: why it failed.
168: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoGetConvergedReason()`, `TaoSetUp()`
169: @*/
170: PetscErrorCode TaoSolve(Tao tao)
171: {
172: static PetscBool set = PETSC_FALSE;
174: PetscFunctionBegin;
176: PetscCall(PetscCitationsRegister("@TechReport{tao-user-ref,\n"
177: "title = {Toolkit for Advanced Optimization (TAO) Users Manual},\n"
178: "author = {Todd Munson and Jason Sarich and Stefan Wild and Steve Benson and Lois Curfman McInnes},\n"
179: "Institution = {Argonne National Laboratory},\n"
180: "Year = 2014,\n"
181: "Number = {ANL/MCS-TM-322 - Revision 3.5},\n"
182: "url = {https://www.mcs.anl.gov/research/projects/tao/}\n}\n",
183: &set));
184: tao->header_printed = PETSC_FALSE;
185: PetscCall(TaoSetUp(tao));
186: PetscCall(TaoResetStatistics(tao));
187: if (tao->linesearch) PetscCall(TaoLineSearchReset(tao->linesearch));
189: PetscCall(PetscLogEventBegin(TAO_Solve, tao, 0, 0, 0));
190: PetscTryTypeMethod(tao, solve);
191: PetscCall(PetscLogEventEnd(TAO_Solve, tao, 0, 0, 0));
193: PetscCall(VecViewFromOptions(tao->solution, (PetscObject)tao, "-tao_view_solution"));
195: tao->ntotalits += tao->niter;
197: if (tao->printreason) {
198: PetscViewer viewer = PETSC_VIEWER_STDOUT_(((PetscObject)tao)->comm);
200: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)tao)->tablevel));
201: if (tao->reason > 0) {
202: if (((PetscObject)tao)->prefix) {
203: PetscCall(PetscViewerASCIIPrintf(viewer, "TAO %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix, TaoConvergedReasons[tao->reason], tao->niter));
204: } else {
205: PetscCall(PetscViewerASCIIPrintf(viewer, "TAO solve converged due to %s iterations %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter));
206: }
207: } else {
208: if (((PetscObject)tao)->prefix) {
209: PetscCall(PetscViewerASCIIPrintf(viewer, "TAO %s solve did not converge due to %s iteration %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix, TaoConvergedReasons[tao->reason], tao->niter));
210: } else {
211: PetscCall(PetscViewerASCIIPrintf(viewer, "TAO solve did not converge due to %s iteration %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter));
212: }
213: }
214: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)tao)->tablevel));
215: }
216: PetscCall(TaoViewFromOptions(tao, NULL, "-tao_view"));
217: PetscFunctionReturn(PETSC_SUCCESS);
218: }
220: /*@
221: TaoSetUp - Sets up the internal data structures for the later use
222: of a Tao solver
224: Collective
226: Input Parameter:
227: . tao - the `Tao` context
229: Level: advanced
231: Note:
232: The user will not need to explicitly call `TaoSetUp()`, as it will
233: automatically be called in `TaoSolve()`. However, if the user
234: desires to call it explicitly, it should come after `TaoCreate()`
235: and any TaoSetSomething() routines, but before `TaoSolve()`.
237: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
238: @*/
239: PetscErrorCode TaoSetUp(Tao tao)
240: {
241: PetscFunctionBegin;
243: if (tao->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
244: PetscCall(TaoSetUpEW_Private(tao));
245: PetscCall(TaoTermMappingSetUp(&tao->objective_term));
246: if (!tao->solution) PetscCall(TaoTermMappingCreateSolutionVec(&tao->objective_term, &tao->solution));
247: PetscCheck(tao->solution, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Must call TaoSetSolution()");
248: if (tao->uses_gradient && !tao->gradient) PetscCall(VecDuplicate(tao->solution, &tao->gradient));
249: if (tao->uses_hessian_matrices) {
250: // TaoSetHessian has been called, but as terms have been added,
251: // subterms' Hessian and PtAP routines, if needed, have to be created
252: // TODO Function to set TAOTERMSUM's Hessian.
253: if (!tao->hessian) {
254: PetscBool is_defined;
256: // TAOTERMSUM's Hessian will follow layout and type of first term's Hessian
257: PetscCall(TaoTermIsCreateHessianMatricesDefined(tao->objective_term.term, &is_defined));
258: if (is_defined) PetscCall(TaoTermMappingCreateHessianMatrices(&tao->objective_term, &tao->hessian, &tao->hessian_pre));
259: }
260: PetscCheck(tao->hessian, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Must call TaoSetHessian()");
261: }
262: PetscTryTypeMethod(tao, setup);
263: tao->setupcalled = PETSC_TRUE;
264: PetscFunctionReturn(PETSC_SUCCESS);
265: }
267: /*@
268: TaoDestroy - Destroys the `Tao` context that was created with `TaoCreate()`
270: Collective
272: Input Parameter:
273: . tao - the `Tao` context
275: Level: beginner
277: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
278: @*/
279: PetscErrorCode TaoDestroy(Tao *tao)
280: {
281: PetscFunctionBegin;
282: if (!*tao) PetscFunctionReturn(PETSC_SUCCESS);
284: if (--((PetscObject)*tao)->refct > 0) {
285: *tao = NULL;
286: PetscFunctionReturn(PETSC_SUCCESS);
287: }
289: PetscTryTypeMethod(*tao, destroy);
290: PetscCall(TaoTermMappingReset(&(*tao)->objective_term));
291: PetscCall(VecDestroy(&(*tao)->objective_parameters));
292: PetscCall(TaoTermDestroy(&(*tao)->callbacks));
293: PetscCall(DMDestroy(&(*tao)->dm));
294: PetscCall(KSPDestroy(&(*tao)->ksp));
295: PetscCall(SNESDestroy(&(*tao)->snes_ewdummy));
296: PetscCall(TaoLineSearchDestroy(&(*tao)->linesearch));
298: if ((*tao)->ops->convergencedestroy) {
299: PetscCall((*(*tao)->ops->convergencedestroy)((*tao)->cnvP));
300: PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
301: }
302: PetscCall(VecDestroy(&(*tao)->solution));
303: PetscCall(VecDestroy(&(*tao)->gradient));
304: PetscCall(VecDestroy(&(*tao)->ls_res));
306: if ((*tao)->gradient_norm) {
307: PetscCall(PetscObjectDereference((PetscObject)(*tao)->gradient_norm));
308: PetscCall(VecDestroy(&(*tao)->gradient_norm_tmp));
309: }
311: PetscCall(VecDestroy(&(*tao)->XL));
312: PetscCall(VecDestroy(&(*tao)->XU));
313: PetscCall(VecDestroy(&(*tao)->IL));
314: PetscCall(VecDestroy(&(*tao)->IU));
315: PetscCall(VecDestroy(&(*tao)->DE));
316: PetscCall(VecDestroy(&(*tao)->DI));
317: PetscCall(VecDestroy(&(*tao)->constraints));
318: PetscCall(VecDestroy(&(*tao)->constraints_equality));
319: PetscCall(VecDestroy(&(*tao)->constraints_inequality));
320: PetscCall(VecDestroy(&(*tao)->stepdirection));
321: PetscCall(MatDestroy(&(*tao)->hessian_pre));
322: PetscCall(MatDestroy(&(*tao)->hessian));
323: PetscCall(MatDestroy(&(*tao)->ls_jac));
324: PetscCall(MatDestroy(&(*tao)->ls_jac_pre));
325: PetscCall(MatDestroy(&(*tao)->jacobian_pre));
326: PetscCall(MatDestroy(&(*tao)->jacobian));
327: PetscCall(MatDestroy(&(*tao)->jacobian_state_pre));
328: PetscCall(MatDestroy(&(*tao)->jacobian_state));
329: PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
330: PetscCall(MatDestroy(&(*tao)->jacobian_design));
331: PetscCall(MatDestroy(&(*tao)->jacobian_equality));
332: PetscCall(MatDestroy(&(*tao)->jacobian_equality_pre));
333: PetscCall(MatDestroy(&(*tao)->jacobian_inequality));
334: PetscCall(MatDestroy(&(*tao)->jacobian_inequality_pre));
335: PetscCall(ISDestroy(&(*tao)->state_is));
336: PetscCall(ISDestroy(&(*tao)->design_is));
337: PetscCall(VecDestroy(&(*tao)->res_weights_v));
338: PetscCall(TaoMonitorCancel(*tao));
339: if ((*tao)->hist_malloc) PetscCall(PetscFree4((*tao)->hist_obj, (*tao)->hist_resid, (*tao)->hist_cnorm, (*tao)->hist_lits));
340: if ((*tao)->res_weights_n) {
341: PetscCall(PetscFree((*tao)->res_weights_rows));
342: PetscCall(PetscFree((*tao)->res_weights_cols));
343: PetscCall(PetscFree((*tao)->res_weights_w));
344: }
345: PetscCall(PetscHeaderDestroy(tao));
346: PetscFunctionReturn(PETSC_SUCCESS);
347: }
349: /*@
350: TaoKSPSetUseEW - Sets `SNES` to use Eisenstat-Walker method {cite}`ew96` for computing relative tolerance for linear solvers.
352: Logically Collective
354: Input Parameters:
355: + tao - Tao context
356: - flag - `PETSC_TRUE` or `PETSC_FALSE`
358: Options Database Key:
359: . -tao_ksp_ew (true|false) - use Eisenstat-Walker linear system convergence test
361: Level: advanced
363: Note:
364: See `SNESKSPSetUseEW()` for customization details.
366: .seealso: [](ch_tao), `Tao`, `SNESKSPSetUseEW()`
367: @*/
368: PetscErrorCode TaoKSPSetUseEW(Tao tao, PetscBool flag)
369: {
370: PetscFunctionBegin;
373: tao->ksp_ewconv = flag;
374: PetscFunctionReturn(PETSC_SUCCESS);
375: }
377: /*@
378: TaoMonitorSetFromOptions - Sets a monitor function, viewer, and viewer format based on the viewer specification in the options database
380: Collective
382: Input Parameters:
383: + tao - `Tao` object you wish to monitor
384: . name - the monitor type one is seeking
385: . help - message indicating what monitoring is done
386: . manual - manual page for the monitor
387: - monitor - the monitor function, this must use a `PetscViewerFormat` as its context
389: Options Database Key:
390: . -name_interval interval - sets the interval of `Tao` iterations to monitor, by default this is 1.
392: Level: developer
394: Note:
395: See `PetscOptionsCreateViewer()` for details on the viewer specification, for example, `-tao_monitor ascii:myfile::append`
397: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
398: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
399: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
400: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
401: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
402: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
403: `PetscOptionsFList()`, `PetscOptionsEList()`
404: @*/
405: PetscErrorCode TaoMonitorSetFromOptions(Tao tao, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(Tao, PetscViewerAndFormat *))
406: {
407: PetscViewer viewer;
408: PetscViewerFormat format;
409: PetscBool flg;
411: PetscFunctionBegin;
412: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)tao), ((PetscObject)tao)->options, ((PetscObject)tao)->prefix, name, &viewer, &format, &flg));
413: if (flg) {
414: PetscViewerAndFormat *vf;
415: char interval_key[1024];
417: PetscCall(PetscSNPrintf(interval_key, sizeof(interval_key), "%s_interval", name));
418: PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
419: vf->view_interval = 1;
420: PetscCall(PetscOptionsGetInt(((PetscObject)tao)->options, ((PetscObject)tao)->prefix, interval_key, &vf->view_interval, NULL));
422: PetscCall(PetscViewerDestroy(&viewer));
423: PetscCall(TaoMonitorSet(tao, (PetscErrorCode (*)(Tao, PetscCtx))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
424: }
425: PetscFunctionReturn(PETSC_SUCCESS);
426: }
428: /*@
429: TaoSetFromOptions - Sets various Tao parameters from the options database
431: Collective
433: Input Parameter:
434: . tao - the `Tao` solver context
436: Options Database Keys:
437: + -tao_type type - The algorithm that `tao` will use (lmvm, nls, etc.). See `TaoType`
438: . -tao_gatol gatol - absolute error tolerance for ||gradient||
439: . -tao_grtol grtol - relative error tolerance for ||gradient||
440: . -tao_gttol gttol - reduction of ||gradient|| relative to initial gradient
441: . -tao_max_it max - sets maximum number of iterations
442: . -tao_max_funcs max - sets maximum number of function evaluations
443: . -tao_fmin fmin - stop if function value reaches `fmin`
444: . -tao_steptol tol - stop if the trust region radius becomes less than `tol`
445: . -tao_trust0 radius - initial trust region radius
446: . -tao_monitor viewer_specification - prints function value and residual norm at each iteration
447: . -tao_monitor_constraint_norm viewer_specification - prints objective value, gradient, and constraint norm at each iteration
448: . -tao_monitor_globalization viewer_specification - prints information about the globalization at each iteration
449: . -tao_monitor_solution viewer_specification - prints solution vector at each iteration
450: . -tao_monitor_residual viewer_specification - view the least-squares residual at each iteration
451: . -tao_monitor_step viewer_specification - prints step vector at each iteration
452: . -tao_monitor_gradient viewer_specification - prints gradient vector at each iteration
453: . -tao_monitor_solution_draw (true|false) - use `TaoMonitorSolutionDraw()` to draw the solution at each iteration
454: . -tao_monitor_gradient_draw (true|false) - use `TaoMonitorGradientDraw()` to draw the gradient at each iteration
455: . -tao_monitor_step_draw (true|false) - use `TaoMonitorStepDraw()` to draw the solution step at each iteration
456: . -tao_monitor_cancel (true|false) - cancels all monitors (except those set from the command line)
457: . -tao_fd_gradient (true|false) - use gradient computed with finite differences
458: . -tao_fd_hessian (true|false) - use Hessian computed with finite differences
459: . -tao_mf_hessian (true|false) - use matrix-free Hessian computed with finite differences. No `TaoTerm` support
460: . -tao_view viewer_specification - displays information about `tao` at the end of `TaoSolve()`
461: . -tao_view_solution viewer_specification - view the solution at the end of the optimization process
462: . -tao_converged_reason (true|false) - displays the reason `tao` stopped iterating
463: . -tao_add_terms prefix1,prefix2,... - takes a comma-separated list of up to 16 options prefixes, a `TaoTerm` will be created for each and added to the objective function
464: . -tao_recycle_history (true|false) - reuse the history from previous `TaoSolve()`, for some algorithms. See `TaoSetRecycleHistory()`
465: . -tao_subset_type (subvec|mask|matrixfree) - strategies for handling active-sets, see `TaoSubsetType`
466: - -tao_ksp_ew (true|false) - use Eisenstat-Walker linear system convergence test, see `TaoKSPSetUseEW()`
468: Level: beginner
470: Notes:
471: See `PetscOptionsCreateViewer()` for the format of `viewer_specification`
473: To see all options, run your program with the `-help` option or consult the
474: user's manual. Should be called after `TaoCreate()` but before `TaoSolve()`.
476: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`, `TaoSetRecycleHistory()`, `PetscOptionsCreateViewer()`, `TaoSubsetType`, `TaoKSPSetUseEW()`
477: @*/
478: PetscErrorCode TaoSetFromOptions(Tao tao)
479: {
480: TaoType default_type = TAOLMVM;
481: char type[256];
482: PetscBool flg, found;
483: MPI_Comm comm;
484: PetscReal catol, crtol, gatol, grtol, gttol;
486: PetscFunctionBegin;
488: PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
490: if (((PetscObject)tao)->type_name) default_type = ((PetscObject)tao)->type_name;
492: PetscObjectOptionsBegin((PetscObject)tao);
493: /* Check for type from options */
494: PetscCall(PetscOptionsFList("-tao_type", "Tao Solver type", "TaoSetType", TaoList, default_type, type, sizeof(type), &flg));
495: if (flg) PetscCall(TaoSetType(tao, type));
496: else if (!((PetscObject)tao)->type_name) PetscCall(TaoSetType(tao, default_type));
498: /* Tao solvers do not set the prefix, set it here if not yet done
499: We do it after SetType since solver may have been changed */
500: if (tao->linesearch) {
501: const char *prefix;
502: PetscCall(TaoLineSearchGetOptionsPrefix(tao->linesearch, &prefix));
503: if (!prefix) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, ((PetscObject)tao)->prefix));
504: }
506: catol = tao->catol;
507: crtol = tao->crtol;
508: PetscCall(PetscOptionsReal("-tao_catol", "Stop if constraints violations within", "TaoSetConstraintTolerances", tao->catol, &catol, NULL));
509: PetscCall(PetscOptionsReal("-tao_crtol", "Stop if relative constraint violations within", "TaoSetConstraintTolerances", tao->crtol, &crtol, NULL));
510: PetscCall(TaoSetConstraintTolerances(tao, catol, crtol));
512: gatol = tao->gatol;
513: grtol = tao->grtol;
514: gttol = tao->gttol;
515: PetscCall(PetscOptionsReal("-tao_gatol", "Stop if norm of gradient less than", "TaoSetTolerances", tao->gatol, &gatol, NULL));
516: PetscCall(PetscOptionsReal("-tao_grtol", "Stop if norm of gradient divided by the function value is less than", "TaoSetTolerances", tao->grtol, &grtol, NULL));
517: PetscCall(PetscOptionsReal("-tao_gttol", "Stop if the norm of the gradient is less than the norm of the initial gradient times tol", "TaoSetTolerances", tao->gttol, >tol, NULL));
518: PetscCall(TaoSetTolerances(tao, gatol, grtol, gttol));
520: PetscCall(PetscOptionsInt("-tao_max_it", "Stop if iteration number exceeds", "TaoSetMaximumIterations", tao->max_it, &tao->max_it, &flg));
521: if (flg) PetscCall(TaoSetMaximumIterations(tao, tao->max_it));
523: PetscCall(PetscOptionsInt("-tao_max_funcs", "Stop if number of function evaluations exceeds", "TaoSetMaximumFunctionEvaluations", tao->max_funcs, &tao->max_funcs, &flg));
524: if (flg) PetscCall(TaoSetMaximumFunctionEvaluations(tao, tao->max_funcs));
526: PetscCall(PetscOptionsReal("-tao_fmin", "Stop if function less than", "TaoSetFunctionLowerBound", tao->fmin, &tao->fmin, NULL));
527: PetscCall(PetscOptionsBoundedReal("-tao_steptol", "Stop if step size or trust region radius less than", "", tao->steptol, &tao->steptol, NULL, 0));
528: PetscCall(PetscOptionsReal("-tao_trust0", "Initial trust region radius", "TaoSetInitialTrustRegionRadius", tao->trust0, &tao->trust0, &flg));
529: if (flg) PetscCall(TaoSetInitialTrustRegionRadius(tao, tao->trust0));
531: PetscCall(PetscOptionsDeprecated("-tao_solution_monitor", "-tao_monitor_solution", "3.21", NULL));
532: PetscCall(PetscOptionsDeprecated("-tao_gradient_monitor", "-tao_monitor_gradient", "3.21", NULL));
533: PetscCall(PetscOptionsDeprecated("-tao_stepdirection_monitor", "-tao_monitor_step", "3.21", NULL));
534: PetscCall(PetscOptionsDeprecated("-tao_residual_monitor", "-tao_monitor_residual", "3.21", NULL));
535: PetscCall(PetscOptionsDeprecated("-tao_smonitor", "-tao_monitor", "3.21", NULL));
536: PetscCall(PetscOptionsDeprecated("-tao_monitor_short", "-tao_monitor", "3.26", NULL));
537: PetscCall(PetscOptionsDeprecated("-tao_monitor_short_interval", "-tao_monitor_interval", "3.26", NULL));
538: PetscCall(PetscOptionsDeprecated("-tao_cmonitor", "-tao_monitor_constraint_norm", "3.21", NULL));
539: PetscCall(PetscOptionsDeprecated("-tao_gmonitor", "-tao_monitor_globalization", "3.21", NULL));
540: PetscCall(PetscOptionsDeprecated("-tao_draw_solution", "-tao_monitor_solution_draw", "3.21", NULL));
541: PetscCall(PetscOptionsDeprecated("-tao_draw_gradient", "-tao_monitor_gradient_draw", "3.21", NULL));
542: PetscCall(PetscOptionsDeprecated("-tao_draw_step", "-tao_monitor_step_draw", "3.21", NULL));
544: PetscCall(PetscOptionsBool("-tao_converged_reason", "Print reason for Tao converged", "TaoSolve", tao->printreason, &tao->printreason, NULL));
546: PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_solution", "View solution vector after each iteration", "TaoMonitorSolution", TaoMonitorSolution));
547: PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_gradient", "View gradient vector for each iteration", "TaoMonitorGradient", TaoMonitorGradient));
549: PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_step", "View step vector after each iteration", "TaoMonitorStep", TaoMonitorStep));
550: PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_residual", "View least-squares residual vector after each iteration", "TaoMonitorResidual", TaoMonitorResidual));
551: PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor", "Use the default convergence monitor", "TaoMonitorDefault", TaoMonitorDefault));
552: PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_globalization", "Use the convergence monitor with extra globalization info", "TaoMonitorGlobalization", TaoMonitorGlobalization));
553: PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_constraint_norm", "Use the default convergence monitor with constraint norm", "TaoMonitorConstraintNorm", TaoMonitorConstraintNorm));
555: flg = PETSC_FALSE;
556: PetscCall(PetscOptionsDeprecated("-tao_cancelmonitors", "-tao_monitor_cancel", "3.21", NULL));
557: PetscCall(PetscOptionsBool("-tao_monitor_cancel", "cancel all monitors and call any registered destroy routines", "TaoMonitorCancel", flg, &flg, NULL));
558: if (flg) PetscCall(TaoMonitorCancel(tao));
560: flg = PETSC_FALSE;
561: PetscCall(PetscOptionsBool("-tao_monitor_solution_draw", "Plot solution vector at each iteration", "TaoMonitorSet", flg, &flg, NULL));
562: if (flg) {
563: TaoMonitorDrawCtx drawctx;
564: PetscInt howoften = 1;
565: PetscCall(PetscOptionsInt("-tao_monitor_solution_draw_interval", "Only draw every interval iterations, and the final value", "TaoMonitorSet", howoften, &howoften, NULL));
566: PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
567: PetscCall(TaoMonitorSet(tao, TaoMonitorSolutionDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
568: }
570: flg = PETSC_FALSE;
571: PetscCall(PetscOptionsBool("-tao_monitor_step_draw", "Plots step at each iteration", "TaoMonitorSet", flg, &flg, NULL));
572: if (flg) {
573: TaoMonitorDrawCtx drawctx;
574: PetscInt howoften = 1;
575: PetscCall(PetscOptionsInt("-tao_monitor_step_draw_interval", "Only draw every interval iterations, and the final value", "TaoMonitorSet", howoften, &howoften, NULL));
576: PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
577: PetscCall(TaoMonitorSet(tao, TaoMonitorStepDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
578: }
580: flg = PETSC_FALSE;
581: PetscCall(PetscOptionsBool("-tao_monitor_gradient_draw", "plots gradient at each iteration", "TaoMonitorSet", flg, &flg, NULL));
582: if (flg) {
583: TaoMonitorDrawCtx drawctx;
584: PetscInt howoften = 1;
585: PetscCall(PetscOptionsInt("-tao_monitor_gradient_draw_interval", "Only draw every interval iterations, and the final value", "TaoMonitorSet", howoften, &howoften, NULL));
586: PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
587: PetscCall(TaoMonitorSet(tao, TaoMonitorGradientDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
588: }
590: flg = PETSC_FALSE;
591: PetscCall(PetscOptionsBool("-tao_fd_gradient", "compute gradient using finite differences", "TaoDefaultComputeGradient", flg, &flg, NULL));
592: if (flg) PetscCall(TaoTermComputeGradientSetUseFD(tao->objective_term.term, PETSC_TRUE));
593: flg = PETSC_FALSE;
594: PetscCall(PetscOptionsBool("-tao_fd_hessian", "compute Hessian using finite differences", "TaoDefaultComputeHessian", flg, &flg, NULL));
595: if (flg) {
596: Mat H;
598: PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
599: PetscCall(MatSetType(H, MATAIJ));
600: PetscCall(MatSetOption(H, MAT_SYMMETRIC, PETSC_TRUE));
601: PetscCall(MatSetOption(H, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
602: PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessian, NULL));
603: PetscCall(TaoTermComputeHessianSetUseFD(tao->objective_term.term, PETSC_TRUE));
604: PetscCall(MatDestroy(&H));
605: }
606: flg = PETSC_FALSE;
607: PetscCall(PetscOptionsBool("-tao_mf_hessian", "compute matrix-free Hessian using finite differences", "TaoDefaultComputeHessianMFFD", flg, &flg, NULL));
608: if (flg) {
609: PetscBool is_callback;
610: Mat H;
612: // Check that tao has only one TaoTerm with type TAOTERMCALLBACK
613: PetscCall(PetscObjectTypeCompare((PetscObject)tao->objective_term.term, TAOTERMCALLBACKS, &is_callback));
614: if (is_callback) {
615: // Create Hessian via TaoTermCreateHessianMFFD
616: PetscCall(TaoTermCreateHessianMFFD(tao->objective_term.term, &H));
617: PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessianMFFD, NULL));
618: PetscCall(MatDestroy(&H));
619: } else {
620: PetscCall(PetscInfo(tao, "-tao_mf_hessian only works when Tao has a single TAOTERMCALLBACK term. Ignoring.\n"));
621: }
622: }
623: PetscCall(PetscOptionsBool("-tao_recycle_history", "enable recycling/re-using information from the previous TaoSolve() call for some algorithms", "TaoSetRecycleHistory", flg, &flg, &found));
624: if (found) PetscCall(TaoSetRecycleHistory(tao, flg));
625: PetscCall(PetscOptionsEnum("-tao_subset_type", "subset type", "", TaoSubsetTypes, (PetscEnum)tao->subset_type, (PetscEnum *)&tao->subset_type, NULL));
627: if (tao->ksp) {
628: PetscCall(PetscOptionsBool("-tao_ksp_ew", "Use Eisentat-Walker linear system convergence test", "TaoKSPSetUseEW", tao->ksp_ewconv, &tao->ksp_ewconv, NULL));
629: PetscCall(TaoKSPSetUseEW(tao, tao->ksp_ewconv));
630: }
632: PetscCall(TaoTermSetFromOptions(tao->callbacks));
634: {
635: char *term_prefixes[16];
636: PetscInt n_terms = PETSC_STATIC_ARRAY_LENGTH(term_prefixes);
638: PetscCall(PetscOptionsStringArray("-tao_add_terms", "a list of prefixes for terms to add to the Tao objective function", "TaoAddTerm", term_prefixes, &n_terms, NULL));
639: for (PetscInt i = 0; i < n_terms; i++) {
640: TaoTerm term;
641: const char *prefix;
643: PetscCall(TaoTermDuplicate(tao->objective_term.term, TAOTERM_DUPLICATE_SIZEONLY, &term));
644: PetscCall(TaoGetOptionsPrefix(tao, &prefix));
645: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)term, prefix));
646: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)term, term_prefixes[i]));
647: PetscCall(TaoTermSetFromOptions(term));
648: PetscCall(TaoAddTerm(tao, term_prefixes[i], 1.0, term, NULL, NULL));
649: PetscCall(TaoTermDestroy(&term));
650: PetscCall(PetscFree(term_prefixes[i]));
651: }
652: }
654: if (tao->objective_term.term != tao->callbacks) PetscCall(TaoTermSetFromOptions(tao->objective_term.term));
656: PetscTryTypeMethod(tao, setfromoptions, PetscOptionsObject);
658: /* process any options handlers added with PetscObjectAddOptionsHandler() */
659: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)tao, PetscOptionsObject));
660: PetscOptionsEnd();
662: if (tao->linesearch) PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
663: PetscFunctionReturn(PETSC_SUCCESS);
664: }
666: /*@
667: TaoViewFromOptions - View a `Tao` object based on values in the options database
669: Collective
671: Input Parameters:
672: + A - the `Tao` context
673: . obj - optional object that provides the prefix for the options database, pass `NULL` to use the options prefix of `A`
674: - name - command line option
676: Options Database Key:
677: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`
679: Level: intermediate
681: Note:
682: This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
683: rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.
685: .seealso: [](ch_tao), `Tao`, `TaoView()`, `PetscObjectViewFromOptions()`, `TaoCreate()`, `PetscOptionsCreateViewer()`
686: @*/
687: PetscErrorCode TaoViewFromOptions(Tao A, PetscObject obj, const char name[])
688: {
689: PetscFunctionBegin;
691: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
692: PetscFunctionReturn(PETSC_SUCCESS);
693: }
695: /*@
696: TaoView - Displays information about the `Tao` object
698: Collective
700: Input Parameters:
701: + tao - the `Tao` context
702: - viewer - visualization context
704: Options Database Key:
705: . -tao_view viewer_specification - Calls `TaoView()` at the end of `TaoSolve()`. See `PetscOptionsCreateViewer()` for the format of `viewer_specification`.
707: Level: beginner
709: Notes:
710: The available visualization contexts include
711: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
712: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
713: output where only the first processor opens
714: the file. All other processors send their
715: data to the first processor to print.
717: To view all the `TaoTerm` inside of `Tao`, use `PETSC_VIEWER_ASCII_INFO_DETAIL`,
718: or pass `-tao_view ::ascii_info_detail` flag
720: .seealso: [](ch_tao), `Tao`, `PetscViewerASCIIOpen()`, `PetscOptionsCreateViewer()`
721: @*/
722: PetscErrorCode TaoView(Tao tao, PetscViewer viewer)
723: {
724: PetscBool isascii, isstring;
725: TaoType type;
727: PetscFunctionBegin;
729: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)tao)->comm, &viewer));
731: PetscCheckSameComm(tao, 1, viewer, 2);
733: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
734: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
735: if (isascii) {
736: PetscViewerFormat format;
738: PetscCall(PetscViewerGetFormat(viewer, &format));
739: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)tao, viewer));
741: PetscCall(PetscViewerASCIIPushTab(viewer));
742: PetscTryTypeMethod(tao, view, viewer);
743: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
744: PetscCall(PetscViewerASCIIPrintf(viewer, "Objective function:\n"));
745: PetscCall(PetscViewerASCIIPushTab(viewer));
746: PetscCall(PetscViewerASCIIPrintf(viewer, "Scale (tao_objective_scale): %g\n", (double)tao->objective_term.scale));
747: PetscCall(PetscViewerASCIIPrintf(viewer, "Function:\n"));
748: PetscCall(PetscViewerASCIIPushTab(viewer));
749: PetscCall(TaoTermView(tao->objective_term.term, viewer));
750: PetscCall(PetscViewerASCIIPopTab(viewer));
751: if (tao->objective_term.map) {
752: PetscCall(PetscViewerASCIIPrintf(viewer, "Map:\n"));
753: PetscCall(PetscViewerASCIIPushTab(viewer));
754: PetscCall(MatView(tao->objective_term.map, viewer));
755: PetscCall(PetscViewerASCIIPopTab(viewer));
756: } else PetscCall(PetscViewerASCIIPrintf(viewer, "Map: unmapped\n"));
757: PetscCall(PetscViewerASCIIPopTab(viewer));
758: } else if (tao->num_terms > 0 || tao->term_set) {
759: if (tao->objective_term.scale == 1.0 && tao->objective_term.map == NULL) {
760: PetscCall(PetscViewerASCIIPrintf(viewer, "Objective function:\n"));
761: PetscCall(PetscViewerASCIIPushTab(viewer));
762: PetscCall(TaoTermView(tao->objective_term.term, viewer));
763: PetscCall(PetscViewerASCIIPopTab(viewer));
764: } else {
765: PetscCall(PetscViewerASCIIPrintf(viewer, "Objective function:\n"));
766: PetscCall(PetscViewerASCIIPushTab(viewer));
767: if (tao->objective_term.scale != 1.0) PetscCall(PetscViewerASCIIPrintf(viewer, "Scale: %g\n", (double)tao->objective_term.scale));
768: PetscCall(PetscViewerASCIIPrintf(viewer, "Function:\n"));
769: PetscCall(PetscViewerASCIIPushTab(viewer));
770: PetscCall(TaoTermView(tao->objective_term.term, viewer));
771: PetscCall(PetscViewerASCIIPopTab(viewer));
772: if (tao->objective_term.map) {
773: PetscCall(PetscViewerASCIIPrintf(viewer, "Map:\n"));
774: PetscCall(PetscViewerASCIIPushTab(viewer));
775: PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO));
776: PetscCall(MatView(tao->objective_term.map, viewer));
777: PetscCall(PetscViewerPopFormat(viewer));
778: PetscCall(PetscViewerASCIIPopTab(viewer));
779: }
780: PetscCall(PetscViewerASCIIPopTab(viewer));
781: }
782: }
783: if (tao->linesearch) PetscCall(TaoLineSearchView(tao->linesearch, viewer));
784: if (tao->ksp) {
785: PetscCall(KSPView(tao->ksp, viewer));
786: PetscCall(PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", tao->ksp_tot_its));
787: }
789: if (tao->XL || tao->XU) PetscCall(PetscViewerASCIIPrintf(viewer, "Active Set subset type: %s\n", TaoSubsetTypes[tao->subset_type]));
791: PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: gatol=%g,", (double)tao->gatol));
792: PetscCall(PetscViewerASCIIPrintf(viewer, " grtol=%g,", (double)tao->grtol));
793: PetscCall(PetscViewerASCIIPrintf(viewer, " steptol=%g,", (double)tao->steptol));
794: PetscCall(PetscViewerASCIIPrintf(viewer, " gttol=%g\n", (double)tao->gttol));
795: PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Function/Gradient:=%g\n", (double)tao->residual));
797: if (tao->constrained) {
798: PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances:"));
799: PetscCall(PetscViewerASCIIPrintf(viewer, " catol=%g,", (double)tao->catol));
800: PetscCall(PetscViewerASCIIPrintf(viewer, " crtol=%g\n", (double)tao->crtol));
801: PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Constraints:=%g\n", (double)tao->cnorm));
802: }
804: if (tao->trust < tao->steptol) {
805: PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: steptol=%g\n", (double)tao->steptol));
806: PetscCall(PetscViewerASCIIPrintf(viewer, "Final trust region radius:=%g\n", (double)tao->trust));
807: }
809: if (tao->fmin > -1.e25) PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: function minimum=%g\n", (double)tao->fmin));
810: PetscCall(PetscViewerASCIIPrintf(viewer, "Objective value=%g\n", (double)tao->fc));
812: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of iterations=%" PetscInt_FMT ", ", tao->niter));
813: PetscCall(PetscViewerASCIIPrintf(viewer, " (max: %" PetscInt_FMT ")\n", tao->max_it));
815: if (tao->objective_term.term->nobj > 0) {
816: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT ",", tao->objective_term.term->nobj));
817: if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, " (max: unlimited)\n"));
818: else PetscCall(PetscViewerASCIIPrintf(viewer, " (max: %" PetscInt_FMT ")\n", tao->max_funcs));
819: }
820: if (tao->objective_term.term->ngrad > 0) {
821: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT ",", tao->objective_term.term->ngrad));
822: if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, " (max: unlimited)\n"));
823: else PetscCall(PetscViewerASCIIPrintf(viewer, " (max: %" PetscInt_FMT ")\n", tao->max_funcs));
824: }
825: if (tao->objective_term.term->nobjgrad > 0) {
826: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT ",", tao->objective_term.term->nobjgrad));
827: if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, " (max: unlimited)\n"));
828: else PetscCall(PetscViewerASCIIPrintf(viewer, " (max: %" PetscInt_FMT ")\n", tao->max_funcs));
829: }
830: if (tao->nres > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of residual evaluations=%" PetscInt_FMT "\n", tao->nres));
831: if (tao->objective_term.term->nhess > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", tao->objective_term.term->nhess));
832: if (tao->nconstraints > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of constraint function evaluations=%" PetscInt_FMT "\n", tao->nconstraints));
833: if (tao->njac > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Jacobian evaluations=%" PetscInt_FMT "\n", tao->njac));
835: if (tao->reason > 0) {
836: PetscCall(PetscViewerASCIIPrintf(viewer, "Solution converged: "));
837: switch (tao->reason) {
838: case TAO_CONVERGED_GATOL:
839: PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)|| <= gatol\n"));
840: break;
841: case TAO_CONVERGED_GRTOL:
842: PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/|f(X)| <= grtol\n"));
843: break;
844: case TAO_CONVERGED_GTTOL:
845: PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/||g(X0)|| <= gttol\n"));
846: break;
847: case TAO_CONVERGED_STEPTOL:
848: PetscCall(PetscViewerASCIIPrintf(viewer, " Steptol -- step size small\n"));
849: break;
850: case TAO_CONVERGED_MINF:
851: PetscCall(PetscViewerASCIIPrintf(viewer, " Minf -- f < fmin\n"));
852: break;
853: case TAO_CONVERGED_USER:
854: PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
855: break;
856: default:
857: PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
858: break;
859: }
860: } else if (tao->reason == TAO_CONTINUE_ITERATING) {
861: PetscCall(PetscViewerASCIIPrintf(viewer, "Solver never run\n"));
862: } else {
863: PetscCall(PetscViewerASCIIPrintf(viewer, "Solver failed: "));
864: switch (tao->reason) {
865: case TAO_DIVERGED_MAXITS:
866: PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Iterations\n"));
867: break;
868: case TAO_DIVERGED_NAN:
869: PetscCall(PetscViewerASCIIPrintf(viewer, " NaN or infinity encountered\n"));
870: break;
871: case TAO_DIVERGED_MAXFCN:
872: PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Function Evaluations\n"));
873: break;
874: case TAO_DIVERGED_LS_FAILURE:
875: PetscCall(PetscViewerASCIIPrintf(viewer, " Line Search Failure\n"));
876: break;
877: case TAO_DIVERGED_TR_REDUCTION:
878: PetscCall(PetscViewerASCIIPrintf(viewer, " Trust Region too small\n"));
879: break;
880: case TAO_DIVERGED_USER:
881: PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
882: break;
883: default:
884: PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
885: break;
886: }
887: }
888: PetscCall(PetscViewerASCIIPopTab(viewer));
889: } else if (isstring) {
890: PetscCall(TaoGetType(tao, &type));
891: PetscCall(PetscViewerStringSPrintf(viewer, " %-3.3s", type));
892: }
893: PetscFunctionReturn(PETSC_SUCCESS);
894: }
896: /*@
897: TaoSetRecycleHistory - Sets the boolean flag to enable/disable re-using
898: iterate information from the previous `TaoSolve()`. This feature is disabled by
899: default.
901: Logically Collective
903: Input Parameters:
904: + tao - the `Tao` context
905: - recycle - boolean flag
907: Options Database Key:
908: . -tao_recycle_history (true|false) - reuse the history
910: Level: intermediate
912: Notes:
913: For conjugate gradient methods (`TAOBNCG`), this re-uses the latest search direction
914: from the previous `TaoSolve()` call when computing the first search direction in a
915: new solution. By default, CG methods set the first search direction to the
916: negative gradient.
918: For quasi-Newton family of methods (`TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`), this re-uses
919: the accumulated quasi-Newton Hessian approximation from the previous `TaoSolve()`
920: call. By default, QN family of methods reset the initial Hessian approximation to
921: the identity matrix.
923: For any other algorithm, this setting has no effect.
925: .seealso: [](ch_tao), `Tao`, `TaoGetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
926: @*/
927: PetscErrorCode TaoSetRecycleHistory(Tao tao, PetscBool recycle)
928: {
929: PetscFunctionBegin;
932: tao->recycle = recycle;
933: PetscFunctionReturn(PETSC_SUCCESS);
934: }
936: /*@
937: TaoGetRecycleHistory - Retrieve the boolean flag for re-using iterate information
938: from the previous `TaoSolve()`. This feature is disabled by default.
940: Logically Collective
942: Input Parameter:
943: . tao - the `Tao` context
945: Output Parameter:
946: . recycle - boolean flag
948: Level: intermediate
950: .seealso: [](ch_tao), `Tao`, `TaoSetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
951: @*/
952: PetscErrorCode TaoGetRecycleHistory(Tao tao, PetscBool *recycle)
953: {
954: PetscFunctionBegin;
956: PetscAssertPointer(recycle, 2);
957: *recycle = tao->recycle;
958: PetscFunctionReturn(PETSC_SUCCESS);
959: }
961: /*@
962: TaoSetTolerances - Sets parameters used in `TaoSolve()` convergence tests
964: Logically Collective
966: Input Parameters:
967: + tao - the `Tao` context
968: . gatol - stop if norm of gradient is less than this
969: . grtol - stop if relative norm of gradient is less than this
970: - gttol - stop if norm of gradient is reduced by this factor
972: Options Database Keys:
973: + -tao_gatol gatol - Sets gatol
974: . -tao_grtol grtol - Sets grtol
975: - -tao_gttol gttol - Sets gttol
977: Stopping Criteria\:
978: .vb
979: ||g(X)|| <= gatol
980: ||g(X)|| / |f(X)| <= grtol
981: ||g(X)|| / ||g(X0)|| <= gttol
982: .ve
984: Level: beginner
986: Notes:
987: Use `PETSC_CURRENT` to leave one or more tolerances unchanged.
989: Use `PETSC_DETERMINE` to set one or more tolerances to their values when the `tao`object's type was set
991: Fortran Note:
992: Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`
994: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`
995: @*/
996: PetscErrorCode TaoSetTolerances(Tao tao, PetscReal gatol, PetscReal grtol, PetscReal gttol)
997: {
998: PetscFunctionBegin;
1004: if (gatol == (PetscReal)PETSC_DETERMINE) {
1005: tao->gatol = tao->default_gatol;
1006: } else if (gatol != (PetscReal)PETSC_CURRENT) {
1007: PetscCheck(gatol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gatol not allowed");
1008: tao->gatol = gatol;
1009: }
1011: if (grtol == (PetscReal)PETSC_DETERMINE) {
1012: tao->grtol = tao->default_grtol;
1013: } else if (grtol != (PetscReal)PETSC_CURRENT) {
1014: PetscCheck(grtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative grtol not allowed");
1015: tao->grtol = grtol;
1016: }
1018: if (gttol == (PetscReal)PETSC_DETERMINE) {
1019: tao->gttol = tao->default_gttol;
1020: } else if (gttol != (PetscReal)PETSC_CURRENT) {
1021: PetscCheck(gttol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gttol not allowed");
1022: tao->gttol = gttol;
1023: }
1024: PetscFunctionReturn(PETSC_SUCCESS);
1025: }
1027: /*@
1028: TaoSetConstraintTolerances - Sets constraint tolerance parameters used in `TaoSolve()` convergence tests
1030: Logically Collective
1032: Input Parameters:
1033: + tao - the `Tao` context
1034: . catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for `gatol` convergence criteria
1035: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for `gatol`, `gttol` convergence criteria
1037: Options Database Keys:
1038: + -tao_catol catol - Sets catol
1039: - -tao_crtol crtol - Sets crtol
1041: Level: intermediate
1043: Notes:
1044: Use `PETSC_CURRENT` to leave one or tolerance unchanged.
1046: Use `PETSC_DETERMINE` to set one or more tolerances to their values when the `tao` object's type was set
1048: Fortran Note:
1049: Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`
1051: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoGetConstraintTolerances()`, `TaoSetTolerances()`
1052: @*/
1053: PetscErrorCode TaoSetConstraintTolerances(Tao tao, PetscReal catol, PetscReal crtol)
1054: {
1055: PetscFunctionBegin;
1060: if (catol == (PetscReal)PETSC_DETERMINE) {
1061: tao->catol = tao->default_catol;
1062: } else if (catol != (PetscReal)PETSC_CURRENT) {
1063: PetscCheck(catol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative catol not allowed");
1064: tao->catol = catol;
1065: }
1067: if (crtol == (PetscReal)PETSC_DETERMINE) {
1068: tao->crtol = tao->default_crtol;
1069: } else if (crtol != (PetscReal)PETSC_CURRENT) {
1070: PetscCheck(crtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative crtol not allowed");
1071: tao->crtol = crtol;
1072: }
1073: PetscFunctionReturn(PETSC_SUCCESS);
1074: }
1076: /*@
1077: TaoGetConstraintTolerances - Gets constraint tolerance parameters used in `TaoSolve()` convergence tests
1079: Not Collective
1081: Input Parameter:
1082: . tao - the `Tao` context
1084: Output Parameters:
1085: + catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for `gatol` convergence criteria
1086: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for `gatol`, `gttol` convergence criteria
1088: Level: intermediate
1090: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoSetTolerances()`, `TaoSetConstraintTolerances()`
1091: @*/
1092: PetscErrorCode TaoGetConstraintTolerances(Tao tao, PetscReal *catol, PetscReal *crtol)
1093: {
1094: PetscFunctionBegin;
1096: if (catol) *catol = tao->catol;
1097: if (crtol) *crtol = tao->crtol;
1098: PetscFunctionReturn(PETSC_SUCCESS);
1099: }
1101: /*@
1102: TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
1103: When an approximate solution with an objective value below this number
1104: has been found, the solver will terminate.
1106: Logically Collective
1108: Input Parameters:
1109: + tao - the Tao solver context
1110: - fmin - the tolerance
1112: Options Database Key:
1113: . -tao_fmin fmin - sets the minimum function value
1115: Level: intermediate
1117: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetTolerances()`
1118: @*/
1119: PetscErrorCode TaoSetFunctionLowerBound(Tao tao, PetscReal fmin)
1120: {
1121: PetscFunctionBegin;
1124: tao->fmin = fmin;
1125: PetscFunctionReturn(PETSC_SUCCESS);
1126: }
1128: /*@
1129: TaoGetFunctionLowerBound - Gets the bound on the solution objective value.
1130: When an approximate solution with an objective value below this number
1131: has been found, the solver will terminate.
1133: Not Collective
1135: Input Parameter:
1136: . tao - the `Tao` solver context
1138: Output Parameter:
1139: . fmin - the minimum function value
1141: Level: intermediate
1143: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetFunctionLowerBound()`
1144: @*/
1145: PetscErrorCode TaoGetFunctionLowerBound(Tao tao, PetscReal *fmin)
1146: {
1147: PetscFunctionBegin;
1149: PetscAssertPointer(fmin, 2);
1150: *fmin = tao->fmin;
1151: PetscFunctionReturn(PETSC_SUCCESS);
1152: }
1154: /*@
1155: TaoSetMaximumFunctionEvaluations - Sets a maximum number of function evaluations allowed for a `TaoSolve()`.
1157: Logically Collective
1159: Input Parameters:
1160: + tao - the `Tao` solver context
1161: - nfcn - the maximum number of function evaluations (>=0), use `PETSC_UNLIMITED` to have no bound
1163: Options Database Key:
1164: . -tao_max_funcs nfcn - sets the maximum number of function evaluations
1166: Level: intermediate
1168: Note:
1169: Use `PETSC_DETERMINE` to use the default maximum number of function evaluations that was set when the object type was set.
1171: Developer Note:
1172: Deprecated support for an unlimited number of function evaluations by passing a negative value.
1174: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumIterations()`
1175: @*/
1176: PetscErrorCode TaoSetMaximumFunctionEvaluations(Tao tao, PetscInt nfcn)
1177: {
1178: PetscFunctionBegin;
1181: if (nfcn == PETSC_DETERMINE) {
1182: tao->max_funcs = tao->default_max_funcs;
1183: } else if (nfcn == PETSC_UNLIMITED || nfcn < 0) {
1184: tao->max_funcs = PETSC_UNLIMITED;
1185: } else {
1186: PetscCheck(nfcn >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations must be positive");
1187: tao->max_funcs = nfcn;
1188: }
1189: PetscFunctionReturn(PETSC_SUCCESS);
1190: }
1192: /*@
1193: TaoGetMaximumFunctionEvaluations - Gets a maximum number of function evaluations allowed for a `TaoSolve()`
1195: Logically Collective
1197: Input Parameter:
1198: . tao - the `Tao` solver context
1200: Output Parameter:
1201: . nfcn - the maximum number of function evaluations
1203: Level: intermediate
1205: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1206: @*/
1207: PetscErrorCode TaoGetMaximumFunctionEvaluations(Tao tao, PetscInt *nfcn)
1208: {
1209: PetscFunctionBegin;
1211: PetscAssertPointer(nfcn, 2);
1212: *nfcn = tao->max_funcs;
1213: PetscFunctionReturn(PETSC_SUCCESS);
1214: }
1216: /*@
1217: TaoGetCurrentFunctionEvaluations - Get current number of function evaluations used by a `Tao` object
1219: Not Collective
1221: Input Parameter:
1222: . tao - the `Tao` solver context
1224: Output Parameter:
1225: . nfuncs - the current number of function evaluations (maximum between gradient and function evaluations)
1227: Level: intermediate
1229: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1230: @*/
1231: PetscErrorCode TaoGetCurrentFunctionEvaluations(Tao tao, PetscInt *nfuncs)
1232: {
1233: PetscFunctionBegin;
1235: PetscAssertPointer(nfuncs, 2);
1236: *nfuncs = PetscMax(tao->objective_term.term->nobj, tao->objective_term.term->nobjgrad);
1237: PetscFunctionReturn(PETSC_SUCCESS);
1238: }
1240: /*@
1241: TaoSetMaximumIterations - Sets a maximum number of iterates to be used in `TaoSolve()`
1243: Logically Collective
1245: Input Parameters:
1246: + tao - the `Tao` solver context
1247: - maxits - the maximum number of iterates (>=0), use `PETSC_UNLIMITED` to have no bound
1249: Options Database Key:
1250: . -tao_max_it its - sets the maximum number of iterations
1252: Level: intermediate
1254: Note:
1255: Use `PETSC_DETERMINE` to use the default maximum number of iterations that was set when the object's type was set.
1257: Developer Note:
1258: Also accepts the deprecated negative values to indicate no limit
1260: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumFunctionEvaluations()`
1261: @*/
1262: PetscErrorCode TaoSetMaximumIterations(Tao tao, PetscInt maxits)
1263: {
1264: PetscFunctionBegin;
1267: if (maxits == PETSC_DETERMINE) {
1268: tao->max_it = tao->default_max_it;
1269: } else if (maxits == PETSC_UNLIMITED) {
1270: tao->max_it = PETSC_INT_MAX;
1271: } else {
1272: PetscCheck(maxits > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations must be positive");
1273: tao->max_it = maxits;
1274: }
1275: PetscFunctionReturn(PETSC_SUCCESS);
1276: }
1278: /*@
1279: TaoGetMaximumIterations - Gets a maximum number of iterates that will be used
1281: Not Collective
1283: Input Parameter:
1284: . tao - the `Tao` solver context
1286: Output Parameter:
1287: . maxits - the maximum number of iterates
1289: Level: intermediate
1291: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumIterations()`, `TaoGetMaximumFunctionEvaluations()`
1292: @*/
1293: PetscErrorCode TaoGetMaximumIterations(Tao tao, PetscInt *maxits)
1294: {
1295: PetscFunctionBegin;
1297: PetscAssertPointer(maxits, 2);
1298: *maxits = tao->max_it;
1299: PetscFunctionReturn(PETSC_SUCCESS);
1300: }
1302: /*@
1303: TaoSetInitialTrustRegionRadius - Sets the initial trust region radius.
1305: Logically Collective
1307: Input Parameters:
1308: + tao - a `Tao` optimization solver
1309: - radius - the trust region radius
1311: Options Database Key:
1312: . -tao_trust0 radius - sets initial trust region radius
1314: Level: intermediate
1316: Note:
1317: Use `PETSC_DETERMINE` to use the default radius that was set when the object's type was set.
1319: .seealso: [](ch_tao), `Tao`, `TaoGetTrustRegionRadius()`, `TaoSetTrustRegionTolerance()`, `TAONTR`
1320: @*/
1321: PetscErrorCode TaoSetInitialTrustRegionRadius(Tao tao, PetscReal radius)
1322: {
1323: PetscFunctionBegin;
1326: if (radius == PETSC_DETERMINE) {
1327: tao->trust0 = tao->default_trust0;
1328: } else {
1329: PetscCheck(radius > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Radius must be positive");
1330: tao->trust0 = radius;
1331: }
1332: PetscFunctionReturn(PETSC_SUCCESS);
1333: }
1335: /*@
1336: TaoGetInitialTrustRegionRadius - Gets the initial trust region radius.
1338: Not Collective
1340: Input Parameter:
1341: . tao - a `Tao` optimization solver
1343: Output Parameter:
1344: . radius - the trust region radius
1346: Level: intermediate
1348: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetCurrentTrustRegionRadius()`, `TAONTR`
1349: @*/
1350: PetscErrorCode TaoGetInitialTrustRegionRadius(Tao tao, PetscReal *radius)
1351: {
1352: PetscFunctionBegin;
1354: PetscAssertPointer(radius, 2);
1355: *radius = tao->trust0;
1356: PetscFunctionReturn(PETSC_SUCCESS);
1357: }
1359: /*@
1360: TaoGetCurrentTrustRegionRadius - Gets the current trust region radius.
1362: Not Collective
1364: Input Parameter:
1365: . tao - a `Tao` optimization solver
1367: Output Parameter:
1368: . radius - the trust region radius
1370: Level: intermediate
1372: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetInitialTrustRegionRadius()`, `TAONTR`
1373: @*/
1374: PetscErrorCode TaoGetCurrentTrustRegionRadius(Tao tao, PetscReal *radius)
1375: {
1376: PetscFunctionBegin;
1378: PetscAssertPointer(radius, 2);
1379: *radius = tao->trust;
1380: PetscFunctionReturn(PETSC_SUCCESS);
1381: }
1383: /*@
1384: TaoGetTolerances - gets the current values of some tolerances used for the convergence testing of `TaoSolve()`
1386: Not Collective
1388: Input Parameter:
1389: . tao - the `Tao` context
1391: Output Parameters:
1392: + gatol - stop if norm of gradient is less than this
1393: . grtol - stop if relative norm of gradient is less than this
1394: - gttol - stop if norm of gradient is reduced by a this factor
1396: Level: intermediate
1398: Note:
1399: `NULL` can be used as an argument if not all tolerances values are needed
1401: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`
1402: @*/
1403: PetscErrorCode TaoGetTolerances(Tao tao, PetscReal *gatol, PetscReal *grtol, PetscReal *gttol)
1404: {
1405: PetscFunctionBegin;
1407: if (gatol) *gatol = tao->gatol;
1408: if (grtol) *grtol = tao->grtol;
1409: if (gttol) *gttol = tao->gttol;
1410: PetscFunctionReturn(PETSC_SUCCESS);
1411: }
1413: /*@
1414: TaoGetKSP - Gets the linear solver used by the optimization solver.
1416: Not Collective
1418: Input Parameter:
1419: . tao - the `Tao` solver
1421: Output Parameter:
1422: . ksp - the `KSP` linear solver used in the optimization solver
1424: Level: intermediate
1426: .seealso: [](ch_tao), `Tao`, `KSP`
1427: @*/
1428: PetscErrorCode TaoGetKSP(Tao tao, KSP *ksp)
1429: {
1430: PetscFunctionBegin;
1432: PetscAssertPointer(ksp, 2);
1433: *ksp = tao->ksp;
1434: PetscFunctionReturn(PETSC_SUCCESS);
1435: }
1437: /*@
1438: TaoGetLinearSolveIterations - Gets the total number of linear iterations
1439: used by the `Tao` solver
1441: Not Collective
1443: Input Parameter:
1444: . tao - the `Tao` context
1446: Output Parameter:
1447: . lits - number of linear iterations
1449: Level: intermediate
1451: Note:
1452: This counter is reset to zero for each successive call to `TaoSolve()`
1454: .seealso: [](ch_tao), `Tao`, `TaoGetKSP()`
1455: @*/
1456: PetscErrorCode TaoGetLinearSolveIterations(Tao tao, PetscInt *lits)
1457: {
1458: PetscFunctionBegin;
1460: PetscAssertPointer(lits, 2);
1461: *lits = tao->ksp_tot_its;
1462: PetscFunctionReturn(PETSC_SUCCESS);
1463: }
1465: /*@
1466: TaoGetLineSearch - Gets the line search used by the optimization solver.
1468: Not Collective
1470: Input Parameter:
1471: . tao - the `Tao` solver
1473: Output Parameter:
1474: . ls - the line search used in the optimization solver
1476: Level: intermediate
1478: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`
1479: @*/
1480: PetscErrorCode TaoGetLineSearch(Tao tao, TaoLineSearch *ls)
1481: {
1482: PetscFunctionBegin;
1484: PetscAssertPointer(ls, 2);
1485: *ls = tao->linesearch;
1486: PetscFunctionReturn(PETSC_SUCCESS);
1487: }
1489: /*@
1490: TaoAddLineSearchCounts - Adds the number of function evaluations spent
1491: in the line search to the running total.
1493: Input Parameters:
1494: . tao - the `Tao` solver
1496: Level: developer
1498: .seealso: [](ch_tao), `Tao`, `TaoGetLineSearch()`, `TaoLineSearchApply()`
1499: @*/
1500: PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1501: {
1502: PetscBool flg;
1503: PetscInt nfeval, ngeval, nfgeval;
1505: PetscFunctionBegin;
1507: if (tao->linesearch) {
1508: PetscCall(TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg));
1509: if (!flg) {
1510: PetscCall(TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval));
1511: tao->objective_term.term->nobj += nfeval;
1512: tao->objective_term.term->ngrad += ngeval;
1513: tao->objective_term.term->nobjgrad += nfgeval;
1514: }
1515: }
1516: PetscFunctionReturn(PETSC_SUCCESS);
1517: }
1519: /*@
1520: TaoGetSolution - Returns the vector with the current solution from the `Tao` object
1522: Not Collective
1524: Input Parameter:
1525: . tao - the `Tao` context
1527: Output Parameter:
1528: . X - the current solution
1530: Level: intermediate
1532: Note:
1533: The returned vector will be the same object that was passed into `TaoSetSolution()`
1535: .seealso: [](ch_tao), `Tao`, `TaoSetSolution()`, `TaoSolve()`
1536: @*/
1537: PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1538: {
1539: PetscFunctionBegin;
1541: PetscAssertPointer(X, 2);
1542: *X = tao->solution;
1543: PetscFunctionReturn(PETSC_SUCCESS);
1544: }
1546: /*@
1547: TaoResetStatistics - Initialize the statistics collected by the `Tao` object.
1548: These statistics include the iteration number, residual norms, and convergence status.
1549: This routine gets called before solving each optimization problem.
1551: Collective
1553: Input Parameter:
1554: . tao - the `Tao` context
1556: Level: developer
1558: Note:
1559: This function does not reset the statistics of internal `TaoTerm`
1561: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
1562: @*/
1563: PetscErrorCode TaoResetStatistics(Tao tao)
1564: {
1565: PetscFunctionBegin;
1567: tao->niter = 0;
1568: tao->nres = 0;
1569: tao->njac = 0;
1570: tao->nconstraints = 0;
1571: tao->ksp_its = 0;
1572: tao->ksp_tot_its = 0;
1573: tao->reason = TAO_CONTINUE_ITERATING;
1574: tao->residual = 0.0;
1575: tao->cnorm = 0.0;
1576: tao->step = 0.0;
1577: tao->lsflag = PETSC_FALSE;
1578: if (tao->hist_reset) tao->hist_len = 0;
1579: PetscFunctionReturn(PETSC_SUCCESS);
1580: }
1582: /*@
1583: TaoSetUpdate - Sets the general-purpose update function called
1584: at the beginning of every iteration of the optimization algorithm. Called after the new solution and the gradient
1585: is determined, but before the Hessian is computed (if applicable).
1587: Logically Collective
1589: Input Parameters:
1590: + tao - The `Tao` solver
1591: . func - The function
1592: - ctx - The update function context
1594: Calling sequence of `func`:
1595: + tao - The optimizer context
1596: . it - The current iteration index
1597: - ctx - The update context
1599: Level: advanced
1601: Notes:
1602: Users can modify the gradient direction or any other vector associated to the specific solver used.
1603: The objective function value is always recomputed after a call to the update hook.
1605: .seealso: [](ch_tao), `Tao`, `TaoSolve()`
1606: @*/
1607: PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao tao, PetscInt it, PetscCtx ctx), PetscCtx ctx)
1608: {
1609: PetscFunctionBegin;
1611: tao->ops->update = func;
1612: tao->user_update = ctx;
1613: PetscFunctionReturn(PETSC_SUCCESS);
1614: }
1616: /*@
1617: TaoSetConvergenceTest - Sets the function that is to be used to test
1618: for convergence of the iterative minimization solution. The new convergence
1619: testing routine will replace Tao's default convergence test.
1621: Logically Collective
1623: Input Parameters:
1624: + tao - the `Tao` object
1625: . conv - the routine to test for convergence
1626: - ctx - [optional] context for private data for the convergence routine (may be `NULL`)
1628: Calling sequence of `conv`:
1629: + tao - the `Tao` object
1630: - ctx - [optional] convergence context
1632: Level: advanced
1634: Note:
1635: The new convergence testing routine should call `TaoSetConvergedReason()`.
1637: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoMonitorSet()`
1638: @*/
1639: PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao tao, PetscCtx ctx), PetscCtx ctx)
1640: {
1641: PetscFunctionBegin;
1643: tao->ops->convergencetest = conv;
1644: tao->cnvP = ctx;
1645: PetscFunctionReturn(PETSC_SUCCESS);
1646: }
1648: /*@
1649: TaoMonitorSet - Sets an additional function that is to be used at every
1650: iteration of the solver to display the iteration's
1651: progress.
1653: Logically Collective
1655: Input Parameters:
1656: + tao - the `Tao` solver context
1657: . func - monitoring routine
1658: . ctx - [optional] user-defined context for private data for the monitor routine (may be `NULL`)
1659: - dest - [optional] function to destroy the context when the `Tao` is destroyed, see `PetscCtxDestroyFn` for the calling sequence
1661: Calling sequence of `func`:
1662: + tao - the `Tao` solver context
1663: - ctx - [optional] monitoring context
1665: Level: intermediate
1667: Notes:
1668: See `TaoSetFromOptions()` for a monitoring options.
1670: Several different monitoring routines may be set by calling
1671: `TaoMonitorSet()` multiple times; all will be called in the
1672: order in which they were set.
1674: Fortran Notes:
1675: Only one monitor function may be set
1677: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoMonitorDefault()`, `TaoMonitorCancel()`, `TaoView()`, `PetscCtxDestroyFn`
1678: @*/
1679: PetscErrorCode TaoMonitorSet(Tao tao, PetscErrorCode (*func)(Tao tao, PetscCtx ctx), PetscCtx ctx, PetscCtxDestroyFn *dest)
1680: {
1681: PetscFunctionBegin;
1683: PetscCheck(tao->numbermonitors < MAXTAOMONITORS, PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Cannot attach another monitor -- max=%d", MAXTAOMONITORS);
1684: for (PetscInt i = 0; i < tao->numbermonitors; i++) {
1685: PetscBool identical;
1687: PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)func, ctx, dest, (PetscErrorCode (*)(void))(PetscVoidFn *)tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical));
1688: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1689: }
1690: tao->monitor[tao->numbermonitors] = func;
1691: tao->monitorcontext[tao->numbermonitors] = ctx;
1692: tao->monitordestroy[tao->numbermonitors] = dest;
1693: ++tao->numbermonitors;
1694: PetscFunctionReturn(PETSC_SUCCESS);
1695: }
1697: /*@
1698: TaoMonitorCancel - Clears all the monitor functions for a `Tao` object.
1700: Logically Collective
1702: Input Parameter:
1703: . tao - the `Tao` solver context
1705: Options Database Key:
1706: . -tao_monitor_cancel - cancels all monitors that have been hardwired
1707: into a code by calls to `TaoMonitorSet()`, but does not cancel those
1708: set via the options database
1710: Level: advanced
1712: Note:
1713: There is no way to clear one specific monitor from a `Tao` object.
1715: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1716: @*/
1717: PetscErrorCode TaoMonitorCancel(Tao tao)
1718: {
1719: PetscFunctionBegin;
1721: for (PetscInt i = 0; i < tao->numbermonitors; i++) {
1722: if (tao->monitordestroy[i]) PetscCall((*tao->monitordestroy[i])(&tao->monitorcontext[i]));
1723: }
1724: tao->numbermonitors = 0;
1725: PetscFunctionReturn(PETSC_SUCCESS);
1726: }
1728: /*@
1729: TaoMonitorDefault - Default routine for monitoring progress of `TaoSolve()`
1731: Collective
1733: Input Parameters:
1734: + tao - the `Tao` context
1735: - vf - `PetscViewerAndFormat` context
1737: Options Database Keys:
1738: + -tao_monitor [ascii][:filename] - monitor function and residual norms at each iteration, only ASCII viewers supported
1739: - -tao_monitor_interval interval - only monitor function and residual norms every `interval` iterations, and the last iteration
1741: Level: advanced
1743: Note:
1744: This monitor prints the function value and gradient
1745: norm at each iteration.
1747: .seealso: [](ch_tao), `Tao`, `TaoMonitorGlobalization()`, `TaoMonitorSet()`
1748: @*/
1749: PetscErrorCode TaoMonitorDefault(Tao tao, PetscViewerAndFormat *vf)
1750: {
1751: PetscViewer viewer = vf->viewer;
1752: PetscBool isascii;
1753: PetscInt tabs;
1755: PetscFunctionBegin;
1757: if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
1759: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1760: PetscCall(PetscViewerPushFormat(viewer, vf->format));
1761: if (isascii) {
1762: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1764: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1765: if (tao->niter == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1766: PetscCall(PetscViewerASCIIPrintf(viewer, " Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1767: tao->header_printed = PETSC_TRUE;
1768: }
1769: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", tao->niter));
1770: PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)tao->fc));
1771: if (tao->residual >= PETSC_INFINITY) {
1772: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: infinity \n"));
1773: } else {
1774: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)tao->residual));
1775: }
1776: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1777: }
1778: PetscCall(PetscViewerPopFormat(viewer));
1779: PetscFunctionReturn(PETSC_SUCCESS);
1780: }
1782: /*@
1783: TaoMonitorGlobalization - Default routine for monitoring progress of `TaoSolve()` with extra detail on the globalization method.
1785: Collective
1787: Input Parameters:
1788: + tao - the `Tao` context
1789: - vf - `PetscViewerAndFormat` context
1791: Options Database Keys:
1792: + -tao_monitor_globalization [ascii][:filename] - monitor globalization information at each iteration, only ASCII viewers are supported
1793: - -tao_monitor_globalization_interval interval - only monitor globalization information every `interval` iterations, and the last iteration
1795: Level: advanced
1797: Note:
1798: This monitor prints the function value and gradient norm at each
1799: iteration, as well as the step size and trust radius. Note that the
1800: step size and trust radius may be the same for some algorithms.
1802: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1803: @*/
1804: PetscErrorCode TaoMonitorGlobalization(Tao tao, PetscViewerAndFormat *vf)
1805: {
1806: PetscViewer viewer = vf->viewer;
1807: PetscBool isascii;
1808: PetscInt tabs;
1810: PetscFunctionBegin;
1812: if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
1814: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1815: PetscCall(PetscViewerPushFormat(viewer, vf->format));
1816: if (isascii) {
1817: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1818: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1819: if (tao->niter == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1820: PetscCall(PetscViewerASCIIPrintf(viewer, " Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1821: tao->header_printed = PETSC_TRUE;
1822: }
1823: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", tao->niter));
1824: PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)tao->fc));
1825: if (tao->residual >= PETSC_INFINITY) {
1826: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf,"));
1827: } else {
1828: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g,", (double)tao->residual));
1829: }
1830: PetscCall(PetscViewerASCIIPrintf(viewer, " Step: %g, Trust: %g\n", (double)tao->step, (double)tao->trust));
1831: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1832: }
1833: PetscCall(PetscViewerPopFormat(viewer));
1834: PetscFunctionReturn(PETSC_SUCCESS);
1835: }
1837: /*@
1838: TaoMonitorConstraintNorm - same as `TaoMonitorDefault()` except
1839: it prints the norm of the constraint function.
1841: Collective
1843: Input Parameters:
1844: + tao - the `Tao` context
1845: - vf - `PetscViewerAndFormat` context
1847: Options Database Keys:
1848: + -tao_monitor_constraint_norm [ascii][:filename] - monitor the constraints at each iteration, only ASCII viewers are supported
1849: - -tao_monitor_constraint_norm_interval interval - only monitor the constraints every `interval` iterations, and the last iteration
1851: Level: advanced
1853: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1854: @*/
1855: PetscErrorCode TaoMonitorConstraintNorm(Tao tao, PetscViewerAndFormat *vf)
1856: {
1857: PetscViewer viewer = vf->viewer;
1858: PetscBool isascii;
1859: PetscInt tabs;
1861: PetscFunctionBegin;
1863: if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
1865: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1866: PetscCall(PetscViewerPushFormat(viewer, vf->format));
1867: if (isascii) {
1868: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1869: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1870: PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", tao->niter));
1871: PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)tao->fc));
1872: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g ", (double)tao->residual));
1873: PetscCall(PetscViewerASCIIPrintf(viewer, " Constraint: %g \n", (double)tao->cnorm));
1874: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1875: }
1876: PetscCall(PetscViewerPopFormat(viewer));
1877: PetscFunctionReturn(PETSC_SUCCESS);
1878: }
1880: /*@
1881: TaoMonitorSolution - Views the solution at each iteration of `TaoSolve()`
1883: Collective
1885: Input Parameters:
1886: + tao - the `Tao` context
1887: - vf - `PetscViewerAndFormat` context
1889: Options Database Keys:
1890: + -tao_monitor_solution viewer_specification - view the solution vector at each iteration, see `PetscOptionsCreateViewer()` for `viewer_specification` details
1891: - -tao_monitor_solution_interval interval - only view the solution every `interval` iterations, and the last iteration
1893: Level: advanced
1895: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1896: @*/
1897: PetscErrorCode TaoMonitorSolution(Tao tao, PetscViewerAndFormat *vf)
1898: {
1899: PetscFunctionBegin;
1901: if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
1902: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
1903: PetscCall(VecView(tao->solution, vf->viewer));
1904: PetscCall(PetscViewerPopFormat(vf->viewer));
1905: PetscFunctionReturn(PETSC_SUCCESS);
1906: }
1908: /*@
1909: TaoMonitorGradient - Views the gradient at each iteration of `TaoSolve()`
1911: Collective
1913: Input Parameters:
1914: + tao - the `Tao` context
1915: - vf - `PetscViewerAndFormat` context
1917: Options Database Keys:
1918: + -tao_monitor_gradient viewer_specification - view the gradient at each iteration, see `PetscOptionsCreateViewer()` for `viewer_specification` details
1919: - -tao_monitor_gradient_interval interval - only view the gradient every `interval` iterations, and the last iteration
1921: Level: advanced
1923: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1924: @*/
1925: PetscErrorCode TaoMonitorGradient(Tao tao, PetscViewerAndFormat *vf)
1926: {
1927: PetscFunctionBegin;
1929: if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
1930: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
1931: PetscCall(VecView(tao->gradient, vf->viewer));
1932: PetscCall(PetscViewerPopFormat(vf->viewer));
1933: PetscFunctionReturn(PETSC_SUCCESS);
1934: }
1936: /*@
1937: TaoMonitorStep - Views the step-direction at each iteration of `TaoSolve()`
1939: Collective
1941: Input Parameters:
1942: + tao - the `Tao` context
1943: - vf - `PetscViewerAndFormat` context
1945: Options Database Keys:
1946: + -tao_monitor_step viewer_specification - view the step vector at each iteration, see `PetscOptionsCreateViewer()` for `viewer_specification` details
1947: - -tao_monitor_step_interval interval - only view the step vector every `interval` iterations, and the last iteration
1949: Level: advanced
1951: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1952: @*/
1953: PetscErrorCode TaoMonitorStep(Tao tao, PetscViewerAndFormat *vf)
1954: {
1955: PetscFunctionBegin;
1957: if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
1958: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
1959: PetscCall(VecView(tao->stepdirection, vf->viewer));
1960: PetscCall(PetscViewerPopFormat(vf->viewer));
1961: PetscFunctionReturn(PETSC_SUCCESS);
1962: }
1964: /*@
1965: TaoMonitorSolutionDraw - Plots the solution at each iteration of `TaoSolve()`
1967: Collective
1969: Input Parameters:
1970: + tao - the `Tao` context
1971: - ctx - `TaoMonitorDrawCtx` context
1973: Options Database Keys:
1974: + -tao_monitor_solution_draw (true|false) - draw the solution at each iteration
1975: - -tao_monitor_solution_draw_interval interval - only draw the solution every `interval` iterations and final value, or only final value if negative
1977: Level: advanced
1979: Note:
1980: The context created by `TaoMonitorDrawCtxCreate()`, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
1981: are passed to `TaoMonitorSet()` to monitor the solution graphically.
1983: .seealso: [](ch_tao), `Tao`, `TaoMonitorSolution()`, `TaoMonitorSet()`, `TaoMonitorGradientDraw()`, `TaoMonitorDrawCtxCreate()`,
1984: `TaoMonitorDrawCtxDestroy()`
1985: @*/
1986: PetscErrorCode TaoMonitorSolutionDraw(Tao tao, PetscCtx ctx)
1987: {
1988: TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
1990: PetscFunctionBegin;
1992: if (!((ictx->howoften > 0 && !((tao->niter % ictx->howoften) && !tao->reason)) || (ictx->howoften < 0 && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1993: PetscCall(VecView(tao->solution, ictx->viewer));
1994: PetscFunctionReturn(PETSC_SUCCESS);
1995: }
1997: /*@
1998: TaoMonitorGradientDraw - Plots the gradient at each iteration of `TaoSolve()`
2000: Collective
2002: Input Parameters:
2003: + tao - the `Tao` context
2004: - ctx - `TaoMonitorDrawCtx` context
2006: Options Database Keys:
2007: + -tao_monitor_gradient_draw (true|false) - draw the gradient at each iteration
2008: - -tao_monitor_gradient_draw_interval interval - only draw the gradient every `interval` iterations and final value, or only final value if negative
2010: Level: advanced
2012: .seealso: [](ch_tao), `Tao`, `TaoMonitorGradient()`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw()`
2013: @*/
2014: PetscErrorCode TaoMonitorGradientDraw(Tao tao, PetscCtx ctx)
2015: {
2016: TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
2018: PetscFunctionBegin;
2020: if (!((ictx->howoften > 0 && !((tao->niter % ictx->howoften) && !tao->reason)) || (ictx->howoften < 0 && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
2021: PetscCall(VecView(tao->gradient, ictx->viewer));
2022: PetscFunctionReturn(PETSC_SUCCESS);
2023: }
2025: /*@
2026: TaoMonitorStepDraw - Plots the step direction at each iteration of `TaoSolve()`
2028: Collective
2030: Input Parameters:
2031: + tao - the `Tao` context
2032: - ctx - the `TaoMonitorDrawCtx` context
2034: Options Database Keys:
2035: + -tao_monitor_step_draw (true|false) - draw the step direction at each iteration
2036: - -tao_monitor_step_draw_interval interval - only draw the step direction every `interval` iterations and final value, or only final value if negative
2038: Level: advanced
2040: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw`
2041: @*/
2042: PetscErrorCode TaoMonitorStepDraw(Tao tao, PetscCtx ctx)
2043: {
2044: TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
2046: PetscFunctionBegin;
2048: if (!((ictx->howoften > 0 && !((tao->niter % ictx->howoften) && !tao->reason)) || (ictx->howoften < 0 && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
2049: PetscCall(VecView(tao->stepdirection, ictx->viewer));
2050: PetscFunctionReturn(PETSC_SUCCESS);
2051: }
2053: /*@
2054: TaoMonitorResidual - Views the least-squares residual at each iteration of `TaoSolve()`
2056: Collective
2058: Input Parameters:
2059: + tao - the `Tao` context
2060: - vf - `PetscViewerAndFormat` context
2062: Options Database Keys:
2063: + -tao_monitor_residual viewer_specification - view the least-squares residual at each iteration, see `PetscOptionsCreateViewer()` for `viewer_specification` details
2064: - -tao_monitor_residual_interval interval - only monitor the residual every `interval` iterations and final value, or only final value if negative
2066: Level: advanced
2068: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
2069: @*/
2070: PetscErrorCode TaoMonitorResidual(Tao tao, PetscViewerAndFormat *vf)
2071: {
2072: PetscFunctionBegin;
2074: if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
2075: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
2076: PetscCall(VecView(tao->ls_res, vf->viewer));
2077: PetscCall(PetscViewerPopFormat(vf->viewer));
2078: PetscFunctionReturn(PETSC_SUCCESS);
2079: }
2081: /*@
2082: TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
2083: or terminate.
2085: Collective
2087: Input Parameters:
2088: + tao - the `Tao` context
2089: - dummy - unused dummy context
2091: Level: developer
2093: Notes:
2094: This routine checks the residual in the optimality conditions, the
2095: relative residual in the optimity conditions, the number of function
2096: evaluations, and the function value to test convergence. Some
2097: solvers may use different convergence routines.
2099: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
2100: @*/
2101: PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
2102: {
2103: PetscInt niter = tao->niter, nfuncs;
2104: PetscInt max_funcs = tao->max_funcs;
2105: PetscReal gnorm = tao->residual, gnorm0 = tao->gnorm0;
2106: PetscReal f = tao->fc, steptol = tao->steptol, trradius = tao->step;
2107: PetscReal gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
2108: PetscReal catol = tao->catol, crtol = tao->crtol;
2109: PetscReal fmin = tao->fmin, cnorm = tao->cnorm;
2110: TaoConvergedReason reason = tao->reason;
2112: PetscFunctionBegin;
2114: if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);
2116: PetscCall(TaoGetCurrentFunctionEvaluations(tao, &nfuncs));
2117: if (PetscIsInfOrNanReal(f)) {
2118: PetscCall(PetscInfo(tao, "Failed to converged, function value is infinity or NaN\n"));
2119: reason = TAO_DIVERGED_NAN;
2120: } else if (f <= fmin && cnorm <= catol) {
2121: PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
2122: reason = TAO_CONVERGED_MINF;
2123: } else if (gnorm <= gatol && cnorm <= catol) {
2124: PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
2125: reason = TAO_CONVERGED_GATOL;
2126: } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
2127: PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
2128: reason = TAO_CONVERGED_GRTOL;
2129: } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
2130: PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
2131: reason = TAO_CONVERGED_GTTOL;
2132: } else if (max_funcs != PETSC_UNLIMITED && nfuncs > max_funcs) {
2133: PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
2134: reason = TAO_DIVERGED_MAXFCN;
2135: } else if (tao->lsflag != 0) {
2136: PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
2137: reason = TAO_DIVERGED_LS_FAILURE;
2138: } else if (trradius < steptol && niter > 0) {
2139: PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
2140: reason = TAO_CONVERGED_STEPTOL;
2141: } else if (niter >= tao->max_it) {
2142: PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
2143: reason = TAO_DIVERGED_MAXITS;
2144: } else {
2145: reason = TAO_CONTINUE_ITERATING;
2146: }
2147: tao->reason = reason;
2148: PetscFunctionReturn(PETSC_SUCCESS);
2149: }
2151: /*@
2152: TaoSetOptionsPrefix - Sets the prefix used for searching for all
2153: Tao options in the database.
2155: Logically Collective
2157: Input Parameters:
2158: + tao - the `Tao` context
2159: - p - the prefix string to prepend to all Tao option requests
2161: Level: advanced
2163: Notes:
2164: A hyphen (-) must NOT be given at the beginning of the prefix name.
2165: The first character of all runtime options is AUTOMATICALLY the hyphen.
2167: For example, to distinguish between the runtime options for two
2168: different Tao solvers, one could call
2169: .vb
2170: TaoSetOptionsPrefix(tao1,"sys1_")
2171: TaoSetOptionsPrefix(tao2,"sys2_")
2172: .ve
2174: This would enable use of different options for each system, such as
2175: .vb
2176: -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2177: -sys2_tao_method lmvm -sys2_tao_grtol 1.e-4
2178: .ve
2180: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2181: @*/
2182: PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2183: {
2184: PetscFunctionBegin;
2186: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2187: if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2188: if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2189: if (tao->callbacks) {
2190: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao->callbacks, p));
2191: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->callbacks, "callbacks_"));
2192: }
2193: PetscFunctionReturn(PETSC_SUCCESS);
2194: }
2196: /*@
2197: TaoAppendOptionsPrefix - Appends to the prefix used for searching for all Tao options in the database.
2199: Logically Collective
2201: Input Parameters:
2202: + tao - the `Tao` solver context
2203: - p - the prefix string to prepend to all `Tao` option requests
2205: Level: advanced
2207: Note:
2208: A hyphen (-) must NOT be given at the beginning of the prefix name.
2209: The first character of all runtime options is automatically the hyphen.
2211: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2212: @*/
2213: PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2214: {
2215: PetscFunctionBegin;
2217: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2218: if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2219: if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2220: if (tao->callbacks) {
2221: const char *prefix;
2223: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, &prefix));
2224: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao->callbacks, prefix));
2225: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->callbacks, "callbacks_"));
2226: }
2227: PetscFunctionReturn(PETSC_SUCCESS);
2228: }
2230: /*@
2231: TaoGetOptionsPrefix - Gets the prefix used for searching for all
2232: Tao options in the database
2234: Not Collective
2236: Input Parameter:
2237: . tao - the `Tao` context
2239: Output Parameter:
2240: . p - pointer to the prefix string used is returned
2242: Level: advanced
2244: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2245: @*/
2246: PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2247: {
2248: PetscFunctionBegin;
2250: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2251: PetscFunctionReturn(PETSC_SUCCESS);
2252: }
2254: /*@
2255: TaoSetType - Sets the `TaoType` for the minimization solver.
2257: Collective
2259: Input Parameters:
2260: + tao - the `Tao` solver context
2261: - type - a known method
2263: Options Database Key:
2264: . -tao_type type - Sets the method; see `TaoType`
2266: Level: intermediate
2268: Note:
2269: Calling this function resets the convergence test to `TaoDefaultConvergenceTest()`.
2270: If a custom convergence test has been set with `TaoSetConvergenceTest()`, it must
2271: be set again after calling `TaoSetType()`.
2273: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2274: @*/
2275: PetscErrorCode TaoSetType(Tao tao, TaoType type)
2276: {
2277: PetscErrorCode (*create_xxx)(Tao);
2278: PetscBool issame;
2280: PetscFunctionBegin;
2283: PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2284: if (issame) PetscFunctionReturn(PETSC_SUCCESS);
2286: PetscCall(PetscFunctionListFind(TaoList, type, &create_xxx));
2287: PetscCheck(create_xxx, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Tao type %s", type);
2289: /* Destroy the existing solver information */
2290: PetscTryTypeMethod(tao, destroy);
2291: PetscCall(KSPDestroy(&tao->ksp));
2292: PetscCall(TaoLineSearchDestroy(&tao->linesearch));
2294: /* Reinitialize type-specific function pointers in TaoOps structure */
2295: tao->ops->setup = NULL;
2296: tao->ops->computedual = NULL;
2297: tao->ops->solve = NULL;
2298: tao->ops->view = NULL;
2299: tao->ops->setfromoptions = NULL;
2300: tao->ops->destroy = NULL;
2301: tao->ops->convergencetest = TaoDefaultConvergenceTest;
2303: tao->setupcalled = PETSC_FALSE;
2304: tao->uses_gradient = PETSC_FALSE;
2305: tao->uses_hessian_matrices = PETSC_FALSE;
2307: PetscCall(TaoParametersInitialize(tao));
2309: PetscCall((*create_xxx)(tao));
2310: PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2311: PetscFunctionReturn(PETSC_SUCCESS);
2312: }
2314: /*@
2315: TaoRegister - Adds a method to the Tao package for minimization.
2317: Not Collective, No Fortran Support
2319: Input Parameters:
2320: + sname - name of a new user-defined solver
2321: - func - routine to create `TaoType` specific method context
2323: Calling sequence of `func`:
2324: . tao - the `Tao` object to be created
2326: Example Usage:
2327: .vb
2328: TaoRegister("my_solver", MySolverCreate);
2329: .ve
2331: Then, your solver can be chosen with the procedural interface via
2332: .vb
2333: TaoSetType(tao, "my_solver")
2334: .ve
2335: or at runtime via the option
2336: .vb
2337: -tao_type my_solver
2338: .ve
2340: Level: advanced
2342: Note:
2343: `TaoRegister()` may be called multiple times to add several user-defined solvers.
2345: .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2346: @*/
2347: PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao tao))
2348: {
2349: PetscFunctionBegin;
2350: PetscCall(TaoInitializePackage());
2351: PetscCall(PetscFunctionListAdd(&TaoList, sname, func));
2352: PetscFunctionReturn(PETSC_SUCCESS);
2353: }
2355: /*@
2356: TaoRegisterDestroy - Frees the list of minimization solvers that were
2357: registered by `TaoRegister()`.
2359: Not Collective
2361: Level: advanced
2363: .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2364: @*/
2365: PetscErrorCode TaoRegisterDestroy(void)
2366: {
2367: PetscFunctionBegin;
2368: PetscCall(PetscFunctionListDestroy(&TaoList));
2369: TaoRegisterAllCalled = PETSC_FALSE;
2370: PetscFunctionReturn(PETSC_SUCCESS);
2371: }
2373: /*@
2374: TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2375: at this time.
2377: Not Collective
2379: Input Parameter:
2380: . tao - the `Tao` context
2382: Output Parameter:
2383: . iter - iteration number
2385: Notes:
2386: For example, during the computation of iteration 2 this would return 1.
2388: Level: intermediate
2390: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2391: @*/
2392: PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2393: {
2394: PetscFunctionBegin;
2396: PetscAssertPointer(iter, 2);
2397: *iter = tao->niter;
2398: PetscFunctionReturn(PETSC_SUCCESS);
2399: }
2401: /*@
2402: TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2403: at this time.
2405: Not Collective
2407: Input Parameter:
2408: . tao - the `Tao` context
2410: Output Parameter:
2411: . value - the current value
2413: Level: intermediate
2415: Developer Notes:
2416: This is the 2-norm of the residual, we cannot use `TaoGetGradientNorm()` because that has
2417: a different meaning. For some reason `Tao` sometimes calls the gradient the residual.
2419: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2420: @*/
2421: PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2422: {
2423: PetscFunctionBegin;
2425: PetscAssertPointer(value, 2);
2426: *value = tao->residual;
2427: PetscFunctionReturn(PETSC_SUCCESS);
2428: }
2430: /*@
2431: TaoSetIterationNumber - Sets the current iteration number.
2433: Logically Collective
2435: Input Parameters:
2436: + tao - the `Tao` context
2437: - iter - iteration number
2439: Level: developer
2441: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2442: @*/
2443: PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2444: {
2445: PetscFunctionBegin;
2448: PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2449: tao->niter = iter;
2450: PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2451: PetscFunctionReturn(PETSC_SUCCESS);
2452: }
2454: /*@
2455: TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2456: completed. This number keeps accumulating if multiple solves
2457: are called with the `Tao` object.
2459: Not Collective
2461: Input Parameter:
2462: . tao - the `Tao` context
2464: Output Parameter:
2465: . iter - number of iterations
2467: Level: intermediate
2469: Note:
2470: The total iteration count is updated after each solve, if there is a current
2471: `TaoSolve()` in progress then those iterations are not included in the count
2473: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2474: @*/
2475: PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2476: {
2477: PetscFunctionBegin;
2479: PetscAssertPointer(iter, 2);
2480: *iter = tao->ntotalits;
2481: PetscFunctionReturn(PETSC_SUCCESS);
2482: }
2484: /*@
2485: TaoSetTotalIterationNumber - Sets the current total iteration number.
2487: Logically Collective
2489: Input Parameters:
2490: + tao - the `Tao` context
2491: - iter - the iteration number
2493: Level: developer
2495: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2496: @*/
2497: PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2498: {
2499: PetscFunctionBegin;
2502: PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2503: tao->ntotalits = iter;
2504: PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2505: PetscFunctionReturn(PETSC_SUCCESS);
2506: }
2508: /*@
2509: TaoSetConvergedReason - Sets the termination flag on a `Tao` object
2511: Logically Collective
2513: Input Parameters:
2514: + tao - the `Tao` context
2515: - reason - the `TaoConvergedReason`
2517: Level: intermediate
2519: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2520: @*/
2521: PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2522: {
2523: PetscFunctionBegin;
2526: tao->reason = reason;
2527: PetscFunctionReturn(PETSC_SUCCESS);
2528: }
2530: /*@
2531: TaoGetConvergedReason - Gets the reason the `TaoSolve()` was stopped.
2533: Not Collective
2535: Input Parameter:
2536: . tao - the `Tao` solver context
2538: Output Parameter:
2539: . reason - value of `TaoConvergedReason`
2541: Level: intermediate
2543: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`, `TaoGetConvergedReasonString()`
2544: @*/
2545: PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2546: {
2547: PetscFunctionBegin;
2549: PetscAssertPointer(reason, 2);
2550: *reason = tao->reason;
2551: PetscFunctionReturn(PETSC_SUCCESS);
2552: }
2554: /*@
2555: TaoGetConvergedReasonString - Return a human readable string for a `TaoConvergedReason`
2557: Not Collective
2559: Input Parameter:
2560: . tao - the `Tao` solver context
2562: Output Parameter:
2563: . strreason - a human readable string that describes the `Tao` converged reason
2565: Level: beginner
2567: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetConvergedReason()`
2568: @*/
2569: PetscErrorCode TaoGetConvergedReasonString(Tao tao, const char *strreason[])
2570: {
2571: PetscFunctionBegin;
2573: PetscAssertPointer(strreason, 2);
2574: *strreason = TaoConvergedReasons[tao->reason];
2575: PetscFunctionReturn(PETSC_SUCCESS);
2576: }
2578: /*@
2579: TaoGetSolutionStatus - Get the current iterate, objective value,
2580: residual, infeasibility, and termination from a `Tao` object
2582: Not Collective
2584: Input Parameter:
2585: . tao - the `Tao` context
2587: Output Parameters:
2588: + its - the current iterate number (>=0)
2589: . f - the current function value
2590: . gnorm - the square of the gradient norm, duality gap, or other measure indicating distance from optimality.
2591: . cnorm - the infeasibility of the current solution with regard to the constraints.
2592: . xdiff - the step length or trust region radius of the most recent iterate.
2593: - reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`
2595: Level: intermediate
2597: Notes:
2598: Tao returns the values set by the solvers in the routine `TaoMonitor()`.
2600: If any of the output arguments are set to `NULL`, no corresponding value will be returned.
2602: .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2603: @*/
2604: PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2605: {
2606: PetscFunctionBegin;
2608: if (its) *its = tao->niter;
2609: if (f) *f = tao->fc;
2610: if (gnorm) *gnorm = tao->residual;
2611: if (cnorm) *cnorm = tao->cnorm;
2612: if (reason) *reason = tao->reason;
2613: if (xdiff) *xdiff = tao->step;
2614: PetscFunctionReturn(PETSC_SUCCESS);
2615: }
2617: /*@
2618: TaoGetType - Gets the current `TaoType` being used in the `Tao` object
2620: Not Collective
2622: Input Parameter:
2623: . tao - the `Tao` solver context
2625: Output Parameter:
2626: . type - the `TaoType`
2628: Level: intermediate
2630: Note:
2631: `type` should not be retained for later use as it will be an invalid pointer if the `TaoType` of `tao` is changed.
2633: .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
2634: @*/
2635: PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2636: {
2637: PetscFunctionBegin;
2639: PetscAssertPointer(type, 2);
2640: *type = ((PetscObject)tao)->type_name;
2641: PetscFunctionReturn(PETSC_SUCCESS);
2642: }
2644: /*@
2645: TaoMonitor - Monitor the solver and the current solution. This
2646: routine will record the iteration number and residual statistics,
2647: and call any monitors specified by the user.
2649: Input Parameters:
2650: + tao - the `Tao` context
2651: . its - the current iterate number (>=0)
2652: . f - the current objective function value
2653: . res - the gradient norm, square root of the duality gap, or other measure indicating distance from optimality. This measure will be recorded and
2654: used for some termination tests.
2655: . cnorm - the infeasibility of the current solution with regard to the constraints.
2656: - steplength - multiple of the step direction added to the previous iterate.
2658: Options Database Key:
2659: . -tao_monitor - Use the default monitor, which prints statistics to standard output
2661: Level: developer
2663: .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoMonitorSet()`
2664: @*/
2665: PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2666: {
2667: PetscFunctionBegin;
2669: tao->fc = f;
2670: tao->residual = res;
2671: tao->cnorm = cnorm;
2672: tao->step = steplength;
2673: if (!its) {
2674: tao->cnorm0 = cnorm;
2675: tao->gnorm0 = res;
2676: }
2677: PetscCall(VecLockReadPush(tao->solution));
2678: for (PetscInt i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2679: PetscCall(VecLockReadPop(tao->solution));
2680: PetscFunctionReturn(PETSC_SUCCESS);
2681: }
2683: /*@
2684: TaoSetConvergenceHistory - Sets the array used to hold the convergence history.
2686: Logically Collective
2688: Input Parameters:
2689: + tao - the `Tao` solver context
2690: . obj - array to hold objective value history
2691: . resid - array to hold residual history
2692: . cnorm - array to hold constraint violation history
2693: . lits - integer array holds the number of linear iterations for each Tao iteration
2694: . na - size of `obj`, `resid`, and `cnorm`
2695: - reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2696: else it continues storing new values for new minimizations after the old ones
2698: Level: intermediate
2700: Notes:
2701: If set, `Tao` will fill the given arrays with the indicated
2702: information at each iteration. If 'obj','resid','cnorm','lits' are
2703: *all* `NULL` then space (using size `na`, or 1000 if `na` is `PETSC_DECIDE`) is allocated for the history.
2704: If not all are `NULL`, then only the non-`NULL` information categories
2705: will be stored, the others will be ignored.
2707: Any convergence information after iteration number 'na' will not be stored.
2709: This routine is useful, e.g., when running a code for purposes
2710: of accurate performance monitoring, when no I/O should be done
2711: during the section of code that is being timed.
2713: .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2714: @*/
2715: PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2716: {
2717: PetscFunctionBegin;
2719: if (obj) PetscAssertPointer(obj, 2);
2720: if (resid) PetscAssertPointer(resid, 3);
2721: if (cnorm) PetscAssertPointer(cnorm, 4);
2722: if (lits) PetscAssertPointer(lits, 5);
2724: if (na == PETSC_DECIDE || na == PETSC_CURRENT) na = 1000;
2725: if (!obj && !resid && !cnorm && !lits) {
2726: PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2727: tao->hist_malloc = PETSC_TRUE;
2728: }
2730: tao->hist_obj = obj;
2731: tao->hist_resid = resid;
2732: tao->hist_cnorm = cnorm;
2733: tao->hist_lits = lits;
2734: tao->hist_max = na;
2735: tao->hist_reset = reset;
2736: tao->hist_len = 0;
2737: PetscFunctionReturn(PETSC_SUCCESS);
2738: }
2740: /*@
2741: TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.
2743: Collective
2745: Input Parameter:
2746: . tao - the `Tao` context
2748: Output Parameters:
2749: + obj - array used to hold objective value history
2750: . resid - array used to hold residual history
2751: . cnorm - array used to hold constraint violation history
2752: . lits - integer array used to hold linear solver iteration count
2753: - nhist - size of `obj`, `resid`, `cnorm`, and `lits`
2755: Level: advanced
2757: Notes:
2758: This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2759: and `TaoSolve()`, otherwise it returns useless information.
2761: This routine is useful, e.g., when running a code for purposes
2762: of accurate performance monitoring, when no I/O should be done
2763: during the section of code that is being timed.
2765: Fortran Notes:
2766: The calling sequence is
2767: .vb
2768: call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2769: .ve
2770: In other words this gets the current number of entries in the history. Access the history through the array you passed to `TaoSetConvergenceHistory()`
2772: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2773: @*/
2774: PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2775: {
2776: PetscFunctionBegin;
2778: if (obj) *obj = tao->hist_obj;
2779: if (cnorm) *cnorm = tao->hist_cnorm;
2780: if (resid) *resid = tao->hist_resid;
2781: if (lits) *lits = tao->hist_lits;
2782: if (nhist) *nhist = tao->hist_len;
2783: PetscFunctionReturn(PETSC_SUCCESS);
2784: }
2786: /*@
2787: TaoSetApplicationContext - Sets the optional user-defined context for a `Tao` solver that can be accessed later, for example in the
2788: `Tao` callback functions with `TaoGetApplicationContext()`
2790: Logically Collective
2792: Input Parameters:
2793: + tao - the `Tao` context
2794: - ctx - the application context
2796: Level: intermediate
2798: Fortran Note:
2799: This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
2800: function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `TaoGetApplicationContext()` for
2801: an example.
2803: .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`
2804: @*/
2805: PetscErrorCode TaoSetApplicationContext(Tao tao, PetscCtx ctx)
2806: {
2807: PetscFunctionBegin;
2809: tao->ctx = ctx;
2810: PetscFunctionReturn(PETSC_SUCCESS);
2811: }
2813: /*@
2814: TaoGetApplicationContext - Gets the user-defined context for a `Tao` solver provided with `TaoSetApplicationContext()`
2816: Not Collective
2818: Input Parameter:
2819: . tao - the `Tao` context
2821: Output Parameter:
2822: . ctx - a pointer to the application context
2824: Level: intermediate
2826: Fortran Note:
2827: This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with
2828: .vb
2829: type(tUsertype), pointer :: ctx
2830: .ve
2832: .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2833: @*/
2834: PetscErrorCode TaoGetApplicationContext(Tao tao, PetscCtxRt ctx)
2835: {
2836: PetscFunctionBegin;
2838: PetscAssertPointer(ctx, 2);
2839: *(void **)ctx = tao->ctx;
2840: PetscFunctionReturn(PETSC_SUCCESS);
2841: }
2843: /*@
2844: TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient in some of the `Tao` algorithms
2846: Collective
2848: Input Parameters:
2849: + tao - the `Tao` context
2850: - M - matrix that defines the norm
2852: Level: beginner
2854: .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2855: @*/
2856: PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2857: {
2858: PetscFunctionBegin;
2861: PetscCall(PetscObjectReference((PetscObject)M));
2862: PetscCall(MatDestroy(&tao->gradient_norm));
2863: PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2864: tao->gradient_norm = M;
2865: PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2866: PetscFunctionReturn(PETSC_SUCCESS);
2867: }
2869: /*@
2870: TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient in some of the `Tao` algorithms
2872: Not Collective
2874: Input Parameter:
2875: . tao - the `Tao` context
2877: Output Parameter:
2878: . M - gradient norm
2880: Level: beginner
2882: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2883: @*/
2884: PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2885: {
2886: PetscFunctionBegin;
2888: PetscAssertPointer(M, 2);
2889: *M = tao->gradient_norm;
2890: PetscFunctionReturn(PETSC_SUCCESS);
2891: }
2893: /*@
2894: TaoGradientNorm - Compute the norm using the `NormType`, the user has selected
2896: Collective
2898: Input Parameters:
2899: + tao - the `Tao` context
2900: . gradient - the gradient
2901: - type - the norm type
2903: Output Parameter:
2904: . gnorm - the gradient norm
2906: Level: advanced
2908: Note:
2909: If `TaoSetGradientNorm()` has been set and `type` is `NORM_2` then the norm provided with `TaoSetGradientNorm()` is used.
2911: Developer Notes:
2912: Should be named `TaoComputeGradientNorm()`.
2914: The usage is a bit confusing, with `TaoSetGradientNorm()` plus `NORM_2` resulting in the computation of the user provided
2915: norm, perhaps a refactorization is in order.
2917: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2918: @*/
2919: PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2920: {
2921: PetscFunctionBegin;
2925: PetscAssertPointer(gnorm, 4);
2926: if (tao->gradient_norm) {
2927: PetscScalar gnorms;
2929: PetscCheck(type == NORM_2, PetscObjectComm((PetscObject)gradient), PETSC_ERR_ARG_WRONG, "Norm type must be NORM_2 if an inner product for the gradient norm is set.");
2930: PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2931: PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2932: *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2933: } else {
2934: PetscCall(VecNorm(gradient, type, gnorm));
2935: }
2936: PetscFunctionReturn(PETSC_SUCCESS);
2937: }
2939: /*@
2940: TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorSolutionDraw()`
2942: Collective
2944: Input Parameters:
2945: + comm - the communicator to share the context
2946: . host - the name of the X Windows host that will display the monitor
2947: . label - the label to put at the top of the display window
2948: . x - the horizontal coordinate of the lower left corner of the window to open
2949: . y - the vertical coordinate of the lower left corner of the window to open
2950: . m - the width of the window
2951: . n - the height of the window
2952: - howoften - how many `Tao` iterations between displaying the monitor information
2954: Output Parameter:
2955: . ctx - the monitor context
2957: Options Database Key:
2958: . -tao_monitor_solution_draw (true|false) - use `TaoMonitorSolutionDraw()` to monitor the solution
2960: Level: intermediate
2962: Note:
2963: The context this creates, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
2964: are passed to `TaoMonitorSet()`.
2966: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2967: @*/
2968: PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2969: {
2970: PetscFunctionBegin;
2971: PetscCall(PetscNew(ctx));
2972: PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
2973: PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
2974: (*ctx)->howoften = howoften;
2975: PetscFunctionReturn(PETSC_SUCCESS);
2976: }
2978: /*@
2979: TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorSolutionDraw()`
2981: Collective
2983: Input Parameter:
2984: . ictx - the monitor context
2986: Level: intermediate
2988: Note:
2989: This is passed to `TaoMonitorSet()` as the final argument, along with `TaoMonitorSolutionDraw()`, and the context
2990: obtained with `TaoMonitorDrawCtxCreate()`.
2992: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorSolutionDraw()`
2993: @*/
2994: PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2995: {
2996: PetscFunctionBegin;
2997: PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
2998: PetscCall(PetscFree(*ictx));
2999: PetscFunctionReturn(PETSC_SUCCESS);
3000: }
3002: /*@
3003: TaoGetTerm - Get the entire objective function of the `Tao` as a
3004: single `TaoTerm` in the form $\alpha f(Ax; p)$, where $\alpha$ is a scaling
3005: coefficient, $f$ is a `TaoTerm`, $A$ is an (optional) map and $p$ are the parameters of $f$.
3007: Not collective
3009: Input Parameter:
3010: . tao - a `Tao` context
3012: Output Parameters:
3013: + scale - the scale of the term
3014: . term - a `TaoTerm` for the real-valued function defining the objective
3015: . params - the vector of parameters for `term`, or `NULL` if no parameters were specified for `term`
3016: - map - a map from the solution space of `tao` to the solution space of `term`, if `NULL` then the map is the identity
3018: Level: intermediate
3020: Notes:
3021: If the objective function was defined by providing function callbacks directly to `Tao` (for example, with `TaoSetObjectiveAndGradient()`), then
3022: `TaoGetTerm` will return a `TaoTerm` with the type `TAOTERMCALLBACKS` that encapsulates
3023: those functions.
3025: If multiple `TaoTerms` were provided to `Tao` via, for example, `TaoAddTerm()`, or in combination with giving functions directly to `Tao`, then the type `TAOTERMSUM` is returned.
3027: .seealso: [](ch_tao), `Tao`, `TaoTerm`, `TAOTERMSUM`, `TaoAddTerm()`
3028: @*/
3029: PetscErrorCode TaoGetTerm(Tao tao, PetscReal *scale, TaoTerm *term, Vec *params, Mat *map)
3030: {
3031: PetscFunctionBegin;
3033: if (scale) PetscAssertPointer(scale, 2);
3034: if (term) PetscAssertPointer(term, 3);
3035: if (params) PetscAssertPointer(params, 4);
3036: if (map) PetscAssertPointer(map, 5);
3037: PetscCall(TaoTermMappingGetData(&tao->objective_term, NULL, scale, term, map));
3038: if (params) *params = tao->objective_parameters;
3039: PetscFunctionReturn(PETSC_SUCCESS);
3040: }
3042: /*@
3043: TaoAddTerm - Add a `term` to the objective function. If `Tao` is empty,
3044: `term` will be the objective of `Tao`.
3046: Collective
3048: Input Parameters:
3049: + tao - a `Tao` solver context
3050: . prefix - the prefix used for configuring the new term (if `NULL`, the index of the term will be used as a prefix, e.g. "0_", "1_", etc.)
3051: . scale - scaling coefficient for the new term
3052: . term - the real-valued function defining the new term
3053: . params - (optional) parameters for the new term. It is up to each implementation of `TaoTerm` to determine how it behaves when parameters are omitted.
3054: - map - (optional) a map from the `tao` solution space to the `term` solution space; if `NULL` the map is assumed to be the identity
3056: Level: beginner
3058: Notes:
3059: If the objective function was $f(x)$, after calling `TaoAddTerm()` it becomes
3060: $f(x) + \alpha g(Ax; p)$, where $\alpha$ is the `scale`, $g$ is the `term`, $A$ is the
3061: (optional) `map`, and $p$ are the (optional) `params` of $g$.
3063: The `map` $A$ transforms the `Tao` solution vector into the term's solution space.
3064: For example, if the `Tao` solution vector is $x \in \mathbb{R}^n$ and the mapping
3065: matrix is $A \in \mathbb{R}^{m \times n}$, then the term evaluates $g(Ax; p)$ with
3066: $Ax \in \mathbb{R}^m$. The term's solution space is therefore $\mathbb{R}^m$. If the map is
3067: `NULL`, the identity is used and the term's solution space must match the `Tao` solution space.
3068: `Tao` automatically applies the chain rule for gradients ($A^T \nabla g$) and Hessians
3069: ($A^T \nabla^2 g \, A$) with respect to $x$.
3071: The `params` $p$ are fixed data that are not optimized over. Some `TaoTermType`s
3072: require the parameter space to be related to the term's solution space (e.g., the same
3073: size); when a mapping matrix $A$ is used, the parameter space may depend on either the row
3074: or column space of $A$. See the documentation for each `TaoTermType`.
3076: Currently, `TaoAddTerm()` does not support bounded Newton solvers (`TAOBNK`,`TAOBNLS`,`TAOBNTL`,`TAOBNTR`,and `TAOBQNK`)
3078: .seealso: [](ch_tao), `Tao`, `TaoTerm`, `TAOTERMSUM`, `TaoGetTerm()`
3079: @*/
3080: PetscErrorCode TaoAddTerm(Tao tao, const char prefix[], PetscReal scale, TaoTerm term, Vec params, Mat map)
3081: {
3082: PetscBool is_sum, is_callback;
3083: PetscInt num_old_terms;
3084: Vec *vec_list = NULL;
3086: PetscFunctionBegin;
3088: if (prefix) PetscAssertPointer(prefix, 2);
3091: PetscCheckSameComm(tao, 1, term, 4);
3092: if (params) {
3094: PetscCheckSameComm(tao, 1, params, 5);
3095: }
3096: if (map) {
3098: PetscCheckSameComm(tao, 1, map, 6);
3099: }
3100: // If user is using TaoAddTerm, before setting any terms or callbacks,
3101: // then tao->objective_term.term is empty callback, which we want to remove.
3102: PetscCall(PetscObjectTypeCompare((PetscObject)tao->objective_term.term, TAOTERMCALLBACKS, &is_callback));
3103: PetscCall(PetscObjectTypeCompare((PetscObject)term, TAOTERMSUM, &is_sum));
3104: PetscCheck(!is_sum, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "TaoAddTerm does not support adding TAOTERMSUM");
3105: if (is_callback) {
3106: PetscBool is_obj, is_objgrad, is_grad;
3108: PetscCall(TaoTermIsObjectiveDefined(tao->objective_term.term, &is_obj));
3109: PetscCall(TaoTermIsObjectiveAndGradientDefined(tao->objective_term.term, &is_objgrad));
3110: PetscCall(TaoTermIsGradientDefined(tao->objective_term.term, &is_grad));
3111: // Empty callback term
3112: if (!(is_obj || is_objgrad || is_grad)) {
3113: PetscCall(TaoTermMappingSetData(&tao->objective_term, NULL, scale, term, map));
3114: PetscCall(PetscObjectReference((PetscObject)params));
3115: PetscCall(VecDestroy(&tao->objective_parameters));
3116: // Empty callback term. Destroy hessians, as they are not needed
3117: PetscCall(MatDestroy(&tao->hessian));
3118: PetscCall(MatDestroy(&tao->hessian_pre));
3119: tao->objective_parameters = params;
3120: tao->term_set = PETSC_TRUE;
3121: PetscFunctionReturn(PETSC_SUCCESS);
3122: }
3123: }
3124: PetscCall(PetscObjectTypeCompare((PetscObject)tao->objective_term.term, TAOTERMSUM, &is_sum));
3125: // One TaoTerm has been set. Create TAOTERMSUM to store that, and the new one
3126: if (!is_sum) {
3127: TaoTerm old_sum;
3128: const char *tao_prefix;
3129: const char *term_prefix;
3131: PetscCall(TaoTermDuplicate(tao->objective_term.term, TAOTERM_DUPLICATE_SIZEONLY, &old_sum));
3132: if (tao->objective_term.map) {
3133: VecType map_vectype;
3134: VecType param_vectype;
3135: PetscLayout cmap, param_layout;
3137: PetscCall(MatGetVecType(tao->objective_term.map, &map_vectype));
3138: PetscCall(MatGetLayouts(tao->objective_term.map, NULL, &cmap));
3139: PetscCall(TaoTermGetParametersVecType(old_sum, ¶m_vectype));
3140: PetscCall(TaoTermGetParametersLayout(old_sum, ¶m_layout));
3142: PetscCall(TaoTermSetSolutionVecType(old_sum, map_vectype));
3143: PetscCall(TaoTermSetParametersVecType(old_sum, param_vectype));
3144: PetscCall(TaoTermSetSolutionLayout(old_sum, cmap));
3145: PetscCall(TaoTermSetParametersLayout(old_sum, param_layout));
3146: }
3148: PetscCall(TaoTermSetType(old_sum, TAOTERMSUM));
3149: PetscCall(TaoGetOptionsPrefix(tao, &tao_prefix));
3150: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)old_sum, tao_prefix));
3151: PetscCall(TaoTermSumSetNumberTerms(old_sum, 1));
3152: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao->objective_term.term, &term_prefix));
3153: PetscCall(TaoTermSumSetTerm(old_sum, 0, term_prefix, tao->objective_term.scale, tao->objective_term.term, tao->objective_term.map));
3154: PetscCall(TaoTermSumSetTermHessianMatrices(old_sum, 0, NULL, NULL, tao->hessian, tao->hessian_pre));
3155: PetscCall(MatDestroy(&tao->hessian));
3156: PetscCall(MatDestroy(&tao->hessian_pre));
3157: PetscCall(TaoTermMappingReset(&tao->objective_term));
3158: PetscCall(TaoTermMappingSetData(&tao->objective_term, NULL, 1.0, old_sum, NULL));
3159: if (tao->objective_parameters) {
3160: // convert the parameters to a VECNEST
3161: Vec subvecs[1];
3163: subvecs[0] = tao->objective_parameters;
3164: tao->objective_parameters = NULL;
3165: PetscCall(TaoTermSumParametersPack(old_sum, subvecs, &tao->objective_parameters));
3166: PetscCall(VecDestroy(&subvecs[0]));
3167: }
3168: PetscCall(TaoTermDestroy(&old_sum));
3169: tao->num_terms = 1;
3170: }
3171: PetscCall(TaoTermSumGetNumberTerms(tao->objective_term.term, &num_old_terms));
3172: if (tao->objective_parameters || params) {
3173: PetscCall(PetscCalloc1(num_old_terms + 1, &vec_list));
3174: if (tao->objective_parameters) PetscCall(TaoTermSumParametersUnpack(tao->objective_term.term, &tao->objective_parameters, vec_list));
3175: PetscCall(PetscObjectReference((PetscObject)params));
3176: vec_list[num_old_terms] = params;
3177: }
3178: PetscCall(TaoTermSumAddTerm(tao->objective_term.term, prefix, scale, term, map, NULL));
3179: tao->num_terms++;
3180: if (vec_list) {
3181: PetscInt num_terms = num_old_terms + 1;
3182: PetscCall(TaoTermSumParametersPack(tao->objective_term.term, vec_list, &tao->objective_parameters));
3183: for (PetscInt i = 0; i < num_terms; i++) PetscCall(VecDestroy(&vec_list[i]));
3184: PetscCall(PetscFree(vec_list));
3185: }
3186: PetscFunctionReturn(PETSC_SUCCESS);
3187: }
3189: /*@
3190: TaoSetDM - Sets the `DM` that may be used by some `TAO` solvers or their underlying solvers and preconditioners
3192: Logically Collective
3194: Input Parameters:
3195: + tao - the nonlinear solver context
3196: - dm - the `DM`, cannot be `NULL`
3198: Level: intermediate
3200: Note:
3201: A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
3202: even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different
3203: problems using the same function space.
3205: .seealso: [](ch_snes), `DM`, `TAO`, `TaoGetDM()`, `SNESSetDM()`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
3206: @*/
3207: PetscErrorCode TaoSetDM(Tao tao, DM dm)
3208: {
3209: KSP ksp;
3211: PetscFunctionBegin;
3214: PetscCall(PetscObjectReference((PetscObject)dm));
3215: PetscCall(DMDestroy(&tao->dm));
3216: tao->dm = dm;
3218: PetscCall(TaoGetKSP(tao, &ksp));
3219: if (ksp) {
3220: PetscCall(KSPSetDM(ksp, dm));
3221: PetscCall(KSPSetDMActive(ksp, KSP_DMACTIVE_ALL, PETSC_FALSE));
3222: }
3223: PetscFunctionReturn(PETSC_SUCCESS);
3224: }
3226: /*@
3227: TaoGetDM - Gets the `DM` that may be used by some `TAO` solvers or their underlying solvers and preconditioners
3229: Not Collective but `dm` obtained is parallel on `tao`
3231: Input Parameter:
3232: . tao - the `TAO` context
3234: Output Parameter:
3235: . dm - the `DM`
3237: Level: intermediate
3239: .seealso: [](ch_snes), `DM`, `TAO`, `TaoSetDM()`, `SNESSetDM()`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
3240: @*/
3241: PetscErrorCode TaoGetDM(Tao tao, DM *dm)
3242: {
3243: PetscFunctionBegin;
3245: PetscAssertPointer(dm, 2);
3246: if (!tao->dm) PetscCall(DMShellCreate(PetscObjectComm((PetscObject)tao), &tao->dm));
3247: *dm = tao->dm;
3248: PetscFunctionReturn(PETSC_SUCCESS);
3249: }