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:   Level: advanced

360:   Note:
361:   See `SNESKSPSetUseEW()` for customization details.

363: .seealso: [](ch_tao), `Tao`, `SNESKSPSetUseEW()`
364: @*/
365: PetscErrorCode TaoKSPSetUseEW(Tao tao, PetscBool flag)
366: {
367:   PetscFunctionBegin;
370:   tao->ksp_ewconv = flag;
371:   PetscFunctionReturn(PETSC_SUCCESS);
372: }

374: /*@
375:   TaoMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user

377:   Collective

379:   Input Parameters:
380: + tao     - `Tao` object you wish to monitor
381: . name    - the monitor type one is seeking
382: . help    - message indicating what monitoring is done
383: . manual  - manual page for the monitor
384: - monitor - the monitor function, this must use a `PetscViewerFormat` as its context

386:   Level: developer

388: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
389:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
390:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
391:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
392:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
393:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
394:           `PetscOptionsFList()`, `PetscOptionsEList()`
395: @*/
396: PetscErrorCode TaoMonitorSetFromOptions(Tao tao, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(Tao, PetscViewerAndFormat *))
397: {
398:   PetscViewer       viewer;
399:   PetscViewerFormat format;
400:   PetscBool         flg;

402:   PetscFunctionBegin;
403:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)tao), ((PetscObject)tao)->options, ((PetscObject)tao)->prefix, name, &viewer, &format, &flg));
404:   if (flg) {
405:     PetscViewerAndFormat *vf;
406:     char                  interval_key[1024];

408:     PetscCall(PetscSNPrintf(interval_key, sizeof interval_key, "%s_interval", name));
409:     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
410:     vf->view_interval = 1;
411:     PetscCall(PetscOptionsGetInt(((PetscObject)tao)->options, ((PetscObject)tao)->prefix, interval_key, &vf->view_interval, NULL));

413:     PetscCall(PetscViewerDestroy(&viewer));
414:     PetscCall(TaoMonitorSet(tao, (PetscErrorCode (*)(Tao, PetscCtx))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
415:   }
416:   PetscFunctionReturn(PETSC_SUCCESS);
417: }

419: /*@
420:   TaoSetFromOptions - Sets various Tao parameters from the options database

422:   Collective

424:   Input Parameter:
425: . tao - the `Tao` solver context

427:   Options Database Keys:
428: + -tao_type type                                               - The algorithm that Tao uses (lmvm, nls, etc.)
429: . -tao_gatol gatol                                             - absolute error tolerance for ||gradient||
430: . -tao_grtol grtol                                             - relative error tolerance for ||gradient||
431: . -tao_gttol gttol                                             - reduction of ||gradient|| relative to initial gradient
432: . -tao_max_it max                                              - sets maximum number of iterations
433: . -tao_max_funcs max                                           - sets maximum number of function evaluations
434: . -tao_fmin fmin                                               - stop if function value reaches `fmin`
435: . -tao_steptol tol                                             - stop if trust region radius less than `tol`
436: . -tao_trust0 t                                                - initial trust region radius
437: . -tao_view_solution                                           - view the solution at the end of the optimization process
438: . -tao_monitor                                                 - prints function value and residual norm at each iteration
439: . -tao_monitor_interval interval                               - run the default monitor every `interval` iterations, and the last iteration
440: . -tao_monitor_short                                           - same as `-tao_monitor`, but truncates very small values
441: . -tao_monitor_short_interval interval                         - run the default short monitor every `interval` iterations, and the last iteration
442: . -tao_monitor_constraint_norm [ascii][:filename]              - prints objective value, gradient, and constraint norm at each iteration
443: . -tao_monitor_constraint_norm_interval interval               - run the constraint norm monitor every `interval` iterations, and the last iteration
444: . -tao_monitor_globalization                                   - prints information about the globalization at each iteration
445: . -tao_monitor_globalization_interval interval                 - run the globalization norm monitor every `interval` iterations, and the last iteration
446: . -tao_monitor_solution [viewertype][:filename][:viewerformat] - view solution vector at each iteration
447: . -tao_monitor_solution_interval interval                      - run the solution monitor every `interval` iterations, and the last iteration
448: . -tao_monitor_residual [viewertype][:filename][:viewerformat] - view least-squares residual vector at each iteration
449: . -tao_monitor_residual_interval interval                      - run the least-squares residual monitor every `interval` iterations, and the last iteration
450: . -tao_monitor_step [viewertype][:filename][:viewerformat]     - view step vector at each iteration
451: . -tao_monitor_step_interval interval                          - run the step monitor every `interval` iterations, and the last iteration
452: . -tao_monitor_gradient [viewertype][:filename][:viewerformat] - view gradient vector at each iteration
453: . -tao_monitor_gradient_interval interval                      - run the gradient monitor every `interval` iterations, and the last iteration
454: . -tao_monitor_solution_draw                                   - graphically view solution vector at each iteration
455: . -tao_monitor_solution_draw_interval interval                 - run the solution draw monitor every `interval` iterations, and the last iteration
456: . -tao_monitor_step_draw                                       - graphically view step vector at each iteration
457: . -tao_monitor_step_draw_interval interval                     - run the step draw monitor every `interval` iterations, and the last iteration
458: . -tao_monitor_gradient_draw                                   - graphically view gradient at each iteration
459: . -tao_monitor_gradient_draw_interval interval                 - run the gradient draw monitor every `interval` iterations, and the last iteration
460: . -tao_monitor_cancel                                          - cancels all monitors (except those set with command line)
461: . -tao_fd_gradient                                             - use gradient computed with finite differences
462: . -tao_fd_hessian                                              - use hessian computed with finite differences
463: . -tao_mf_hessian                                              - use matrix-free Hessian computed with finite differences
464: . -tao_recycle_history                                         - enable recycling/re-using information from the previous `TaoSolve()` call for some algorithms
465: . -tao_subset_type (subvec|mask|matrixfree)                    - the method to use for subsetting in active-set methods, the default is `subvec`
466: . -tao_ksp_ew                                                  - use Eisenstat-Walker linear system convergence test
467: . -tao_view                                                    - prints information about the Tao after solving
468: . -tao_converged_reason                                        - prints the reason Tao stopped iterating
469: - -tao_add_terms                                               - takes a comma-separated list of up to 16 options prefixes, a `TaoTerm` will be created for each and added to the objective function

471:   Level: beginner

473:   Notes:
474:   To see all options, run your program with the `-help` option or consult the
475:   user's manual. Should be called after `TaoCreate()` but before `TaoSolve()`.

477:   The `-tao_add_terms` option accepts at most 16 prefixes.

479: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
480: @*/
481: PetscErrorCode TaoSetFromOptions(Tao tao)
482: {
483:   TaoType   default_type = TAOLMVM;
484:   char      type[256];
485:   PetscBool flg, found;
486:   MPI_Comm  comm;
487:   PetscReal catol, crtol, gatol, grtol, gttol;

489:   PetscFunctionBegin;
491:   PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));

493:   if (((PetscObject)tao)->type_name) default_type = ((PetscObject)tao)->type_name;

495:   PetscObjectOptionsBegin((PetscObject)tao);
496:   /* Check for type from options */
497:   PetscCall(PetscOptionsFList("-tao_type", "Tao Solver type", "TaoSetType", TaoList, default_type, type, 256, &flg));
498:   if (flg) PetscCall(TaoSetType(tao, type));
499:   else if (!((PetscObject)tao)->type_name) PetscCall(TaoSetType(tao, default_type));

501:   /* Tao solvers do not set the prefix, set it here if not yet done
502:      We do it after SetType since solver may have been changed */
503:   if (tao->linesearch) {
504:     const char *prefix;
505:     PetscCall(TaoLineSearchGetOptionsPrefix(tao->linesearch, &prefix));
506:     if (!prefix) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, ((PetscObject)tao)->prefix));
507:   }

509:   catol = tao->catol;
510:   crtol = tao->crtol;
511:   PetscCall(PetscOptionsReal("-tao_catol", "Stop if constraints violations within", "TaoSetConstraintTolerances", tao->catol, &catol, NULL));
512:   PetscCall(PetscOptionsReal("-tao_crtol", "Stop if relative constraint violations within", "TaoSetConstraintTolerances", tao->crtol, &crtol, NULL));
513:   PetscCall(TaoSetConstraintTolerances(tao, catol, crtol));

515:   gatol = tao->gatol;
516:   grtol = tao->grtol;
517:   gttol = tao->gttol;
518:   PetscCall(PetscOptionsReal("-tao_gatol", "Stop if norm of gradient less than", "TaoSetTolerances", tao->gatol, &gatol, NULL));
519:   PetscCall(PetscOptionsReal("-tao_grtol", "Stop if norm of gradient divided by the function value is less than", "TaoSetTolerances", tao->grtol, &grtol, NULL));
520:   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, &gttol, NULL));
521:   PetscCall(TaoSetTolerances(tao, gatol, grtol, gttol));

523:   PetscCall(PetscOptionsInt("-tao_max_it", "Stop if iteration number exceeds", "TaoSetMaximumIterations", tao->max_it, &tao->max_it, &flg));
524:   if (flg) PetscCall(TaoSetMaximumIterations(tao, tao->max_it));

526:   PetscCall(PetscOptionsInt("-tao_max_funcs", "Stop if number of function evaluations exceeds", "TaoSetMaximumFunctionEvaluations", tao->max_funcs, &tao->max_funcs, &flg));
527:   if (flg) PetscCall(TaoSetMaximumFunctionEvaluations(tao, tao->max_funcs));

529:   PetscCall(PetscOptionsReal("-tao_fmin", "Stop if function less than", "TaoSetFunctionLowerBound", tao->fmin, &tao->fmin, NULL));
530:   PetscCall(PetscOptionsBoundedReal("-tao_steptol", "Stop if step size or trust region radius less than", "", tao->steptol, &tao->steptol, NULL, 0));
531:   PetscCall(PetscOptionsReal("-tao_trust0", "Initial trust region radius", "TaoSetInitialTrustRegionRadius", tao->trust0, &tao->trust0, &flg));
532:   if (flg) PetscCall(TaoSetInitialTrustRegionRadius(tao, tao->trust0));

534:   PetscCall(PetscOptionsDeprecated("-tao_solution_monitor", "-tao_monitor_solution", "3.21", NULL));
535:   PetscCall(PetscOptionsDeprecated("-tao_gradient_monitor", "-tao_monitor_gradient", "3.21", NULL));
536:   PetscCall(PetscOptionsDeprecated("-tao_stepdirection_monitor", "-tao_monitor_step", "3.21", NULL));
537:   PetscCall(PetscOptionsDeprecated("-tao_residual_monitor", "-tao_monitor_residual", "3.21", NULL));
538:   PetscCall(PetscOptionsDeprecated("-tao_smonitor", "-tao_monitor_short", "3.21", NULL));
539:   PetscCall(PetscOptionsDeprecated("-tao_cmonitor", "-tao_monitor_constraint_norm", "3.21", NULL));
540:   PetscCall(PetscOptionsDeprecated("-tao_gmonitor", "-tao_monitor_globalization", "3.21", NULL));
541:   PetscCall(PetscOptionsDeprecated("-tao_draw_solution", "-tao_monitor_solution_draw", "3.21", NULL));
542:   PetscCall(PetscOptionsDeprecated("-tao_draw_gradient", "-tao_monitor_gradient_draw", "3.21", NULL));
543:   PetscCall(PetscOptionsDeprecated("-tao_draw_step", "-tao_monitor_step_draw", "3.21", NULL));

545:   PetscCall(PetscOptionsBool("-tao_converged_reason", "Print reason for Tao converged", "TaoSolve", tao->printreason, &tao->printreason, NULL));

547:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_solution", "View solution vector after each iteration", "TaoMonitorSolution", TaoMonitorSolution));
548:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_gradient", "View gradient vector for each iteration", "TaoMonitorGradient", TaoMonitorGradient));

550:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_step", "View step vector after each iteration", "TaoMonitorStep", TaoMonitorStep));
551:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_residual", "View least-squares residual vector after each iteration", "TaoMonitorResidual", TaoMonitorResidual));
552:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor", "Use the default convergence monitor", "TaoMonitorDefault", TaoMonitorDefault));
553:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_globalization", "Use the convergence monitor with extra globalization info", "TaoMonitorGlobalization", TaoMonitorGlobalization));
554:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_short", "Use the short convergence monitor", "TaoMonitorDefaultShort", TaoMonitorDefaultShort));
555:   PetscCall(TaoMonitorSetFromOptions(tao, "-tao_monitor_constraint_norm", "Use the default convergence monitor with constraint norm", "TaoMonitorConstraintNorm", TaoMonitorConstraintNorm));

557:   flg = PETSC_FALSE;
558:   PetscCall(PetscOptionsDeprecated("-tao_cancelmonitors", "-tao_monitor_cancel", "3.21", NULL));
559:   PetscCall(PetscOptionsBool("-tao_monitor_cancel", "cancel all monitors and call any registered destroy routines", "TaoMonitorCancel", flg, &flg, NULL));
560:   if (flg) PetscCall(TaoMonitorCancel(tao));

562:   flg = PETSC_FALSE;
563:   PetscCall(PetscOptionsBool("-tao_monitor_solution_draw", "Plot solution vector at each iteration", "TaoMonitorSet", flg, &flg, NULL));
564:   if (flg) {
565:     TaoMonitorDrawCtx drawctx;
566:     PetscInt          howoften = 1;
567:     PetscCall(PetscOptionsInt("-tao_monitor_solution_draw_interval", "Only draw every interval iterations, and the final value", "TaoMonitorSet", howoften, &howoften, NULL));
568:     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
569:     PetscCall(TaoMonitorSet(tao, TaoMonitorSolutionDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
570:   }

572:   flg = PETSC_FALSE;
573:   PetscCall(PetscOptionsBool("-tao_monitor_step_draw", "Plots step at each iteration", "TaoMonitorSet", flg, &flg, NULL));
574:   if (flg) {
575:     TaoMonitorDrawCtx drawctx;
576:     PetscInt          howoften = 1;
577:     PetscCall(PetscOptionsInt("-tao_monitor_step_draw_interval", "Only draw every interval iterations, and the final value", "TaoMonitorSet", howoften, &howoften, NULL));
578:     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
579:     PetscCall(TaoMonitorSet(tao, TaoMonitorStepDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
580:   }

582:   flg = PETSC_FALSE;
583:   PetscCall(PetscOptionsBool("-tao_monitor_gradient_draw", "plots gradient at each iteration", "TaoMonitorSet", flg, &flg, NULL));
584:   if (flg) {
585:     TaoMonitorDrawCtx drawctx;
586:     PetscInt          howoften = 1;
587:     PetscCall(PetscOptionsInt("-tao_monitor_gradient_draw_interval", "Only draw every interval iterations, and the final value", "TaoMonitorSet", howoften, &howoften, NULL));
588:     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
589:     PetscCall(TaoMonitorSet(tao, TaoMonitorGradientDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
590:   }

592:   flg = PETSC_FALSE;
593:   PetscCall(PetscOptionsBool("-tao_fd_gradient", "compute gradient using finite differences", "TaoDefaultComputeGradient", flg, &flg, NULL));
594:   if (flg) PetscCall(TaoTermComputeGradientSetUseFD(tao->objective_term.term, PETSC_TRUE));
595:   flg = PETSC_FALSE;
596:   PetscCall(PetscOptionsBool("-tao_fd_hessian", "compute Hessian using finite differences", "TaoDefaultComputeHessian", flg, &flg, NULL));
597:   if (flg) {
598:     Mat H;

600:     PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
601:     PetscCall(MatSetType(H, MATAIJ));
602:     PetscCall(MatSetOption(H, MAT_SYMMETRIC, PETSC_TRUE));
603:     PetscCall(MatSetOption(H, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
604:     PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessian, NULL));
605:     PetscCall(TaoTermComputeHessianSetUseFD(tao->objective_term.term, PETSC_TRUE));
606:     PetscCall(MatDestroy(&H));
607:   }
608:   flg = PETSC_FALSE;
609:   PetscCall(PetscOptionsBool("-tao_mf_hessian", "compute matrix-free Hessian using finite differences", "TaoDefaultComputeHessianMFFD", flg, &flg, NULL));
610:   if (flg) {
611:     PetscBool is_callback;
612:     Mat       H;

614:     // Check that tao has only one TaoTerm with type TAOTERMCALLBACK
615:     PetscCall(PetscObjectTypeCompare((PetscObject)tao->objective_term.term, TAOTERMCALLBACKS, &is_callback));
616:     if (is_callback) {
617:       // Create Hessian via TaoTermCreateHessianMFFD
618:       PetscCall(TaoTermCreateHessianMFFD(tao->objective_term.term, &H));
619:       PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessianMFFD, NULL));
620:       PetscCall(MatDestroy(&H));
621:     } else {
622:       PetscCall(PetscInfo(tao, "-tao_mf_hessian only works when Tao has a single TAOTERMCALLBACK term. Ignoring.\n"));
623:     }
624:   }
625:   PetscCall(PetscOptionsBool("-tao_recycle_history", "enable recycling/re-using information from the previous TaoSolve() call for some algorithms", "TaoSetRecycleHistory", flg, &flg, &found));
626:   if (found) PetscCall(TaoSetRecycleHistory(tao, flg));
627:   PetscCall(PetscOptionsEnum("-tao_subset_type", "subset type", "", TaoSubsetTypes, (PetscEnum)tao->subset_type, (PetscEnum *)&tao->subset_type, NULL));

629:   if (tao->ksp) {
630:     PetscCall(PetscOptionsBool("-tao_ksp_ew", "Use Eisentat-Walker linear system convergence test", "TaoKSPSetUseEW", tao->ksp_ewconv, &tao->ksp_ewconv, NULL));
631:     PetscCall(TaoKSPSetUseEW(tao, tao->ksp_ewconv));
632:   }

634:   PetscCall(TaoTermSetFromOptions(tao->callbacks));

636:   {
637:     char    *term_prefixes[16];
638:     PetscInt n_terms = PETSC_STATIC_ARRAY_LENGTH(term_prefixes);

640:     PetscCall(PetscOptionsStringArray("-tao_add_terms", "a list of prefixes for terms to add to the Tao objective function", "TaoAddTerm", term_prefixes, &n_terms, NULL));
641:     for (PetscInt i = 0; i < n_terms; i++) {
642:       TaoTerm     term;
643:       const char *prefix;

645:       PetscCall(TaoTermDuplicate(tao->objective_term.term, TAOTERM_DUPLICATE_SIZEONLY, &term));
646:       PetscCall(TaoGetOptionsPrefix(tao, &prefix));
647:       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)term, prefix));
648:       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)term, term_prefixes[i]));
649:       PetscCall(TaoTermSetFromOptions(term));
650:       PetscCall(TaoAddTerm(tao, term_prefixes[i], 1.0, term, NULL, NULL));
651:       PetscCall(TaoTermDestroy(&term));
652:       PetscCall(PetscFree(term_prefixes[i]));
653:     }
654:   }

656:   if (tao->objective_term.term != tao->callbacks) PetscCall(TaoTermSetFromOptions(tao->objective_term.term));

658:   PetscTryTypeMethod(tao, setfromoptions, PetscOptionsObject);

660:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
661:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)tao, PetscOptionsObject));
662:   PetscOptionsEnd();

664:   if (tao->linesearch) PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
665:   PetscFunctionReturn(PETSC_SUCCESS);
666: }

668: /*@
669:   TaoViewFromOptions - View a `Tao` object based on values in the options database

671:   Collective

673:   Input Parameters:
674: + A    - the  `Tao` context
675: . obj  - Optional object that provides the prefix for the options database
676: - name - command line option

678:   Options Database Key:
679: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments

681:   Level: intermediate

683: .seealso: [](ch_tao), `Tao`, `TaoView`, `PetscObjectViewFromOptions()`, `TaoCreate()`
684: @*/
685: PetscErrorCode TaoViewFromOptions(Tao A, PetscObject obj, const char name[])
686: {
687:   PetscFunctionBegin;
689:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
690:   PetscFunctionReturn(PETSC_SUCCESS);
691: }

693: /*@
694:   TaoView - Prints information about the `Tao` object

696:   Collective

698:   Input Parameters:
699: + tao    - the `Tao` context
700: - viewer - visualization context

702:   Options Database Key:
703: . -tao_view - Calls `TaoView()` at the end of `TaoSolve()`

705:   Level: beginner

707:   Notes:
708:   The available visualization contexts include
709: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
710: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
711:   output where only the first processor opens
712:   the file.  All other processors send their
713:   data to the first processor to print.

715:   To view all the `TaoTerm` inside of `Tao`, use `PETSC_VIEWER_ASCII_INFO_DETAIL`,
716:   or pass `-tao_view ::ascii_info_detail` flag

718: .seealso: [](ch_tao), `Tao`, `PetscViewerASCIIOpen()`
719: @*/
720: PetscErrorCode TaoView(Tao tao, PetscViewer viewer)
721: {
722:   PetscBool isascii, isstring;
723:   TaoType   type;

725:   PetscFunctionBegin;
727:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)tao)->comm, &viewer));
729:   PetscCheckSameComm(tao, 1, viewer, 2);

731:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
732:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
733:   if (isascii) {
734:     PetscViewerFormat format;

736:     PetscCall(PetscViewerGetFormat(viewer, &format));
737:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)tao, viewer));

739:     PetscCall(PetscViewerASCIIPushTab(viewer));
740:     PetscTryTypeMethod(tao, view, viewer);
741:     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
742:       PetscCall(PetscViewerASCIIPrintf(viewer, "Objective function:\n"));
743:       PetscCall(PetscViewerASCIIPushTab(viewer));
744:       PetscCall(PetscViewerASCIIPrintf(viewer, "Scale (tao_objective_scale): %g\n", (double)tao->objective_term.scale));
745:       PetscCall(PetscViewerASCIIPrintf(viewer, "Function:\n"));
746:       PetscCall(PetscViewerASCIIPushTab(viewer));
747:       PetscCall(TaoTermView(tao->objective_term.term, viewer));
748:       PetscCall(PetscViewerASCIIPopTab(viewer));
749:       if (tao->objective_term.map) {
750:         PetscCall(PetscViewerASCIIPrintf(viewer, "Map:\n"));
751:         PetscCall(PetscViewerASCIIPushTab(viewer));
752:         PetscCall(MatView(tao->objective_term.map, viewer));
753:         PetscCall(PetscViewerASCIIPopTab(viewer));
754:       } else PetscCall(PetscViewerASCIIPrintf(viewer, "Map: unmapped\n"));
755:       PetscCall(PetscViewerASCIIPopTab(viewer));
756:     } else if (tao->num_terms > 0 || tao->term_set) {
757:       if (tao->objective_term.scale == 1.0 && tao->objective_term.map == NULL) {
758:         PetscCall(PetscViewerASCIIPrintf(viewer, "Objective function:\n"));
759:         PetscCall(PetscViewerASCIIPushTab(viewer));
760:         PetscCall(TaoTermView(tao->objective_term.term, viewer));
761:         PetscCall(PetscViewerASCIIPopTab(viewer));
762:       } else {
763:         PetscCall(PetscViewerASCIIPrintf(viewer, "Objective function:\n"));
764:         PetscCall(PetscViewerASCIIPushTab(viewer));
765:         if (tao->objective_term.scale != 1.0) PetscCall(PetscViewerASCIIPrintf(viewer, "Scale: %g\n", (double)tao->objective_term.scale));
766:         PetscCall(PetscViewerASCIIPrintf(viewer, "Function:\n"));
767:         PetscCall(PetscViewerASCIIPushTab(viewer));
768:         PetscCall(TaoTermView(tao->objective_term.term, viewer));
769:         PetscCall(PetscViewerASCIIPopTab(viewer));
770:         if (tao->objective_term.map) {
771:           PetscCall(PetscViewerASCIIPrintf(viewer, "Map:\n"));
772:           PetscCall(PetscViewerASCIIPushTab(viewer));
773:           PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO));
774:           PetscCall(MatView(tao->objective_term.map, viewer));
775:           PetscCall(PetscViewerPopFormat(viewer));
776:           PetscCall(PetscViewerASCIIPopTab(viewer));
777:         }
778:         PetscCall(PetscViewerASCIIPopTab(viewer));
779:       }
780:     }
781:     if (tao->linesearch) PetscCall(TaoLineSearchView(tao->linesearch, viewer));
782:     if (tao->ksp) {
783:       PetscCall(KSPView(tao->ksp, viewer));
784:       PetscCall(PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", tao->ksp_tot_its));
785:     }

787:     if (tao->XL || tao->XU) PetscCall(PetscViewerASCIIPrintf(viewer, "Active Set subset type: %s\n", TaoSubsetTypes[tao->subset_type]));

789:     PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: gatol=%g,", (double)tao->gatol));
790:     PetscCall(PetscViewerASCIIPrintf(viewer, " grtol=%g,", (double)tao->grtol));
791:     PetscCall(PetscViewerASCIIPrintf(viewer, " steptol=%g,", (double)tao->steptol));
792:     PetscCall(PetscViewerASCIIPrintf(viewer, " gttol=%g\n", (double)tao->gttol));
793:     PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Function/Gradient:=%g\n", (double)tao->residual));

795:     if (tao->constrained) {
796:       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances:"));
797:       PetscCall(PetscViewerASCIIPrintf(viewer, " catol=%g,", (double)tao->catol));
798:       PetscCall(PetscViewerASCIIPrintf(viewer, " crtol=%g\n", (double)tao->crtol));
799:       PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Constraints:=%g\n", (double)tao->cnorm));
800:     }

802:     if (tao->trust < tao->steptol) {
803:       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: steptol=%g\n", (double)tao->steptol));
804:       PetscCall(PetscViewerASCIIPrintf(viewer, "Final trust region radius:=%g\n", (double)tao->trust));
805:     }

807:     if (tao->fmin > -1.e25) PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: function minimum=%g\n", (double)tao->fmin));
808:     PetscCall(PetscViewerASCIIPrintf(viewer, "Objective value=%g\n", (double)tao->fc));

810:     PetscCall(PetscViewerASCIIPrintf(viewer, "total number of iterations=%" PetscInt_FMT ",          ", tao->niter));
811:     PetscCall(PetscViewerASCIIPrintf(viewer, "              (max: %" PetscInt_FMT ")\n", tao->max_it));

813:     if (tao->objective_term.term->nobj > 0) {
814:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT ",", tao->objective_term.term->nobj));
815:       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: unlimited)\n"));
816:       else PetscCall(PetscViewerASCIIPrintf(viewer, "               (max: %" PetscInt_FMT ")\n", tao->max_funcs));
817:     }
818:     if (tao->objective_term.term->ngrad > 0) {
819:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT ",", tao->objective_term.term->ngrad));
820:       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: unlimited)\n"));
821:       else PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: %" PetscInt_FMT ")\n", tao->max_funcs));
822:     }
823:     if (tao->objective_term.term->nobjgrad > 0) {
824:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT ",", tao->objective_term.term->nobjgrad));
825:       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "    (max: unlimited)\n"));
826:       else PetscCall(PetscViewerASCIIPrintf(viewer, "    (max: %" PetscInt_FMT ")\n", tao->max_funcs));
827:     }
828:     if (tao->nres > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of residual evaluations=%" PetscInt_FMT "\n", tao->nres));
829:     if (tao->objective_term.term->nhess > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", tao->objective_term.term->nhess));
830:     if (tao->nconstraints > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of constraint function evaluations=%" PetscInt_FMT "\n", tao->nconstraints));
831:     if (tao->njac > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Jacobian evaluations=%" PetscInt_FMT "\n", tao->njac));

833:     if (tao->reason > 0) {
834:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solution converged: "));
835:       switch (tao->reason) {
836:       case TAO_CONVERGED_GATOL:
837:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)|| <= gatol\n"));
838:         break;
839:       case TAO_CONVERGED_GRTOL:
840:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/|f(X)| <= grtol\n"));
841:         break;
842:       case TAO_CONVERGED_GTTOL:
843:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/||g(X0)|| <= gttol\n"));
844:         break;
845:       case TAO_CONVERGED_STEPTOL:
846:         PetscCall(PetscViewerASCIIPrintf(viewer, " Steptol -- step size small\n"));
847:         break;
848:       case TAO_CONVERGED_MINF:
849:         PetscCall(PetscViewerASCIIPrintf(viewer, " Minf --  f < fmin\n"));
850:         break;
851:       case TAO_CONVERGED_USER:
852:         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
853:         break;
854:       default:
855:         PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
856:         break;
857:       }
858:     } else if (tao->reason == TAO_CONTINUE_ITERATING) {
859:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solver never run\n"));
860:     } else {
861:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solver failed: "));
862:       switch (tao->reason) {
863:       case TAO_DIVERGED_MAXITS:
864:         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Iterations\n"));
865:         break;
866:       case TAO_DIVERGED_NAN:
867:         PetscCall(PetscViewerASCIIPrintf(viewer, " NaN or infinity encountered\n"));
868:         break;
869:       case TAO_DIVERGED_MAXFCN:
870:         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Function Evaluations\n"));
871:         break;
872:       case TAO_DIVERGED_LS_FAILURE:
873:         PetscCall(PetscViewerASCIIPrintf(viewer, " Line Search Failure\n"));
874:         break;
875:       case TAO_DIVERGED_TR_REDUCTION:
876:         PetscCall(PetscViewerASCIIPrintf(viewer, " Trust Region too small\n"));
877:         break;
878:       case TAO_DIVERGED_USER:
879:         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
880:         break;
881:       default:
882:         PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
883:         break;
884:       }
885:     }
886:     PetscCall(PetscViewerASCIIPopTab(viewer));
887:   } else if (isstring) {
888:     PetscCall(TaoGetType(tao, &type));
889:     PetscCall(PetscViewerStringSPrintf(viewer, " %-3.3s", type));
890:   }
891:   PetscFunctionReturn(PETSC_SUCCESS);
892: }

894: /*@
895:   TaoSetRecycleHistory - Sets the boolean flag to enable/disable re-using
896:   iterate information from the previous `TaoSolve()`. This feature is disabled by
897:   default.

899:   Logically Collective

901:   Input Parameters:
902: + tao     - the `Tao` context
903: - recycle - boolean flag

905:   Options Database Key:
906: . -tao_recycle_history (true|false) - reuse the history

908:   Level: intermediate

910:   Notes:
911:   For conjugate gradient methods (`TAOBNCG`), this re-uses the latest search direction
912:   from the previous `TaoSolve()` call when computing the first search direction in a
913:   new solution. By default, CG methods set the first search direction to the
914:   negative gradient.

916:   For quasi-Newton family of methods (`TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`), this re-uses
917:   the accumulated quasi-Newton Hessian approximation from the previous `TaoSolve()`
918:   call. By default, QN family of methods reset the initial Hessian approximation to
919:   the identity matrix.

921:   For any other algorithm, this setting has no effect.

923: .seealso: [](ch_tao), `Tao`, `TaoGetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
924: @*/
925: PetscErrorCode TaoSetRecycleHistory(Tao tao, PetscBool recycle)
926: {
927:   PetscFunctionBegin;
930:   tao->recycle = recycle;
931:   PetscFunctionReturn(PETSC_SUCCESS);
932: }

934: /*@
935:   TaoGetRecycleHistory - Retrieve the boolean flag for re-using iterate information
936:   from the previous `TaoSolve()`. This feature is disabled by default.

938:   Logically Collective

940:   Input Parameter:
941: . tao - the `Tao` context

943:   Output Parameter:
944: . recycle - boolean flag

946:   Level: intermediate

948: .seealso: [](ch_tao), `Tao`, `TaoSetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
949: @*/
950: PetscErrorCode TaoGetRecycleHistory(Tao tao, PetscBool *recycle)
951: {
952:   PetscFunctionBegin;
954:   PetscAssertPointer(recycle, 2);
955:   *recycle = tao->recycle;
956:   PetscFunctionReturn(PETSC_SUCCESS);
957: }

959: /*@
960:   TaoSetTolerances - Sets parameters used in `TaoSolve()` convergence tests

962:   Logically Collective

964:   Input Parameters:
965: + tao   - the `Tao` context
966: . gatol - stop if norm of gradient is less than this
967: . grtol - stop if relative norm of gradient is less than this
968: - gttol - stop if norm of gradient is reduced by this factor

970:   Options Database Keys:
971: + -tao_gatol gatol - Sets gatol
972: . -tao_grtol grtol - Sets grtol
973: - -tao_gttol gttol - Sets gttol

975:   Stopping Criteria\:
976: .vb
977:   ||g(X)||                            <= gatol
978:   ||g(X)|| / |f(X)|                   <= grtol
979:   ||g(X)|| / ||g(X0)||                <= gttol
980: .ve

982:   Level: beginner

984:   Notes:
985:   Use `PETSC_CURRENT` to leave one or more tolerances unchanged.

987:   Use `PETSC_DETERMINE` to set one or more tolerances to their values when the `tao`object's type was set

989:   Fortran Note:
990:   Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`

992: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`
993: @*/
994: PetscErrorCode TaoSetTolerances(Tao tao, PetscReal gatol, PetscReal grtol, PetscReal gttol)
995: {
996:   PetscFunctionBegin;

1002:   if (gatol == (PetscReal)PETSC_DETERMINE) {
1003:     tao->gatol = tao->default_gatol;
1004:   } else if (gatol != (PetscReal)PETSC_CURRENT) {
1005:     PetscCheck(gatol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gatol not allowed");
1006:     tao->gatol = gatol;
1007:   }

1009:   if (grtol == (PetscReal)PETSC_DETERMINE) {
1010:     tao->grtol = tao->default_grtol;
1011:   } else if (grtol != (PetscReal)PETSC_CURRENT) {
1012:     PetscCheck(grtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative grtol not allowed");
1013:     tao->grtol = grtol;
1014:   }

1016:   if (gttol == (PetscReal)PETSC_DETERMINE) {
1017:     tao->gttol = tao->default_gttol;
1018:   } else if (gttol != (PetscReal)PETSC_CURRENT) {
1019:     PetscCheck(gttol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gttol not allowed");
1020:     tao->gttol = gttol;
1021:   }
1022:   PetscFunctionReturn(PETSC_SUCCESS);
1023: }

1025: /*@
1026:   TaoSetConstraintTolerances - Sets constraint tolerance parameters used in `TaoSolve()` convergence tests

1028:   Logically Collective

1030:   Input Parameters:
1031: + tao   - the `Tao` context
1032: . catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for `gatol` convergence criteria
1033: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for `gatol`, `gttol` convergence criteria

1035:   Options Database Keys:
1036: + -tao_catol catol - Sets catol
1037: - -tao_crtol crtol - Sets crtol

1039:   Level: intermediate

1041:   Notes:
1042:   Use `PETSC_CURRENT` to leave one or tolerance unchanged.

1044:   Use `PETSC_DETERMINE` to set one or more tolerances to their values when the `tao` object's type was set

1046:   Fortran Note:
1047:   Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`

1049: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoGetConstraintTolerances()`, `TaoSetTolerances()`
1050: @*/
1051: PetscErrorCode TaoSetConstraintTolerances(Tao tao, PetscReal catol, PetscReal crtol)
1052: {
1053:   PetscFunctionBegin;

1058:   if (catol == (PetscReal)PETSC_DETERMINE) {
1059:     tao->catol = tao->default_catol;
1060:   } else if (catol != (PetscReal)PETSC_CURRENT) {
1061:     PetscCheck(catol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative catol not allowed");
1062:     tao->catol = catol;
1063:   }

1065:   if (crtol == (PetscReal)PETSC_DETERMINE) {
1066:     tao->crtol = tao->default_crtol;
1067:   } else if (crtol != (PetscReal)PETSC_CURRENT) {
1068:     PetscCheck(crtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative crtol not allowed");
1069:     tao->crtol = crtol;
1070:   }
1071:   PetscFunctionReturn(PETSC_SUCCESS);
1072: }

1074: /*@
1075:   TaoGetConstraintTolerances - Gets constraint tolerance parameters used in `TaoSolve()` convergence tests

1077:   Not Collective

1079:   Input Parameter:
1080: . tao - the `Tao` context

1082:   Output Parameters:
1083: + catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for `gatol` convergence criteria
1084: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for `gatol`, `gttol` convergence criteria

1086:   Level: intermediate

1088: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoSetTolerances()`, `TaoSetConstraintTolerances()`
1089: @*/
1090: PetscErrorCode TaoGetConstraintTolerances(Tao tao, PetscReal *catol, PetscReal *crtol)
1091: {
1092:   PetscFunctionBegin;
1094:   if (catol) *catol = tao->catol;
1095:   if (crtol) *crtol = tao->crtol;
1096:   PetscFunctionReturn(PETSC_SUCCESS);
1097: }

1099: /*@
1100:   TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
1101:   When an approximate solution with an objective value below this number
1102:   has been found, the solver will terminate.

1104:   Logically Collective

1106:   Input Parameters:
1107: + tao  - the Tao solver context
1108: - fmin - the tolerance

1110:   Options Database Key:
1111: . -tao_fmin fmin - sets the minimum function value

1113:   Level: intermediate

1115: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetTolerances()`
1116: @*/
1117: PetscErrorCode TaoSetFunctionLowerBound(Tao tao, PetscReal fmin)
1118: {
1119:   PetscFunctionBegin;
1122:   tao->fmin = fmin;
1123:   PetscFunctionReturn(PETSC_SUCCESS);
1124: }

1126: /*@
1127:   TaoGetFunctionLowerBound - Gets the bound on the solution objective value.
1128:   When an approximate solution with an objective value below this number
1129:   has been found, the solver will terminate.

1131:   Not Collective

1133:   Input Parameter:
1134: . tao - the `Tao` solver context

1136:   Output Parameter:
1137: . fmin - the minimum function value

1139:   Level: intermediate

1141: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetFunctionLowerBound()`
1142: @*/
1143: PetscErrorCode TaoGetFunctionLowerBound(Tao tao, PetscReal *fmin)
1144: {
1145:   PetscFunctionBegin;
1147:   PetscAssertPointer(fmin, 2);
1148:   *fmin = tao->fmin;
1149:   PetscFunctionReturn(PETSC_SUCCESS);
1150: }

1152: /*@
1153:   TaoSetMaximumFunctionEvaluations - Sets a maximum number of function evaluations allowed for a `TaoSolve()`.

1155:   Logically Collective

1157:   Input Parameters:
1158: + tao  - the `Tao` solver context
1159: - nfcn - the maximum number of function evaluations (>=0), use `PETSC_UNLIMITED` to have no bound

1161:   Options Database Key:
1162: . -tao_max_funcs nfcn - sets the maximum number of function evaluations

1164:   Level: intermediate

1166:   Note:
1167:   Use `PETSC_DETERMINE` to use the default maximum number of function evaluations that was set when the object type was set.

1169:   Developer Note:
1170:   Deprecated support for an unlimited number of function evaluations by passing a negative value.

1172: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumIterations()`
1173: @*/
1174: PetscErrorCode TaoSetMaximumFunctionEvaluations(Tao tao, PetscInt nfcn)
1175: {
1176:   PetscFunctionBegin;
1179:   if (nfcn == PETSC_DETERMINE) {
1180:     tao->max_funcs = tao->default_max_funcs;
1181:   } else if (nfcn == PETSC_UNLIMITED || nfcn < 0) {
1182:     tao->max_funcs = PETSC_UNLIMITED;
1183:   } else {
1184:     PetscCheck(nfcn >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations  must be positive");
1185:     tao->max_funcs = nfcn;
1186:   }
1187:   PetscFunctionReturn(PETSC_SUCCESS);
1188: }

1190: /*@
1191:   TaoGetMaximumFunctionEvaluations - Gets a maximum number of function evaluations allowed for a `TaoSolve()`

1193:   Logically Collective

1195:   Input Parameter:
1196: . tao - the `Tao` solver context

1198:   Output Parameter:
1199: . nfcn - the maximum number of function evaluations

1201:   Level: intermediate

1203: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1204: @*/
1205: PetscErrorCode TaoGetMaximumFunctionEvaluations(Tao tao, PetscInt *nfcn)
1206: {
1207:   PetscFunctionBegin;
1209:   PetscAssertPointer(nfcn, 2);
1210:   *nfcn = tao->max_funcs;
1211:   PetscFunctionReturn(PETSC_SUCCESS);
1212: }

1214: /*@
1215:   TaoGetCurrentFunctionEvaluations - Get current number of function evaluations used by a `Tao` object

1217:   Not Collective

1219:   Input Parameter:
1220: . tao - the `Tao` solver context

1222:   Output Parameter:
1223: . nfuncs - the current number of function evaluations (maximum between gradient and function evaluations)

1225:   Level: intermediate

1227: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1228: @*/
1229: PetscErrorCode TaoGetCurrentFunctionEvaluations(Tao tao, PetscInt *nfuncs)
1230: {
1231:   PetscFunctionBegin;
1233:   PetscAssertPointer(nfuncs, 2);
1234:   *nfuncs = PetscMax(tao->objective_term.term->nobj, tao->objective_term.term->nobjgrad);
1235:   PetscFunctionReturn(PETSC_SUCCESS);
1236: }

1238: /*@
1239:   TaoSetMaximumIterations - Sets a maximum number of iterates to be used in `TaoSolve()`

1241:   Logically Collective

1243:   Input Parameters:
1244: + tao    - the `Tao` solver context
1245: - maxits - the maximum number of iterates (>=0), use `PETSC_UNLIMITED` to have no bound

1247:   Options Database Key:
1248: . -tao_max_it its - sets the maximum number of iterations

1250:   Level: intermediate

1252:   Note:
1253:   Use `PETSC_DETERMINE` to use the default maximum number of iterations that was set when the object's type was set.

1255:   Developer Note:
1256:   Also accepts the deprecated negative values to indicate no limit

1258: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumFunctionEvaluations()`
1259: @*/
1260: PetscErrorCode TaoSetMaximumIterations(Tao tao, PetscInt maxits)
1261: {
1262:   PetscFunctionBegin;
1265:   if (maxits == PETSC_DETERMINE) {
1266:     tao->max_it = tao->default_max_it;
1267:   } else if (maxits == PETSC_UNLIMITED) {
1268:     tao->max_it = PETSC_INT_MAX;
1269:   } else {
1270:     PetscCheck(maxits > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations must be positive");
1271:     tao->max_it = maxits;
1272:   }
1273:   PetscFunctionReturn(PETSC_SUCCESS);
1274: }

1276: /*@
1277:   TaoGetMaximumIterations - Gets a maximum number of iterates that will be used

1279:   Not Collective

1281:   Input Parameter:
1282: . tao - the `Tao` solver context

1284:   Output Parameter:
1285: . maxits - the maximum number of iterates

1287:   Level: intermediate

1289: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumIterations()`, `TaoGetMaximumFunctionEvaluations()`
1290: @*/
1291: PetscErrorCode TaoGetMaximumIterations(Tao tao, PetscInt *maxits)
1292: {
1293:   PetscFunctionBegin;
1295:   PetscAssertPointer(maxits, 2);
1296:   *maxits = tao->max_it;
1297:   PetscFunctionReturn(PETSC_SUCCESS);
1298: }

1300: /*@
1301:   TaoSetInitialTrustRegionRadius - Sets the initial trust region radius.

1303:   Logically Collective

1305:   Input Parameters:
1306: + tao    - a `Tao` optimization solver
1307: - radius - the trust region radius

1309:   Options Database Key:
1310: . -tao_trust0 radius - sets initial trust region radius

1312:   Level: intermediate

1314:   Note:
1315:   Use `PETSC_DETERMINE` to use the default radius that was set when the object's type was set.

1317: .seealso: [](ch_tao), `Tao`, `TaoGetTrustRegionRadius()`, `TaoSetTrustRegionTolerance()`, `TAONTR`
1318: @*/
1319: PetscErrorCode TaoSetInitialTrustRegionRadius(Tao tao, PetscReal radius)
1320: {
1321:   PetscFunctionBegin;
1324:   if (radius == PETSC_DETERMINE) {
1325:     tao->trust0 = tao->default_trust0;
1326:   } else {
1327:     PetscCheck(radius > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Radius must be positive");
1328:     tao->trust0 = radius;
1329:   }
1330:   PetscFunctionReturn(PETSC_SUCCESS);
1331: }

1333: /*@
1334:   TaoGetInitialTrustRegionRadius - Gets the initial trust region radius.

1336:   Not Collective

1338:   Input Parameter:
1339: . tao - a `Tao` optimization solver

1341:   Output Parameter:
1342: . radius - the trust region radius

1344:   Level: intermediate

1346: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetCurrentTrustRegionRadius()`, `TAONTR`
1347: @*/
1348: PetscErrorCode TaoGetInitialTrustRegionRadius(Tao tao, PetscReal *radius)
1349: {
1350:   PetscFunctionBegin;
1352:   PetscAssertPointer(radius, 2);
1353:   *radius = tao->trust0;
1354:   PetscFunctionReturn(PETSC_SUCCESS);
1355: }

1357: /*@
1358:   TaoGetCurrentTrustRegionRadius - Gets the current trust region radius.

1360:   Not Collective

1362:   Input Parameter:
1363: . tao - a `Tao` optimization solver

1365:   Output Parameter:
1366: . radius - the trust region radius

1368:   Level: intermediate

1370: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetInitialTrustRegionRadius()`, `TAONTR`
1371: @*/
1372: PetscErrorCode TaoGetCurrentTrustRegionRadius(Tao tao, PetscReal *radius)
1373: {
1374:   PetscFunctionBegin;
1376:   PetscAssertPointer(radius, 2);
1377:   *radius = tao->trust;
1378:   PetscFunctionReturn(PETSC_SUCCESS);
1379: }

1381: /*@
1382:   TaoGetTolerances - gets the current values of some tolerances used for the convergence testing of `TaoSolve()`

1384:   Not Collective

1386:   Input Parameter:
1387: . tao - the `Tao` context

1389:   Output Parameters:
1390: + gatol - stop if norm of gradient is less than this
1391: . grtol - stop if relative norm of gradient is less than this
1392: - gttol - stop if norm of gradient is reduced by a this factor

1394:   Level: intermediate

1396:   Note:
1397:   `NULL` can be used as an argument if not all tolerances values are needed

1399: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`
1400: @*/
1401: PetscErrorCode TaoGetTolerances(Tao tao, PetscReal *gatol, PetscReal *grtol, PetscReal *gttol)
1402: {
1403:   PetscFunctionBegin;
1405:   if (gatol) *gatol = tao->gatol;
1406:   if (grtol) *grtol = tao->grtol;
1407:   if (gttol) *gttol = tao->gttol;
1408:   PetscFunctionReturn(PETSC_SUCCESS);
1409: }

1411: /*@
1412:   TaoGetKSP - Gets the linear solver used by the optimization solver.

1414:   Not Collective

1416:   Input Parameter:
1417: . tao - the `Tao` solver

1419:   Output Parameter:
1420: . ksp - the `KSP` linear solver used in the optimization solver

1422:   Level: intermediate

1424: .seealso: [](ch_tao), `Tao`, `KSP`
1425: @*/
1426: PetscErrorCode TaoGetKSP(Tao tao, KSP *ksp)
1427: {
1428:   PetscFunctionBegin;
1430:   PetscAssertPointer(ksp, 2);
1431:   *ksp = tao->ksp;
1432:   PetscFunctionReturn(PETSC_SUCCESS);
1433: }

1435: /*@
1436:   TaoGetLinearSolveIterations - Gets the total number of linear iterations
1437:   used by the `Tao` solver

1439:   Not Collective

1441:   Input Parameter:
1442: . tao - the `Tao` context

1444:   Output Parameter:
1445: . lits - number of linear iterations

1447:   Level: intermediate

1449:   Note:
1450:   This counter is reset to zero for each successive call to `TaoSolve()`

1452: .seealso: [](ch_tao), `Tao`, `TaoGetKSP()`
1453: @*/
1454: PetscErrorCode TaoGetLinearSolveIterations(Tao tao, PetscInt *lits)
1455: {
1456:   PetscFunctionBegin;
1458:   PetscAssertPointer(lits, 2);
1459:   *lits = tao->ksp_tot_its;
1460:   PetscFunctionReturn(PETSC_SUCCESS);
1461: }

1463: /*@
1464:   TaoGetLineSearch - Gets the line search used by the optimization solver.

1466:   Not Collective

1468:   Input Parameter:
1469: . tao - the `Tao` solver

1471:   Output Parameter:
1472: . ls - the line search used in the optimization solver

1474:   Level: intermediate

1476: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`
1477: @*/
1478: PetscErrorCode TaoGetLineSearch(Tao tao, TaoLineSearch *ls)
1479: {
1480:   PetscFunctionBegin;
1482:   PetscAssertPointer(ls, 2);
1483:   *ls = tao->linesearch;
1484:   PetscFunctionReturn(PETSC_SUCCESS);
1485: }

1487: /*@
1488:   TaoAddLineSearchCounts - Adds the number of function evaluations spent
1489:   in the line search to the running total.

1491:   Input Parameters:
1492: . tao - the `Tao` solver

1494:   Level: developer

1496: .seealso: [](ch_tao), `Tao`, `TaoGetLineSearch()`, `TaoLineSearchApply()`
1497: @*/
1498: PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1499: {
1500:   PetscBool flg;
1501:   PetscInt  nfeval, ngeval, nfgeval;

1503:   PetscFunctionBegin;
1505:   if (tao->linesearch) {
1506:     PetscCall(TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg));
1507:     if (!flg) {
1508:       PetscCall(TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval));
1509:       tao->objective_term.term->nobj += nfeval;
1510:       tao->objective_term.term->ngrad += ngeval;
1511:       tao->objective_term.term->nobjgrad += nfgeval;
1512:     }
1513:   }
1514:   PetscFunctionReturn(PETSC_SUCCESS);
1515: }

1517: /*@
1518:   TaoGetSolution - Returns the vector with the current solution from the `Tao` object

1520:   Not Collective

1522:   Input Parameter:
1523: . tao - the `Tao` context

1525:   Output Parameter:
1526: . X - the current solution

1528:   Level: intermediate

1530:   Note:
1531:   The returned vector will be the same object that was passed into `TaoSetSolution()`

1533: .seealso: [](ch_tao), `Tao`, `TaoSetSolution()`, `TaoSolve()`
1534: @*/
1535: PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1536: {
1537:   PetscFunctionBegin;
1539:   PetscAssertPointer(X, 2);
1540:   *X = tao->solution;
1541:   PetscFunctionReturn(PETSC_SUCCESS);
1542: }

1544: /*@
1545:   TaoResetStatistics - Initialize the statistics collected by the `Tao` object.
1546:   These statistics include the iteration number, residual norms, and convergence status.
1547:   This routine gets called before solving each optimization problem.

1549:   Collective

1551:   Input Parameter:
1552: . tao - the `Tao` context

1554:   Level: developer

1556:   Note:
1557:   This function does not reset the statistics of internal `TaoTerm`

1559: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
1560: @*/
1561: PetscErrorCode TaoResetStatistics(Tao tao)
1562: {
1563:   PetscFunctionBegin;
1565:   tao->niter        = 0;
1566:   tao->nres         = 0;
1567:   tao->njac         = 0;
1568:   tao->nconstraints = 0;
1569:   tao->ksp_its      = 0;
1570:   tao->ksp_tot_its  = 0;
1571:   tao->reason       = TAO_CONTINUE_ITERATING;
1572:   tao->residual     = 0.0;
1573:   tao->cnorm        = 0.0;
1574:   tao->step         = 0.0;
1575:   tao->lsflag       = PETSC_FALSE;
1576:   if (tao->hist_reset) tao->hist_len = 0;
1577:   PetscFunctionReturn(PETSC_SUCCESS);
1578: }

1580: /*@
1581:   TaoSetUpdate - Sets the general-purpose update function called
1582:   at the beginning of every iteration of the optimization algorithm. Called after the new solution and the gradient
1583:   is determined, but before the Hessian is computed (if applicable).

1585:   Logically Collective

1587:   Input Parameters:
1588: + tao  - The `Tao` solver
1589: . func - The function
1590: - ctx  - The update function context

1592:   Calling sequence of `func`:
1593: + tao - The optimizer context
1594: . it  - The current iteration index
1595: - ctx - The update context

1597:   Level: advanced

1599:   Notes:
1600:   Users can modify the gradient direction or any other vector associated to the specific solver used.
1601:   The objective function value is always recomputed after a call to the update hook.

1603: .seealso: [](ch_tao), `Tao`, `TaoSolve()`
1604: @*/
1605: PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao tao, PetscInt it, PetscCtx ctx), PetscCtx ctx)
1606: {
1607:   PetscFunctionBegin;
1609:   tao->ops->update = func;
1610:   tao->user_update = ctx;
1611:   PetscFunctionReturn(PETSC_SUCCESS);
1612: }

1614: /*@
1615:   TaoSetConvergenceTest - Sets the function that is to be used to test
1616:   for convergence of the iterative minimization solution.  The new convergence
1617:   testing routine will replace Tao's default convergence test.

1619:   Logically Collective

1621:   Input Parameters:
1622: + tao  - the `Tao` object
1623: . conv - the routine to test for convergence
1624: - ctx  - [optional] context for private data for the convergence routine (may be `NULL`)

1626:   Calling sequence of `conv`:
1627: + tao - the `Tao` object
1628: - ctx - [optional] convergence context

1630:   Level: advanced

1632:   Note:
1633:   The new convergence testing routine should call `TaoSetConvergedReason()`.

1635: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoMonitorSet()`
1636: @*/
1637: PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao tao, PetscCtx ctx), PetscCtx ctx)
1638: {
1639:   PetscFunctionBegin;
1641:   tao->ops->convergencetest = conv;
1642:   tao->cnvP                 = ctx;
1643:   PetscFunctionReturn(PETSC_SUCCESS);
1644: }

1646: /*@
1647:   TaoMonitorSet - Sets an additional function that is to be used at every
1648:   iteration of the solver to display the iteration's
1649:   progress.

1651:   Logically Collective

1653:   Input Parameters:
1654: + tao  - the `Tao` solver context
1655: . func - monitoring routine
1656: . ctx  - [optional] user-defined context for private data for the monitor routine (may be `NULL`)
1657: - dest - [optional] function to destroy the context when the `Tao` is destroyed, see `PetscCtxDestroyFn` for the calling sequence

1659:   Calling sequence of `func`:
1660: + tao - the `Tao` solver context
1661: - ctx - [optional] monitoring context

1663:   Level: intermediate

1665:   Notes:
1666:   See `TaoSetFromOptions()` for a monitoring options.

1668:   Several different monitoring routines may be set by calling
1669:   `TaoMonitorSet()` multiple times; all will be called in the
1670:   order in which they were set.

1672:   Fortran Notes:
1673:   Only one monitor function may be set

1675: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoMonitorDefault()`, `TaoMonitorCancel()`, `TaoView()`, `PetscCtxDestroyFn`
1676: @*/
1677: PetscErrorCode TaoMonitorSet(Tao tao, PetscErrorCode (*func)(Tao tao, PetscCtx ctx), PetscCtx ctx, PetscCtxDestroyFn *dest)
1678: {
1679:   PetscFunctionBegin;
1681:   PetscCheck(tao->numbermonitors < MAXTAOMONITORS, PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Cannot attach another monitor -- max=%d", MAXTAOMONITORS);
1682:   for (PetscInt i = 0; i < tao->numbermonitors; i++) {
1683:     PetscBool identical;

1685:     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)func, ctx, dest, (PetscErrorCode (*)(void))(PetscVoidFn *)tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical));
1686:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1687:   }
1688:   tao->monitor[tao->numbermonitors]        = func;
1689:   tao->monitorcontext[tao->numbermonitors] = ctx;
1690:   tao->monitordestroy[tao->numbermonitors] = dest;
1691:   ++tao->numbermonitors;
1692:   PetscFunctionReturn(PETSC_SUCCESS);
1693: }

1695: /*@
1696:   TaoMonitorCancel - Clears all the monitor functions for a `Tao` object.

1698:   Logically Collective

1700:   Input Parameter:
1701: . tao - the `Tao` solver context

1703:   Options Database Key:
1704: . -tao_monitor_cancel - cancels all monitors that have been hardwired
1705:     into a code by calls to `TaoMonitorSet()`, but does not cancel those
1706:     set via the options database

1708:   Level: advanced

1710:   Note:
1711:   There is no way to clear one specific monitor from a `Tao` object.

1713: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1714: @*/
1715: PetscErrorCode TaoMonitorCancel(Tao tao)
1716: {
1717:   PetscFunctionBegin;
1719:   for (PetscInt i = 0; i < tao->numbermonitors; i++) {
1720:     if (tao->monitordestroy[i]) PetscCall((*tao->monitordestroy[i])(&tao->monitorcontext[i]));
1721:   }
1722:   tao->numbermonitors = 0;
1723:   PetscFunctionReturn(PETSC_SUCCESS);
1724: }

1726: /*@
1727:   TaoMonitorDefault - Default routine for monitoring progress of `TaoSolve()`

1729:   Collective

1731:   Input Parameters:
1732: + tao - the `Tao` context
1733: - vf  - `PetscViewerAndFormat` context

1735:   Options Database Keys:
1736: + -tao_monitor [ascii][:filename] - monitor function and residual norms at each iteration, only ASCII viewers supported
1737: - -tao_monitor_interval interval  - only monitor function and residual norms every `interval` iterations, and the last iteration

1739:   Level: advanced

1741:   Note:
1742:   This monitor prints the function value and gradient
1743:   norm at each iteration.

1745: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1746: @*/
1747: PetscErrorCode TaoMonitorDefault(Tao tao, PetscViewerAndFormat *vf)
1748: {
1749:   PetscViewer viewer = vf->viewer;
1750:   PetscBool   isascii;
1751:   PetscInt    tabs;

1753:   PetscFunctionBegin;
1755:   if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);

1757:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1758:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
1759:   if (isascii) {
1760:     PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));

1762:     PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1763:     if (tao->niter == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1764:       PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1765:       tao->header_printed = PETSC_TRUE;
1766:     }
1767:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", tao->niter));
1768:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)tao->fc));
1769:     if (tao->residual >= PETSC_INFINITY) {
1770:       PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: infinity \n"));
1771:     } else {
1772:       PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g \n", (double)tao->residual));
1773:     }
1774:     PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1775:   }
1776:   PetscCall(PetscViewerPopFormat(viewer));
1777:   PetscFunctionReturn(PETSC_SUCCESS);
1778: }

1780: /*@
1781:   TaoMonitorGlobalization - Default routine for monitoring progress of `TaoSolve()` with extra detail on the globalization method.

1783:   Collective

1785:   Input Parameters:
1786: + tao - the `Tao` context
1787: - vf  - `PetscViewerAndFormat` context

1789:   Options Database Keys:
1790: + -tao_monitor_globalization [ascii][:filename] - monitor globalization information at each iteration, only ASCII viewers are supported
1791: - -tao_monitor_globalization_interval interval  - only monitor globalization information every `interval` iterations, and the last iteration

1793:   Level: advanced

1795:   Note:
1796:   This monitor prints the function value and gradient norm at each
1797:   iteration, as well as the step size and trust radius. Note that the
1798:   step size and trust radius may be the same for some algorithms.

1800: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1801: @*/
1802: PetscErrorCode TaoMonitorGlobalization(Tao tao, PetscViewerAndFormat *vf)
1803: {
1804:   PetscViewer viewer = vf->viewer;
1805:   PetscBool   isascii;
1806:   PetscInt    tabs;

1808:   PetscFunctionBegin;
1810:   if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);

1812:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1813:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
1814:   if (isascii) {
1815:     PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1816:     PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1817:     if (tao->niter == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1818:       PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1819:       tao->header_printed = PETSC_TRUE;
1820:     }
1821:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", tao->niter));
1822:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)tao->fc));
1823:     if (tao->residual >= PETSC_INFINITY) {
1824:       PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf,"));
1825:     } else {
1826:       PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g,", (double)tao->residual));
1827:     }
1828:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Step: %g,  Trust: %g\n", (double)tao->step, (double)tao->trust));
1829:     PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1830:   }
1831:   PetscCall(PetscViewerPopFormat(viewer));
1832:   PetscFunctionReturn(PETSC_SUCCESS);
1833: }

1835: /*@
1836:   TaoMonitorDefaultShort - Routine for monitoring progress of `TaoSolve()` that displays fewer digits than `TaoMonitorDefault()`

1838:   Collective

1840:   Input Parameters:
1841: + tao - the `Tao` context
1842: - vf  - `PetscViewerAndFormat` context

1844:   Options Database Keys:
1845: + -tao_monitor_short [ascii][:filename] - monitor function and residual norms at each iteration, with fewer digits of the residual, only ASCII viewers are supported
1846: - -tao_monitor_short_interval interval  - only monitor function and residual norms every `interval` iterations, and the last iteration

1848:   Level: advanced

1850:   Note:
1851:   Same as `TaoMonitorDefault()` except
1852:   it prints fewer digits of the residual as the residual gets smaller.
1853:   This is because the later digits are meaningless and are often
1854:   different on different machines; by using this routine different
1855:   machines will usually generate the same output.

1857: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1858: @*/
1859: PetscErrorCode TaoMonitorDefaultShort(Tao tao, PetscViewerAndFormat *vf)
1860: {
1861:   PetscViewer viewer = vf->viewer;
1862:   PetscBool   isascii;
1863:   PetscInt    tabs;
1864:   PetscReal   gnorm;

1866:   PetscFunctionBegin;
1868:   if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);

1870:   gnorm = tao->residual;
1871:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1872:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
1873:   if (isascii) {
1874:     PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1875:     PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1876:     PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %3" PetscInt_FMT ",", tao->niter));
1877:     PetscCall(PetscViewerASCIIPrintf(viewer, " Function value %g,", (double)tao->fc));
1878:     if (gnorm >= PETSC_INFINITY) {
1879:       PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: infinity \n"));
1880:     } else if (gnorm > 1.e-6) {
1881:       PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm));
1882:     } else if (gnorm > 1.e-11) {
1883:       PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-6 \n"));
1884:     } else {
1885:       PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-11 \n"));
1886:     }
1887:     PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1888:   }
1889:   PetscCall(PetscViewerPopFormat(viewer));
1890:   PetscFunctionReturn(PETSC_SUCCESS);
1891: }

1893: /*@
1894:   TaoMonitorConstraintNorm - same as `TaoMonitorDefault()` except
1895:   it prints the norm of the constraint function.

1897:   Collective

1899:   Input Parameters:
1900: + tao - the `Tao` context
1901: - vf  - `PetscViewerAndFormat` context

1903:   Options Database Keys:
1904: + -tao_monitor_constraint_norm [ascii][:filename] - monitor the constraints at each iteration, only ASCII viewers are supported
1905: - -tao_monitor_constraint_norm_interval interval  - only monitor the constraints every `interval` iterations, and the last iteration

1907:   Level: advanced

1909: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1910: @*/
1911: PetscErrorCode TaoMonitorConstraintNorm(Tao tao, PetscViewerAndFormat *vf)
1912: {
1913:   PetscViewer viewer = vf->viewer;
1914:   PetscBool   isascii;
1915:   PetscInt    tabs;

1917:   PetscFunctionBegin;
1919:   if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);

1921:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1922:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
1923:   if (isascii) {
1924:     PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1925:     PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1926:     PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", tao->niter));
1927:     PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)tao->fc));
1928:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g ", (double)tao->residual));
1929:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Constraint: %g \n", (double)tao->cnorm));
1930:     PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1931:   }
1932:   PetscCall(PetscViewerPopFormat(viewer));
1933:   PetscFunctionReturn(PETSC_SUCCESS);
1934: }

1936: /*@
1937:   TaoMonitorSolution - Views the solution 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_solution [viewertype][:filename][:viewerformat] - view the solution vector at each iteration
1947: - -tao_monitor_solution_interval interval                      - only view the solution every `interval` iterations, and the last iteration

1949:   Level: advanced

1951: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1952: @*/
1953: PetscErrorCode TaoMonitorSolution(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->solution, vf->viewer));
1960:   PetscCall(PetscViewerPopFormat(vf->viewer));
1961:   PetscFunctionReturn(PETSC_SUCCESS);
1962: }

1964: /*@
1965:   TaoMonitorGradient - Views the gradient at each iteration of `TaoSolve()`

1967:   Collective

1969:   Input Parameters:
1970: + tao - the `Tao` context
1971: - vf  - `PetscViewerAndFormat` context

1973:   Options Database Keys:
1974: + -tao_monitor_gradient [viewertype][:filename][:viewerformat] - view the gradient at each iteration
1975: - -tao_monitor_gradient_interval interval                      - only view the gradient every `interval` iterations, and the last iteration

1977:   Level: advanced

1979: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1980: @*/
1981: PetscErrorCode TaoMonitorGradient(Tao tao, PetscViewerAndFormat *vf)
1982: {
1983:   PetscFunctionBegin;
1985:   if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
1986:   PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
1987:   PetscCall(VecView(tao->gradient, vf->viewer));
1988:   PetscCall(PetscViewerPopFormat(vf->viewer));
1989:   PetscFunctionReturn(PETSC_SUCCESS);
1990: }

1992: /*@
1993:   TaoMonitorStep - Views the step-direction at each iteration of `TaoSolve()`

1995:   Collective

1997:   Input Parameters:
1998: + tao - the `Tao` context
1999: - vf  - `PetscViewerAndFormat` context

2001:   Options Database Keys:
2002: + -tao_monitor_step [viewertype][:filename][:viewerformat] - view the step vector at each iteration
2003: - -tao_monitor_step_interval interval                      - only view the step vector every `interval` iterations, and the last iteration

2005:   Level: advanced

2007: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
2008: @*/
2009: PetscErrorCode TaoMonitorStep(Tao tao, PetscViewerAndFormat *vf)
2010: {
2011:   PetscFunctionBegin;
2013:   if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
2014:   PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
2015:   PetscCall(VecView(tao->stepdirection, vf->viewer));
2016:   PetscCall(PetscViewerPopFormat(vf->viewer));
2017:   PetscFunctionReturn(PETSC_SUCCESS);
2018: }

2020: /*@
2021:   TaoMonitorSolutionDraw - Plots the solution at each iteration of `TaoSolve()`

2023:   Collective

2025:   Input Parameters:
2026: + tao - the `Tao` context
2027: - ctx - `TaoMonitorDrawCtx` context

2029:   Options Database Keys:
2030: + -tao_monitor_solution_draw                   - draw the solution at each iteration
2031: - -tao_monitor_solution_draw_interval interval - only draw the solution every `interval` iterations and final value, or only final value if negative

2033:   Level: advanced

2035:   Note:
2036:   The context created by `TaoMonitorDrawCtxCreate()`, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
2037:   are passed to `TaoMonitorSet()` to monitor the solution graphically.

2039: .seealso: [](ch_tao), `Tao`, `TaoMonitorSolution()`, `TaoMonitorSet()`, `TaoMonitorGradientDraw()`, `TaoMonitorDrawCtxCreate()`,
2040:           `TaoMonitorDrawCtxDestroy()`
2041: @*/
2042: PetscErrorCode TaoMonitorSolutionDraw(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->solution, ictx->viewer));
2050:   PetscFunctionReturn(PETSC_SUCCESS);
2051: }

2053: /*@
2054:   TaoMonitorGradientDraw - Plots the gradient at each iteration of `TaoSolve()`

2056:   Collective

2058:   Input Parameters:
2059: + tao - the `Tao` context
2060: - ctx - `TaoMonitorDrawCtx` context

2062:   Options Database Keys:
2063: + -tao_monitor_gradient_draw                   - draw the gradient at each iteration
2064: - -tao_monitor_gradient_draw_interval interval - only draw the gradient every `interval` iterations and final value, or only final value if negative

2066:   Level: advanced

2068: .seealso: [](ch_tao), `Tao`, `TaoMonitorGradient()`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw()`
2069: @*/
2070: PetscErrorCode TaoMonitorGradientDraw(Tao tao, PetscCtx ctx)
2071: {
2072:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

2074:   PetscFunctionBegin;
2076:   if (!((ictx->howoften > 0 && !((tao->niter % ictx->howoften) && !tao->reason)) || (ictx->howoften < 0 && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
2077:   PetscCall(VecView(tao->gradient, ictx->viewer));
2078:   PetscFunctionReturn(PETSC_SUCCESS);
2079: }

2081: /*@
2082:   TaoMonitorStepDraw - Plots the step direction at each iteration of `TaoSolve()`

2084:   Collective

2086:   Input Parameters:
2087: + tao - the `Tao` context
2088: - ctx - the `TaoMonitorDrawCtx` context

2090:   Options Database Keys:
2091: + -tao_monitor_step_draw                   - draw the step direction at each iteration
2092: - -tao_monitor_step_draw_interval interval - only draw the step direction every `interval` iterations and final value, or only final value if negative

2094:   Level: advanced

2096: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw`
2097: @*/
2098: PetscErrorCode TaoMonitorStepDraw(Tao tao, PetscCtx ctx)
2099: {
2100:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

2102:   PetscFunctionBegin;
2104:   if (!((ictx->howoften > 0 && !((tao->niter % ictx->howoften) && !tao->reason)) || (ictx->howoften < 0 && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
2105:   PetscCall(VecView(tao->stepdirection, ictx->viewer));
2106:   PetscFunctionReturn(PETSC_SUCCESS);
2107: }

2109: /*@
2110:   TaoMonitorResidual - Views the least-squares residual at each iteration of `TaoSolve()`

2112:   Collective

2114:   Input Parameters:
2115: + tao - the `Tao` context
2116: - vf  - `PetscViewerAndFormat` context

2118:   Options Database Keys:
2119: + -tao_monitor_residual                   - view the residual at each iteration
2120: - -tao_monitor_residual_interval interval - only view residual every `interval` iterations, and the last iteration

2122:   Level: advanced

2124: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
2125: @*/
2126: PetscErrorCode TaoMonitorResidual(Tao tao, PetscViewerAndFormat *vf)
2127: {
2128:   PetscFunctionBegin;
2130:   if (vf->view_interval > 0 && tao->niter % vf->view_interval && !tao->reason) PetscFunctionReturn(PETSC_SUCCESS);
2131:   PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
2132:   PetscCall(VecView(tao->ls_res, vf->viewer));
2133:   PetscCall(PetscViewerPopFormat(vf->viewer));
2134:   PetscFunctionReturn(PETSC_SUCCESS);
2135: }

2137: /*@
2138:   TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
2139:   or terminate.

2141:   Collective

2143:   Input Parameters:
2144: + tao   - the `Tao` context
2145: - dummy - unused dummy context

2147:   Level: developer

2149:   Notes:
2150:   This routine checks the residual in the optimality conditions, the
2151:   relative residual in the optimity conditions, the number of function
2152:   evaluations, and the function value to test convergence.  Some
2153:   solvers may use different convergence routines.

2155: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
2156: @*/
2157: PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
2158: {
2159:   PetscInt           niter     = tao->niter, nfuncs;
2160:   PetscInt           max_funcs = tao->max_funcs;
2161:   PetscReal          gnorm = tao->residual, gnorm0 = tao->gnorm0;
2162:   PetscReal          f = tao->fc, steptol = tao->steptol, trradius = tao->step;
2163:   PetscReal          gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
2164:   PetscReal          catol = tao->catol, crtol = tao->crtol;
2165:   PetscReal          fmin = tao->fmin, cnorm = tao->cnorm;
2166:   TaoConvergedReason reason = tao->reason;

2168:   PetscFunctionBegin;
2170:   if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);

2172:   PetscCall(TaoGetCurrentFunctionEvaluations(tao, &nfuncs));
2173:   if (PetscIsInfOrNanReal(f)) {
2174:     PetscCall(PetscInfo(tao, "Failed to converged, function value is infinity or NaN\n"));
2175:     reason = TAO_DIVERGED_NAN;
2176:   } else if (f <= fmin && cnorm <= catol) {
2177:     PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
2178:     reason = TAO_CONVERGED_MINF;
2179:   } else if (gnorm <= gatol && cnorm <= catol) {
2180:     PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
2181:     reason = TAO_CONVERGED_GATOL;
2182:   } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
2183:     PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
2184:     reason = TAO_CONVERGED_GRTOL;
2185:   } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
2186:     PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
2187:     reason = TAO_CONVERGED_GTTOL;
2188:   } else if (max_funcs != PETSC_UNLIMITED && nfuncs > max_funcs) {
2189:     PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
2190:     reason = TAO_DIVERGED_MAXFCN;
2191:   } else if (tao->lsflag != 0) {
2192:     PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
2193:     reason = TAO_DIVERGED_LS_FAILURE;
2194:   } else if (trradius < steptol && niter > 0) {
2195:     PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
2196:     reason = TAO_CONVERGED_STEPTOL;
2197:   } else if (niter >= tao->max_it) {
2198:     PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
2199:     reason = TAO_DIVERGED_MAXITS;
2200:   } else {
2201:     reason = TAO_CONTINUE_ITERATING;
2202:   }
2203:   tao->reason = reason;
2204:   PetscFunctionReturn(PETSC_SUCCESS);
2205: }

2207: /*@
2208:   TaoSetOptionsPrefix - Sets the prefix used for searching for all
2209:   Tao options in the database.

2211:   Logically Collective

2213:   Input Parameters:
2214: + tao - the `Tao` context
2215: - p   - the prefix string to prepend to all Tao option requests

2217:   Level: advanced

2219:   Notes:
2220:   A hyphen (-) must NOT be given at the beginning of the prefix name.
2221:   The first character of all runtime options is AUTOMATICALLY the hyphen.

2223:   For example, to distinguish between the runtime options for two
2224:   different Tao solvers, one could call
2225: .vb
2226:       TaoSetOptionsPrefix(tao1,"sys1_")
2227:       TaoSetOptionsPrefix(tao2,"sys2_")
2228: .ve

2230:   This would enable use of different options for each system, such as
2231: .vb
2232:       -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2233:       -sys2_tao_method lmvm  -sys2_tao_grtol 1.e-4
2234: .ve

2236: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2237: @*/
2238: PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2239: {
2240:   PetscFunctionBegin;
2242:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2243:   if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2244:   if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2245:   if (tao->callbacks) {
2246:     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao->callbacks, p));
2247:     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->callbacks, "callbacks_"));
2248:   }
2249:   PetscFunctionReturn(PETSC_SUCCESS);
2250: }

2252: /*@
2253:   TaoAppendOptionsPrefix - Appends to the prefix used for searching for all Tao options in the database.

2255:   Logically Collective

2257:   Input Parameters:
2258: + tao - the `Tao` solver context
2259: - p   - the prefix string to prepend to all `Tao` option requests

2261:   Level: advanced

2263:   Note:
2264:   A hyphen (-) must NOT be given at the beginning of the prefix name.
2265:   The first character of all runtime options is automatically the hyphen.

2267: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2268: @*/
2269: PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2270: {
2271:   PetscFunctionBegin;
2273:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2274:   if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2275:   if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2276:   if (tao->callbacks) {
2277:     const char *prefix;

2279:     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, &prefix));
2280:     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao->callbacks, prefix));
2281:     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->callbacks, "callbacks_"));
2282:   }
2283:   PetscFunctionReturn(PETSC_SUCCESS);
2284: }

2286: /*@
2287:   TaoGetOptionsPrefix - Gets the prefix used for searching for all
2288:   Tao options in the database

2290:   Not Collective

2292:   Input Parameter:
2293: . tao - the `Tao` context

2295:   Output Parameter:
2296: . p - pointer to the prefix string used is returned

2298:   Level: advanced

2300: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2301: @*/
2302: PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2303: {
2304:   PetscFunctionBegin;
2306:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2307:   PetscFunctionReturn(PETSC_SUCCESS);
2308: }

2310: /*@
2311:   TaoSetType - Sets the `TaoType` for the minimization solver.

2313:   Collective

2315:   Input Parameters:
2316: + tao  - the `Tao` solver context
2317: - type - a known method

2319:   Options Database Key:
2320: . -tao_type type - Sets the method; see `TaoType`

2322:   Level: intermediate

2324:   Note:
2325:   Calling this function resets the convergence test to `TaoDefaultConvergenceTest()`.
2326:   If a custom convergence test has been set with `TaoSetConvergenceTest()`, it must
2327:   be set again after calling `TaoSetType()`.

2329: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2330: @*/
2331: PetscErrorCode TaoSetType(Tao tao, TaoType type)
2332: {
2333:   PetscErrorCode (*create_xxx)(Tao);
2334:   PetscBool issame;

2336:   PetscFunctionBegin;

2339:   PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2340:   if (issame) PetscFunctionReturn(PETSC_SUCCESS);

2342:   PetscCall(PetscFunctionListFind(TaoList, type, &create_xxx));
2343:   PetscCheck(create_xxx, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Tao type %s", type);

2345:   /* Destroy the existing solver information */
2346:   PetscTryTypeMethod(tao, destroy);
2347:   PetscCall(KSPDestroy(&tao->ksp));
2348:   PetscCall(TaoLineSearchDestroy(&tao->linesearch));

2350:   /* Reinitialize type-specific function pointers in TaoOps structure */
2351:   tao->ops->setup           = NULL;
2352:   tao->ops->computedual     = NULL;
2353:   tao->ops->solve           = NULL;
2354:   tao->ops->view            = NULL;
2355:   tao->ops->setfromoptions  = NULL;
2356:   tao->ops->destroy         = NULL;
2357:   tao->ops->convergencetest = TaoDefaultConvergenceTest;

2359:   tao->setupcalled           = PETSC_FALSE;
2360:   tao->uses_gradient         = PETSC_FALSE;
2361:   tao->uses_hessian_matrices = PETSC_FALSE;

2363:   PetscCall(TaoParametersInitialize(tao));

2365:   PetscCall((*create_xxx)(tao));
2366:   PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2367:   PetscFunctionReturn(PETSC_SUCCESS);
2368: }

2370: /*@
2371:   TaoRegister - Adds a method to the Tao package for minimization.

2373:   Not Collective, No Fortran Support

2375:   Input Parameters:
2376: + sname - name of a new user-defined solver
2377: - func  - routine to create `TaoType` specific method context

2379:   Calling sequence of `func`:
2380: . tao - the `Tao` object to be created

2382:   Example Usage:
2383: .vb
2384:    TaoRegister("my_solver", MySolverCreate);
2385: .ve

2387:   Then, your solver can be chosen with the procedural interface via
2388: .vb
2389:   TaoSetType(tao, "my_solver")
2390: .ve
2391:   or at runtime via the option
2392: .vb
2393:   -tao_type my_solver
2394: .ve

2396:   Level: advanced

2398:   Note:
2399:   `TaoRegister()` may be called multiple times to add several user-defined solvers.

2401: .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2402: @*/
2403: PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao tao))
2404: {
2405:   PetscFunctionBegin;
2406:   PetscCall(TaoInitializePackage());
2407:   PetscCall(PetscFunctionListAdd(&TaoList, sname, func));
2408:   PetscFunctionReturn(PETSC_SUCCESS);
2409: }

2411: /*@
2412:   TaoRegisterDestroy - Frees the list of minimization solvers that were
2413:   registered by `TaoRegister()`.

2415:   Not Collective

2417:   Level: advanced

2419: .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2420: @*/
2421: PetscErrorCode TaoRegisterDestroy(void)
2422: {
2423:   PetscFunctionBegin;
2424:   PetscCall(PetscFunctionListDestroy(&TaoList));
2425:   TaoRegisterAllCalled = PETSC_FALSE;
2426:   PetscFunctionReturn(PETSC_SUCCESS);
2427: }

2429: /*@
2430:   TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2431:   at this time.

2433:   Not Collective

2435:   Input Parameter:
2436: . tao - the `Tao` context

2438:   Output Parameter:
2439: . iter - iteration number

2441:   Notes:
2442:   For example, during the computation of iteration 2 this would return 1.

2444:   Level: intermediate

2446: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2447: @*/
2448: PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2449: {
2450:   PetscFunctionBegin;
2452:   PetscAssertPointer(iter, 2);
2453:   *iter = tao->niter;
2454:   PetscFunctionReturn(PETSC_SUCCESS);
2455: }

2457: /*@
2458:   TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2459:   at this time.

2461:   Not Collective

2463:   Input Parameter:
2464: . tao - the `Tao` context

2466:   Output Parameter:
2467: . value - the current value

2469:   Level: intermediate

2471:   Developer Notes:
2472:   This is the 2-norm of the residual, we cannot use `TaoGetGradientNorm()` because that has
2473:   a different meaning. For some reason `Tao` sometimes calls the gradient the residual.

2475: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2476: @*/
2477: PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2478: {
2479:   PetscFunctionBegin;
2481:   PetscAssertPointer(value, 2);
2482:   *value = tao->residual;
2483:   PetscFunctionReturn(PETSC_SUCCESS);
2484: }

2486: /*@
2487:   TaoSetIterationNumber - Sets the current iteration number.

2489:   Logically Collective

2491:   Input Parameters:
2492: + tao  - the `Tao` context
2493: - iter - iteration number

2495:   Level: developer

2497: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2498: @*/
2499: PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2500: {
2501:   PetscFunctionBegin;
2504:   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2505:   tao->niter = iter;
2506:   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2507:   PetscFunctionReturn(PETSC_SUCCESS);
2508: }

2510: /*@
2511:   TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2512:   completed. This number keeps accumulating if multiple solves
2513:   are called with the `Tao` object.

2515:   Not Collective

2517:   Input Parameter:
2518: . tao - the `Tao` context

2520:   Output Parameter:
2521: . iter - number of iterations

2523:   Level: intermediate

2525:   Note:
2526:   The total iteration count is updated after each solve, if there is a current
2527:   `TaoSolve()` in progress then those iterations are not included in the count

2529: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2530: @*/
2531: PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2532: {
2533:   PetscFunctionBegin;
2535:   PetscAssertPointer(iter, 2);
2536:   *iter = tao->ntotalits;
2537:   PetscFunctionReturn(PETSC_SUCCESS);
2538: }

2540: /*@
2541:   TaoSetTotalIterationNumber - Sets the current total iteration number.

2543:   Logically Collective

2545:   Input Parameters:
2546: + tao  - the `Tao` context
2547: - iter - the iteration number

2549:   Level: developer

2551: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2552: @*/
2553: PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2554: {
2555:   PetscFunctionBegin;
2558:   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2559:   tao->ntotalits = iter;
2560:   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2561:   PetscFunctionReturn(PETSC_SUCCESS);
2562: }

2564: /*@
2565:   TaoSetConvergedReason - Sets the termination flag on a `Tao` object

2567:   Logically Collective

2569:   Input Parameters:
2570: + tao    - the `Tao` context
2571: - reason - the `TaoConvergedReason`

2573:   Level: intermediate

2575: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2576: @*/
2577: PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2578: {
2579:   PetscFunctionBegin;
2582:   tao->reason = reason;
2583:   PetscFunctionReturn(PETSC_SUCCESS);
2584: }

2586: /*@
2587:   TaoGetConvergedReason - Gets the reason the `TaoSolve()` was stopped.

2589:   Not Collective

2591:   Input Parameter:
2592: . tao - the `Tao` solver context

2594:   Output Parameter:
2595: . reason - value of `TaoConvergedReason`

2597:   Level: intermediate

2599: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`
2600: @*/
2601: PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2602: {
2603:   PetscFunctionBegin;
2605:   PetscAssertPointer(reason, 2);
2606:   *reason = tao->reason;
2607:   PetscFunctionReturn(PETSC_SUCCESS);
2608: }

2610: /*@
2611:   TaoGetSolutionStatus - Get the current iterate, objective value,
2612:   residual, infeasibility, and termination from a `Tao` object

2614:   Not Collective

2616:   Input Parameter:
2617: . tao - the `Tao` context

2619:   Output Parameters:
2620: + its    - the current iterate number (>=0)
2621: . f      - the current function value
2622: . gnorm  - the square of the gradient norm, duality gap, or other measure indicating distance from optimality.
2623: . cnorm  - the infeasibility of the current solution with regard to the constraints.
2624: . xdiff  - the step length or trust region radius of the most recent iterate.
2625: - reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`

2627:   Level: intermediate

2629:   Notes:
2630:   Tao returns the values set by the solvers in the routine `TaoMonitor()`.

2632:   If any of the output arguments are set to `NULL`, no corresponding value will be returned.

2634: .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2635: @*/
2636: PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2637: {
2638:   PetscFunctionBegin;
2640:   if (its) *its = tao->niter;
2641:   if (f) *f = tao->fc;
2642:   if (gnorm) *gnorm = tao->residual;
2643:   if (cnorm) *cnorm = tao->cnorm;
2644:   if (reason) *reason = tao->reason;
2645:   if (xdiff) *xdiff = tao->step;
2646:   PetscFunctionReturn(PETSC_SUCCESS);
2647: }

2649: /*@
2650:   TaoGetType - Gets the current `TaoType` being used in the `Tao` object

2652:   Not Collective

2654:   Input Parameter:
2655: . tao - the `Tao` solver context

2657:   Output Parameter:
2658: . type - the `TaoType`

2660:   Level: intermediate

2662:   Note:
2663:   `type` should not be retained for later use as it will be an invalid pointer if the `TaoType` of `tao` is changed.

2665: .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
2666: @*/
2667: PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2668: {
2669:   PetscFunctionBegin;
2671:   PetscAssertPointer(type, 2);
2672:   *type = ((PetscObject)tao)->type_name;
2673:   PetscFunctionReturn(PETSC_SUCCESS);
2674: }

2676: /*@
2677:   TaoMonitor - Monitor the solver and the current solution.  This
2678:   routine will record the iteration number and residual statistics,
2679:   and call any monitors specified by the user.

2681:   Input Parameters:
2682: + tao        - the `Tao` context
2683: . its        - the current iterate number (>=0)
2684: . f          - the current objective function value
2685: . res        - the gradient norm, square root of the duality gap, or other measure indicating distance from optimality.  This measure will be recorded and
2686:           used for some termination tests.
2687: . cnorm      - the infeasibility of the current solution with regard to the constraints.
2688: - steplength - multiple of the step direction added to the previous iterate.

2690:   Options Database Key:
2691: . -tao_monitor - Use the default monitor, which prints statistics to standard output

2693:   Level: developer

2695: .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoMonitorSet()`
2696: @*/
2697: PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2698: {
2699:   PetscFunctionBegin;
2701:   tao->fc       = f;
2702:   tao->residual = res;
2703:   tao->cnorm    = cnorm;
2704:   tao->step     = steplength;
2705:   if (!its) {
2706:     tao->cnorm0 = cnorm;
2707:     tao->gnorm0 = res;
2708:   }
2709:   PetscCall(VecLockReadPush(tao->solution));
2710:   for (PetscInt i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2711:   PetscCall(VecLockReadPop(tao->solution));
2712:   PetscFunctionReturn(PETSC_SUCCESS);
2713: }

2715: /*@
2716:   TaoSetConvergenceHistory - Sets the array used to hold the convergence history.

2718:   Logically Collective

2720:   Input Parameters:
2721: + tao   - the `Tao` solver context
2722: . obj   - array to hold objective value history
2723: . resid - array to hold residual history
2724: . cnorm - array to hold constraint violation history
2725: . lits  - integer array holds the number of linear iterations for each Tao iteration
2726: . na    - size of `obj`, `resid`, and `cnorm`
2727: - reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2728:            else it continues storing new values for new minimizations after the old ones

2730:   Level: intermediate

2732:   Notes:
2733:   If set, `Tao` will fill the given arrays with the indicated
2734:   information at each iteration.  If 'obj','resid','cnorm','lits' are
2735:   *all* `NULL` then space (using size `na`, or 1000 if `na` is `PETSC_DECIDE`) is allocated for the history.
2736:   If not all are `NULL`, then only the non-`NULL` information categories
2737:   will be stored, the others will be ignored.

2739:   Any convergence information after iteration number 'na' will not be stored.

2741:   This routine is useful, e.g., when running a code for purposes
2742:   of accurate performance monitoring, when no I/O should be done
2743:   during the section of code that is being timed.

2745: .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2746: @*/
2747: PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2748: {
2749:   PetscFunctionBegin;
2751:   if (obj) PetscAssertPointer(obj, 2);
2752:   if (resid) PetscAssertPointer(resid, 3);
2753:   if (cnorm) PetscAssertPointer(cnorm, 4);
2754:   if (lits) PetscAssertPointer(lits, 5);

2756:   if (na == PETSC_DECIDE || na == PETSC_CURRENT) na = 1000;
2757:   if (!obj && !resid && !cnorm && !lits) {
2758:     PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2759:     tao->hist_malloc = PETSC_TRUE;
2760:   }

2762:   tao->hist_obj   = obj;
2763:   tao->hist_resid = resid;
2764:   tao->hist_cnorm = cnorm;
2765:   tao->hist_lits  = lits;
2766:   tao->hist_max   = na;
2767:   tao->hist_reset = reset;
2768:   tao->hist_len   = 0;
2769:   PetscFunctionReturn(PETSC_SUCCESS);
2770: }

2772: /*@
2773:   TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.

2775:   Collective

2777:   Input Parameter:
2778: . tao - the `Tao` context

2780:   Output Parameters:
2781: + obj   - array used to hold objective value history
2782: . resid - array used to hold residual history
2783: . cnorm - array used to hold constraint violation history
2784: . lits  - integer array used to hold linear solver iteration count
2785: - nhist - size of `obj`, `resid`, `cnorm`, and `lits`

2787:   Level: advanced

2789:   Notes:
2790:   This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2791:   and `TaoSolve()`, otherwise it returns useless information.

2793:   This routine is useful, e.g., when running a code for purposes
2794:   of accurate performance monitoring, when no I/O should be done
2795:   during the section of code that is being timed.

2797:   Fortran Notes:
2798:   The calling sequence is
2799: .vb
2800:    call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2801: .ve
2802:   In other words this gets the current number of entries in the history. Access the history through the array you passed to `TaoSetConvergenceHistory()`

2804: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2805: @*/
2806: PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2807: {
2808:   PetscFunctionBegin;
2810:   if (obj) *obj = tao->hist_obj;
2811:   if (cnorm) *cnorm = tao->hist_cnorm;
2812:   if (resid) *resid = tao->hist_resid;
2813:   if (lits) *lits = tao->hist_lits;
2814:   if (nhist) *nhist = tao->hist_len;
2815:   PetscFunctionReturn(PETSC_SUCCESS);
2816: }

2818: /*@
2819:   TaoSetApplicationContext - Sets the optional user-defined context for a `Tao` solver that can be accessed later, for example in the
2820:   `Tao` callback functions with `TaoGetApplicationContext()`

2822:   Logically Collective

2824:   Input Parameters:
2825: + tao - the `Tao` context
2826: - ctx - the application context

2828:   Level: intermediate

2830:   Fortran Note:
2831:   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
2832:   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `TaoGetApplicationContext()` for
2833:   an example.

2835: .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`
2836: @*/
2837: PetscErrorCode TaoSetApplicationContext(Tao tao, PetscCtx ctx)
2838: {
2839:   PetscFunctionBegin;
2841:   tao->ctx = ctx;
2842:   PetscFunctionReturn(PETSC_SUCCESS);
2843: }

2845: /*@
2846:   TaoGetApplicationContext - Gets the user-defined context for a `Tao` solver provided with `TaoSetApplicationContext()`

2848:   Not Collective

2850:   Input Parameter:
2851: . tao - the `Tao` context

2853:   Output Parameter:
2854: . ctx - a pointer to the application context

2856:   Level: intermediate

2858:   Fortran Note:
2859:   This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with
2860: .vb
2861:   type(tUsertype), pointer :: ctx
2862: .ve

2864: .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2865: @*/
2866: PetscErrorCode TaoGetApplicationContext(Tao tao, PetscCtxRt ctx)
2867: {
2868:   PetscFunctionBegin;
2870:   PetscAssertPointer(ctx, 2);
2871:   *(void **)ctx = tao->ctx;
2872:   PetscFunctionReturn(PETSC_SUCCESS);
2873: }

2875: /*@
2876:   TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient in some of the `Tao` algorithms

2878:   Collective

2880:   Input Parameters:
2881: + tao - the `Tao` context
2882: - M   - matrix that defines the norm

2884:   Level: beginner

2886: .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2887: @*/
2888: PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2889: {
2890:   PetscFunctionBegin;
2893:   PetscCall(PetscObjectReference((PetscObject)M));
2894:   PetscCall(MatDestroy(&tao->gradient_norm));
2895:   PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2896:   tao->gradient_norm = M;
2897:   PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2898:   PetscFunctionReturn(PETSC_SUCCESS);
2899: }

2901: /*@
2902:   TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient in some of the `Tao` algorithms

2904:   Not Collective

2906:   Input Parameter:
2907: . tao - the `Tao` context

2909:   Output Parameter:
2910: . M - gradient norm

2912:   Level: beginner

2914: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2915: @*/
2916: PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2917: {
2918:   PetscFunctionBegin;
2920:   PetscAssertPointer(M, 2);
2921:   *M = tao->gradient_norm;
2922:   PetscFunctionReturn(PETSC_SUCCESS);
2923: }

2925: /*@
2926:   TaoGradientNorm - Compute the norm using the `NormType`, the user has selected

2928:   Collective

2930:   Input Parameters:
2931: + tao      - the `Tao` context
2932: . gradient - the gradient
2933: - type     - the norm type

2935:   Output Parameter:
2936: . gnorm - the gradient norm

2938:   Level: advanced

2940:   Note:
2941:   If `TaoSetGradientNorm()` has been set and `type` is `NORM_2` then the norm provided with `TaoSetGradientNorm()` is used.

2943:   Developer Notes:
2944:   Should be named `TaoComputeGradientNorm()`.

2946:   The usage is a bit confusing, with `TaoSetGradientNorm()` plus `NORM_2` resulting in the computation of the user provided
2947:   norm, perhaps a refactorization is in order.

2949: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2950: @*/
2951: PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2952: {
2953:   PetscFunctionBegin;
2957:   PetscAssertPointer(gnorm, 4);
2958:   if (tao->gradient_norm) {
2959:     PetscScalar gnorms;

2961:     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.");
2962:     PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2963:     PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2964:     *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2965:   } else {
2966:     PetscCall(VecNorm(gradient, type, gnorm));
2967:   }
2968:   PetscFunctionReturn(PETSC_SUCCESS);
2969: }

2971: /*@
2972:   TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorSolutionDraw()`

2974:   Collective

2976:   Input Parameters:
2977: + comm     - the communicator to share the context
2978: . host     - the name of the X Windows host that will display the monitor
2979: . label    - the label to put at the top of the display window
2980: . x        - the horizontal coordinate of the lower left corner of the window to open
2981: . y        - the vertical coordinate of the lower left corner of the window to open
2982: . m        - the width of the window
2983: . n        - the height of the window
2984: - howoften - how many `Tao` iterations between displaying the monitor information

2986:   Output Parameter:
2987: . ctx - the monitor context

2989:   Options Database Keys:
2990: + -tao_monitor_solution_draw - use `TaoMonitorSolutionDraw()` to monitor the solution
2991: - -tao_draw_solution_initial - show initial guess as well as current solution

2993:   Level: intermediate

2995:   Note:
2996:   The context this creates, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
2997:   are passed to `TaoMonitorSet()`.

2999: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
3000: @*/
3001: PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
3002: {
3003:   PetscFunctionBegin;
3004:   PetscCall(PetscNew(ctx));
3005:   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
3006:   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
3007:   (*ctx)->howoften = howoften;
3008:   PetscFunctionReturn(PETSC_SUCCESS);
3009: }

3011: /*@
3012:   TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorSolutionDraw()`

3014:   Collective

3016:   Input Parameter:
3017: . ictx - the monitor context

3019:   Level: intermediate

3021:   Note:
3022:   This is passed to `TaoMonitorSet()` as the final argument, along with `TaoMonitorSolutionDraw()`, and the context
3023:   obtained with `TaoMonitorDrawCtxCreate()`.

3025: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorSolutionDraw()`
3026: @*/
3027: PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
3028: {
3029:   PetscFunctionBegin;
3030:   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
3031:   PetscCall(PetscFree(*ictx));
3032:   PetscFunctionReturn(PETSC_SUCCESS);
3033: }

3035: /*@
3036:   TaoGetTerm - Get the entire objective function of the `Tao` as a
3037:   single `TaoTerm` in the form $\alpha f(Ax; p)$, where $\alpha$ is a scaling
3038:   coefficient, $f$ is a `TaoTerm`, $A$ is an (optional) map and $p$ are the parameters of $f$.

3040:   Not collective

3042:   Input Parameter:
3043: . tao - a `Tao` context

3045:   Output Parameters:
3046: + scale  - the scale of the term
3047: . term   - a `TaoTerm` for the real-valued function defining the objective
3048: . params - the vector of parameters for `term`, or `NULL` if no parameters were specified for `term`
3049: - map    - a map from the solution space of `tao` to the solution space of `term`, if `NULL` then the map is the identity

3051:   Level: intermediate

3053:   Notes:
3054:   If the objective function was defined by providing function callbacks directly to `Tao` (for example, with `TaoSetObjectiveAndGradient()`), then
3055:   `TaoGetTerm` will return a `TaoTerm` with the type `TAOTERMCALLBACKS` that encapsulates
3056:   those functions.

3058:   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.

3060: .seealso: [](ch_tao), `Tao`, `TaoTerm`, `TAOTERMSUM`, `TaoAddTerm()`
3061: @*/
3062: PetscErrorCode TaoGetTerm(Tao tao, PetscReal *scale, TaoTerm *term, Vec *params, Mat *map)
3063: {
3064:   PetscFunctionBegin;
3066:   if (scale) PetscAssertPointer(scale, 2);
3067:   if (term) PetscAssertPointer(term, 3);
3068:   if (params) PetscAssertPointer(params, 4);
3069:   if (map) PetscAssertPointer(map, 5);
3070:   PetscCall(TaoTermMappingGetData(&tao->objective_term, NULL, scale, term, map));
3071:   if (params) *params = tao->objective_parameters;
3072:   PetscFunctionReturn(PETSC_SUCCESS);
3073: }

3075: /*@
3076:   TaoAddTerm - Add a `term` to the objective function. If `Tao` is empty,
3077:   `term` will be the objective of `Tao`.

3079:   Collective

3081:   Input Parameters:
3082: + tao    - a `Tao` solver context
3083: . 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.)
3084: . scale  - scaling coefficient for the new term
3085: . term   - the real-valued function defining the new term
3086: . params - (optional) parameters for the new term.  It is up to each implementation of `TaoTerm` to determine how it behaves when parameters are omitted.
3087: - map    - (optional) a map from the `tao` solution space to the `term` solution space; if `NULL` the map is assumed to be the identity

3089:   Level: beginner

3091:   Notes:
3092:   If the objective function was $f(x)$, after calling `TaoAddTerm()` it becomes
3093:   $f(x) + \alpha g(Ax; p)$, where $\alpha$ is the `scale`, $g$ is the `term`, $A$ is the
3094:   (optional) `map`, and $p$ are the (optional) `params` of $g$.

3096:   The `map` $A$ transforms the `Tao` solution vector into the term's solution space.
3097:   For example, if the `Tao` solution vector is $x \in \mathbb{R}^n$ and the mapping
3098:   matrix is $A \in \mathbb{R}^{m \times n}$, then the term evaluates $g(Ax; p)$ with
3099:   $Ax \in \mathbb{R}^m$. The term's solution space is therefore $\mathbb{R}^m$. If the map is
3100:   `NULL`, the identity is used and the term's solution space must match the `Tao` solution space.
3101:   `Tao` automatically applies the chain rule for gradients ($A^T \nabla g$) and Hessians
3102:   ($A^T \nabla^2 g \, A$) with respect to $x$.

3104:   The `params` $p$ are fixed data that are not optimized over. Some `TaoTermType`s
3105:   require the parameter space to be related to the term's solution space (e.g., the same
3106:   size); when a mapping matrix $A$ is used, the parameter space may depend on either the row
3107:   or column space of $A$.  See the documentation for each `TaoTermType`.

3109:   Currently, `TaoAddTerm()` does not support bounded Newton solvers (`TAOBNK`,`TAOBNLS`,`TAOBNTL`,`TAOBNTR`,and `TAOBQNK`)

3111: .seealso: [](ch_tao), `Tao`, `TaoTerm`, `TAOTERMSUM`, `TaoGetTerm()`
3112: @*/
3113: PetscErrorCode TaoAddTerm(Tao tao, const char prefix[], PetscReal scale, TaoTerm term, Vec params, Mat map)
3114: {
3115:   PetscBool is_sum, is_callback;
3116:   PetscInt  num_old_terms;
3117:   Vec      *vec_list = NULL;

3119:   PetscFunctionBegin;
3121:   if (prefix) PetscAssertPointer(prefix, 2);
3124:   PetscCheckSameComm(tao, 1, term, 4);
3125:   if (params) {
3127:     PetscCheckSameComm(tao, 1, params, 5);
3128:   }
3129:   if (map) {
3131:     PetscCheckSameComm(tao, 1, map, 6);
3132:   }
3133:   // If user is using TaoAddTerm, before setting any terms or callbacks,
3134:   // then tao->objective_term.term is empty callback, which we want to remove.
3135:   PetscCall(PetscObjectTypeCompare((PetscObject)tao->objective_term.term, TAOTERMCALLBACKS, &is_callback));
3136:   PetscCall(PetscObjectTypeCompare((PetscObject)term, TAOTERMSUM, &is_sum));
3137:   PetscCheck(!is_sum, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONG, "TaoAddTerm does not support adding TAOTERMSUM");
3138:   if (is_callback) {
3139:     PetscBool is_obj, is_objgrad, is_grad;

3141:     PetscCall(TaoTermIsObjectiveDefined(tao->objective_term.term, &is_obj));
3142:     PetscCall(TaoTermIsObjectiveAndGradientDefined(tao->objective_term.term, &is_objgrad));
3143:     PetscCall(TaoTermIsGradientDefined(tao->objective_term.term, &is_grad));
3144:     // Empty callback term
3145:     if (!(is_obj || is_objgrad || is_grad)) {
3146:       PetscCall(TaoTermMappingSetData(&tao->objective_term, NULL, scale, term, map));
3147:       PetscCall(PetscObjectReference((PetscObject)params));
3148:       PetscCall(VecDestroy(&tao->objective_parameters));
3149:       // Empty callback term. Destroy hessians, as they are not needed
3150:       PetscCall(MatDestroy(&tao->hessian));
3151:       PetscCall(MatDestroy(&tao->hessian_pre));
3152:       tao->objective_parameters = params;
3153:       tao->term_set             = PETSC_TRUE;
3154:       PetscFunctionReturn(PETSC_SUCCESS);
3155:     }
3156:   }
3157:   PetscCall(PetscObjectTypeCompare((PetscObject)tao->objective_term.term, TAOTERMSUM, &is_sum));
3158:   // One TaoTerm has been set. Create TAOTERMSUM to store that, and the new one
3159:   if (!is_sum) {
3160:     TaoTerm     old_sum;
3161:     const char *tao_prefix;
3162:     const char *term_prefix;

3164:     PetscCall(TaoTermDuplicate(tao->objective_term.term, TAOTERM_DUPLICATE_SIZEONLY, &old_sum));
3165:     if (tao->objective_term.map) {
3166:       VecType     map_vectype;
3167:       VecType     param_vectype;
3168:       PetscLayout cmap, param_layout;

3170:       PetscCall(MatGetVecType(tao->objective_term.map, &map_vectype));
3171:       PetscCall(MatGetLayouts(tao->objective_term.map, NULL, &cmap));
3172:       PetscCall(TaoTermGetParametersVecType(old_sum, &param_vectype));
3173:       PetscCall(TaoTermGetParametersLayout(old_sum, &param_layout));

3175:       PetscCall(TaoTermSetSolutionVecType(old_sum, map_vectype));
3176:       PetscCall(TaoTermSetParametersVecType(old_sum, param_vectype));
3177:       PetscCall(TaoTermSetSolutionLayout(old_sum, cmap));
3178:       PetscCall(TaoTermSetParametersLayout(old_sum, param_layout));
3179:     }

3181:     PetscCall(TaoTermSetType(old_sum, TAOTERMSUM));
3182:     PetscCall(TaoGetOptionsPrefix(tao, &tao_prefix));
3183:     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)old_sum, tao_prefix));
3184:     PetscCall(TaoTermSumSetNumberTerms(old_sum, 1));
3185:     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao->objective_term.term, &term_prefix));
3186:     PetscCall(TaoTermSumSetTerm(old_sum, 0, term_prefix, tao->objective_term.scale, tao->objective_term.term, tao->objective_term.map));
3187:     PetscCall(TaoTermSumSetTermHessianMatrices(old_sum, 0, NULL, NULL, tao->hessian, tao->hessian_pre));
3188:     PetscCall(MatDestroy(&tao->hessian));
3189:     PetscCall(MatDestroy(&tao->hessian_pre));
3190:     PetscCall(TaoTermMappingReset(&tao->objective_term));
3191:     PetscCall(TaoTermMappingSetData(&tao->objective_term, NULL, 1.0, old_sum, NULL));
3192:     if (tao->objective_parameters) {
3193:       // convert the parameters to a VECNEST
3194:       Vec subvecs[1];

3196:       subvecs[0]                = tao->objective_parameters;
3197:       tao->objective_parameters = NULL;
3198:       PetscCall(TaoTermSumParametersPack(old_sum, subvecs, &tao->objective_parameters));
3199:       PetscCall(VecDestroy(&subvecs[0]));
3200:     }
3201:     PetscCall(TaoTermDestroy(&old_sum));
3202:     tao->num_terms = 1;
3203:   }
3204:   PetscCall(TaoTermSumGetNumberTerms(tao->objective_term.term, &num_old_terms));
3205:   if (tao->objective_parameters || params) {
3206:     PetscCall(PetscCalloc1(num_old_terms + 1, &vec_list));
3207:     if (tao->objective_parameters) PetscCall(TaoTermSumParametersUnpack(tao->objective_term.term, &tao->objective_parameters, vec_list));
3208:     PetscCall(PetscObjectReference((PetscObject)params));
3209:     vec_list[num_old_terms] = params;
3210:   }
3211:   PetscCall(TaoTermSumAddTerm(tao->objective_term.term, prefix, scale, term, map, NULL));
3212:   tao->num_terms++;
3213:   if (vec_list) {
3214:     PetscInt num_terms = num_old_terms + 1;
3215:     PetscCall(TaoTermSumParametersPack(tao->objective_term.term, vec_list, &tao->objective_parameters));
3216:     for (PetscInt i = 0; i < num_terms; i++) PetscCall(VecDestroy(&vec_list[i]));
3217:     PetscCall(PetscFree(vec_list));
3218:   }
3219:   PetscFunctionReturn(PETSC_SUCCESS);
3220: }

3222: /*@
3223:   TaoSetDM - Sets the `DM` that may be used by some `TAO` solvers or their underlying solvers and preconditioners

3225:   Logically Collective

3227:   Input Parameters:
3228: + tao - the nonlinear solver context
3229: - dm  - the `DM`, cannot be `NULL`

3231:   Level: intermediate

3233:   Note:
3234:   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
3235:   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
3236:   problems using the same function space.

3238: .seealso: [](ch_snes), `DM`, `TAO`, `TaoGetDM()`, `SNESSetDM()`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
3239: @*/
3240: PetscErrorCode TaoSetDM(Tao tao, DM dm)
3241: {
3242:   KSP ksp;

3244:   PetscFunctionBegin;
3247:   PetscCall(PetscObjectReference((PetscObject)dm));
3248:   PetscCall(DMDestroy(&tao->dm));
3249:   tao->dm = dm;

3251:   PetscCall(TaoGetKSP(tao, &ksp));
3252:   if (ksp) {
3253:     PetscCall(KSPSetDM(ksp, dm));
3254:     PetscCall(KSPSetDMActive(ksp, KSP_DMACTIVE_ALL, PETSC_FALSE));
3255:   }
3256:   PetscFunctionReturn(PETSC_SUCCESS);
3257: }

3259: /*@
3260:   TaoGetDM - Gets the `DM` that may be used by some `TAO` solvers or their underlying solvers and preconditioners

3262:   Not Collective but `dm` obtained is parallel on `tao`

3264:   Input Parameter:
3265: . tao - the `TAO` context

3267:   Output Parameter:
3268: . dm - the `DM`

3270:   Level: intermediate

3272: .seealso: [](ch_snes), `DM`, `TAO`, `TaoSetDM()`, `SNESSetDM()`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
3273: @*/
3274: PetscErrorCode TaoGetDM(Tao tao, DM *dm)
3275: {
3276:   PetscFunctionBegin;
3278:   PetscAssertPointer(dm, 2);
3279:   if (!tao->dm) PetscCall(DMShellCreate(PetscObjectComm((PetscObject)tao), &tao->dm));
3280:   *dm = tao->dm;
3281:   PetscFunctionReturn(PETSC_SUCCESS);
3282: }