Actual source code: taosolver.c

  1: #include <petsc/private/taoimpl.h>
  2: #include <petsc/private/snesimpl.h>

  4: PetscBool         TaoRegisterAllCalled = PETSC_FALSE;
  5: PetscFunctionList TaoList              = NULL;

  7: PetscClassId TAO_CLASSID;

  9: PetscLogEvent TAO_Solve;
 10: PetscLogEvent TAO_ObjectiveEval;
 11: PetscLogEvent TAO_GradientEval;
 12: PetscLogEvent TAO_ObjGradEval;
 13: PetscLogEvent TAO_HessianEval;
 14: PetscLogEvent TAO_JacobianEval;
 15: PetscLogEvent TAO_ConstraintsEval;

 17: const char *TaoSubSetTypes[] = {"subvec", "mask", "matrixfree", "TaoSubSetType", "TAO_SUBSET_", NULL};

 19: struct _n_TaoMonitorDrawCtx {
 20:   PetscViewer viewer;
 21:   PetscInt    howoften; /* when > 0 uses iteration % howoften, when negative only final solution plotted */
 22: };

 24: static PetscErrorCode KSPPreSolve_TAOEW_Private(KSP ksp, Vec b, Vec x, void *ctx)
 25: {
 26:   Tao  tao          = (Tao)ctx;
 27:   SNES snes_ewdummy = tao->snes_ewdummy;

 29:   PetscFunctionBegin;
 30:   if (!snes_ewdummy) PetscFunctionReturn(PETSC_SUCCESS);
 31:   /* populate snes_ewdummy struct values used in KSPPreSolve_SNESEW */
 32:   snes_ewdummy->vec_func = b;
 33:   snes_ewdummy->rtol     = tao->gttol;
 34:   snes_ewdummy->iter     = tao->niter;
 35:   PetscCall(VecNorm(b, NORM_2, &snes_ewdummy->norm));
 36:   PetscCall(KSPPreSolve_SNESEW(ksp, b, x, snes_ewdummy));
 37:   snes_ewdummy->vec_func = NULL;
 38:   PetscFunctionReturn(PETSC_SUCCESS);
 39: }

 41: static PetscErrorCode KSPPostSolve_TAOEW_Private(KSP ksp, Vec b, Vec x, void *ctx)
 42: {
 43:   Tao  tao          = (Tao)ctx;
 44:   SNES snes_ewdummy = tao->snes_ewdummy;

 46:   PetscFunctionBegin;
 47:   if (!snes_ewdummy) PetscFunctionReturn(PETSC_SUCCESS);
 48:   PetscCall(KSPPostSolve_SNESEW(ksp, b, x, snes_ewdummy));
 49:   PetscFunctionReturn(PETSC_SUCCESS);
 50: }

 52: static PetscErrorCode TaoSetUpEW_Private(Tao tao)
 53: {
 54:   SNESKSPEW  *kctx;
 55:   const char *ewprefix;

 57:   PetscFunctionBegin;
 58:   if (!tao->ksp) PetscFunctionReturn(PETSC_SUCCESS);
 59:   if (tao->ksp_ewconv) {
 60:     if (!tao->snes_ewdummy) PetscCall(SNESCreate(PetscObjectComm((PetscObject)tao), &tao->snes_ewdummy));
 61:     tao->snes_ewdummy->ksp_ewconv = PETSC_TRUE;
 62:     PetscCall(KSPSetPreSolve(tao->ksp, KSPPreSolve_TAOEW_Private, tao));
 63:     PetscCall(KSPSetPostSolve(tao->ksp, KSPPostSolve_TAOEW_Private, tao));

 65:     PetscCall(KSPGetOptionsPrefix(tao->ksp, &ewprefix));
 66:     kctx = (SNESKSPEW *)tao->snes_ewdummy->kspconvctx;
 67:     PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_FALSE, PetscObjectComm((PetscObject)tao), ewprefix));
 68:   } else PetscCall(SNESDestroy(&tao->snes_ewdummy));
 69:   PetscFunctionReturn(PETSC_SUCCESS);
 70: }

 72: /*@
 73:   TaoParametersInitialize - Sets all the parameters in `tao` to their default value (when `TaoCreate()` was called) if they
 74:   currently contain default values. Default values are the parameter values when the object's type is set.

 76:   Collective

 78:   Input Parameter:
 79: . tao - the `Tao` object

 81:   Level: developer

 83:   Developer Note:
 84:   This is called by all the `TaoCreate_XXX()` routines.

 86: .seealso: [](ch_snes), `Tao`, `TaoSolve()`, `TaoDestroy()`,
 87:           `PetscObjectParameterSetDefault()`
 88: @*/
 89: PetscErrorCode TaoParametersInitialize(Tao tao)
 90: {
 91:   PetscObjectParameterSetDefault(tao, max_it, 10000);
 92:   PetscObjectParameterSetDefault(tao, max_funcs, PETSC_UNLIMITED);
 93:   PetscObjectParameterSetDefault(tao, gatol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
 94:   PetscObjectParameterSetDefault(tao, grtol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
 95:   PetscObjectParameterSetDefault(tao, crtol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
 96:   PetscObjectParameterSetDefault(tao, catol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
 97:   PetscObjectParameterSetDefault(tao, gttol, 0.0);
 98:   PetscObjectParameterSetDefault(tao, steptol, 0.0);
 99:   PetscObjectParameterSetDefault(tao, fmin, PETSC_NINFINITY);
100:   PetscObjectParameterSetDefault(tao, trust0, PETSC_INFINITY);
101:   return PETSC_SUCCESS;
102: }

104: /*@
105:   TaoCreate - Creates a Tao solver

107:   Collective

109:   Input Parameter:
110: . comm - MPI communicator

112:   Output Parameter:
113: . newtao - the new `Tao` context

115:   Options Database Key:
116: . -tao_type - select which method Tao should use

118:   Level: beginner

120: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoDestroy()`, `TaoSetFromOptions()`, `TaoSetType()`
121: @*/
122: PetscErrorCode TaoCreate(MPI_Comm comm, Tao *newtao)
123: {
124:   Tao tao;

126:   PetscFunctionBegin;
127:   PetscAssertPointer(newtao, 2);
128:   PetscCall(TaoInitializePackage());
129:   PetscCall(TaoLineSearchInitializePackage());

131:   PetscCall(PetscHeaderCreate(tao, TAO_CLASSID, "Tao", "Optimization solver", "Tao", comm, TaoDestroy, TaoView));
132:   tao->ops->convergencetest = TaoDefaultConvergenceTest;

134:   tao->hist_reset = PETSC_TRUE;
135:   PetscCall(TaoResetStatistics(tao));
136:   *newtao = tao;
137:   PetscFunctionReturn(PETSC_SUCCESS);
138: }

140: /*@
141:   TaoSolve - Solves an optimization problem min F(x) s.t. l <= x <= u

143:   Collective

145:   Input Parameter:
146: . tao - the `Tao` context

148:   Level: beginner

150:   Notes:
151:   The user must set up the `Tao` object  with calls to `TaoSetSolution()`, `TaoSetObjective()`, `TaoSetGradient()`, and (if using 2nd order method) `TaoSetHessian()`.

153:   You should call `TaoGetConvergedReason()` or run with `-tao_converged_reason` to determine if the optimization algorithm actually succeeded or
154:   why it failed.

156: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoGetConvergedReason()`, `TaoSetUp()`
157:  @*/
158: PetscErrorCode TaoSolve(Tao tao)
159: {
160:   static PetscBool set = PETSC_FALSE;

162:   PetscFunctionBegin;
164:   PetscCall(PetscCitationsRegister("@TechReport{tao-user-ref,\n"
165:                                    "title   = {Toolkit for Advanced Optimization (TAO) Users Manual},\n"
166:                                    "author  = {Todd Munson and Jason Sarich and Stefan Wild and Steve Benson and Lois Curfman McInnes},\n"
167:                                    "Institution = {Argonne National Laboratory},\n"
168:                                    "Year   = 2014,\n"
169:                                    "Number = {ANL/MCS-TM-322 - Revision 3.5},\n"
170:                                    "url    = {https://www.mcs.anl.gov/research/projects/tao/}\n}\n",
171:                                    &set));
172:   tao->header_printed = PETSC_FALSE;
173:   PetscCall(TaoSetUp(tao));
174:   PetscCall(TaoResetStatistics(tao));
175:   if (tao->linesearch) PetscCall(TaoLineSearchReset(tao->linesearch));

177:   PetscCall(PetscLogEventBegin(TAO_Solve, tao, 0, 0, 0));
178:   PetscTryTypeMethod(tao, solve);
179:   PetscCall(PetscLogEventEnd(TAO_Solve, tao, 0, 0, 0));

181:   PetscCall(VecViewFromOptions(tao->solution, (PetscObject)tao, "-tao_view_solution"));

183:   tao->ntotalits += tao->niter;

185:   if (tao->printreason) {
186:     PetscViewer viewer = PETSC_VIEWER_STDOUT_(((PetscObject)tao)->comm);

188:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)tao)->tablevel));
189:     if (tao->reason > 0) {
190:       if (((PetscObject)tao)->prefix) {
191:         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix, TaoConvergedReasons[tao->reason], tao->niter));
192:       } else {
193:         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO solve converged due to %s iterations %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter));
194:       }
195:     } else {
196:       if (((PetscObject)tao)->prefix) {
197:         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO %s solve did not converge due to %s iteration %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix, TaoConvergedReasons[tao->reason], tao->niter));
198:       } else {
199:         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO solve did not converge due to %s iteration %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter));
200:       }
201:     }
202:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)tao)->tablevel));
203:   }
204:   PetscCall(TaoViewFromOptions(tao, NULL, "-tao_view"));
205:   PetscFunctionReturn(PETSC_SUCCESS);
206: }

208: /*@
209:   TaoSetUp - Sets up the internal data structures for the later use
210:   of a Tao solver

212:   Collective

214:   Input Parameter:
215: . tao - the `Tao` context

217:   Level: advanced

219:   Note:
220:   The user will not need to explicitly call `TaoSetUp()`, as it will
221:   automatically be called in `TaoSolve()`.  However, if the user
222:   desires to call it explicitly, it should come after `TaoCreate()`
223:   and any TaoSetSomething() routines, but before `TaoSolve()`.

225: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
226: @*/
227: PetscErrorCode TaoSetUp(Tao tao)
228: {
229:   PetscFunctionBegin;
231:   if (tao->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
232:   PetscCall(TaoSetUpEW_Private(tao));
233:   PetscCheck(tao->solution, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Must call TaoSetSolution");
234:   PetscTryTypeMethod(tao, setup);
235:   tao->setupcalled = PETSC_TRUE;
236:   PetscFunctionReturn(PETSC_SUCCESS);
237: }

239: /*@
240:   TaoDestroy - Destroys the `Tao` context that was created with `TaoCreate()`

242:   Collective

244:   Input Parameter:
245: . tao - the `Tao` context

247:   Level: beginner

249: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
250: @*/
251: PetscErrorCode TaoDestroy(Tao *tao)
252: {
253:   PetscFunctionBegin;
254:   if (!*tao) PetscFunctionReturn(PETSC_SUCCESS);
256:   if (--((PetscObject)*tao)->refct > 0) {
257:     *tao = NULL;
258:     PetscFunctionReturn(PETSC_SUCCESS);
259:   }

261:   PetscTryTypeMethod(*tao, destroy);
262:   PetscCall(KSPDestroy(&(*tao)->ksp));
263:   PetscCall(SNESDestroy(&(*tao)->snes_ewdummy));
264:   PetscCall(TaoLineSearchDestroy(&(*tao)->linesearch));

266:   if ((*tao)->ops->convergencedestroy) {
267:     PetscCall((*(*tao)->ops->convergencedestroy)((*tao)->cnvP));
268:     if ((*tao)->jacobian_state_inv) PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
269:   }
270:   PetscCall(VecDestroy(&(*tao)->solution));
271:   PetscCall(VecDestroy(&(*tao)->gradient));
272:   PetscCall(VecDestroy(&(*tao)->ls_res));

274:   if ((*tao)->gradient_norm) {
275:     PetscCall(PetscObjectDereference((PetscObject)(*tao)->gradient_norm));
276:     PetscCall(VecDestroy(&(*tao)->gradient_norm_tmp));
277:   }

279:   PetscCall(VecDestroy(&(*tao)->XL));
280:   PetscCall(VecDestroy(&(*tao)->XU));
281:   PetscCall(VecDestroy(&(*tao)->IL));
282:   PetscCall(VecDestroy(&(*tao)->IU));
283:   PetscCall(VecDestroy(&(*tao)->DE));
284:   PetscCall(VecDestroy(&(*tao)->DI));
285:   PetscCall(VecDestroy(&(*tao)->constraints));
286:   PetscCall(VecDestroy(&(*tao)->constraints_equality));
287:   PetscCall(VecDestroy(&(*tao)->constraints_inequality));
288:   PetscCall(VecDestroy(&(*tao)->stepdirection));
289:   PetscCall(MatDestroy(&(*tao)->hessian_pre));
290:   PetscCall(MatDestroy(&(*tao)->hessian));
291:   PetscCall(MatDestroy(&(*tao)->ls_jac));
292:   PetscCall(MatDestroy(&(*tao)->ls_jac_pre));
293:   PetscCall(MatDestroy(&(*tao)->jacobian_pre));
294:   PetscCall(MatDestroy(&(*tao)->jacobian));
295:   PetscCall(MatDestroy(&(*tao)->jacobian_state_pre));
296:   PetscCall(MatDestroy(&(*tao)->jacobian_state));
297:   PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
298:   PetscCall(MatDestroy(&(*tao)->jacobian_design));
299:   PetscCall(MatDestroy(&(*tao)->jacobian_equality));
300:   PetscCall(MatDestroy(&(*tao)->jacobian_equality_pre));
301:   PetscCall(MatDestroy(&(*tao)->jacobian_inequality));
302:   PetscCall(MatDestroy(&(*tao)->jacobian_inequality_pre));
303:   PetscCall(ISDestroy(&(*tao)->state_is));
304:   PetscCall(ISDestroy(&(*tao)->design_is));
305:   PetscCall(VecDestroy(&(*tao)->res_weights_v));
306:   PetscCall(TaoMonitorCancel(*tao));
307:   if ((*tao)->hist_malloc) PetscCall(PetscFree4((*tao)->hist_obj, (*tao)->hist_resid, (*tao)->hist_cnorm, (*tao)->hist_lits));
308:   if ((*tao)->res_weights_n) {
309:     PetscCall(PetscFree((*tao)->res_weights_rows));
310:     PetscCall(PetscFree((*tao)->res_weights_cols));
311:     PetscCall(PetscFree((*tao)->res_weights_w));
312:   }
313:   PetscCall(PetscHeaderDestroy(tao));
314:   PetscFunctionReturn(PETSC_SUCCESS);
315: }

317: /*@
318:   TaoKSPSetUseEW - Sets `SNES` to use Eisenstat-Walker method {cite}`ew96`for computing relative tolerance for linear solvers.

320:   Logically Collective

322:   Input Parameters:
323: + tao  - Tao context
324: - flag - `PETSC_TRUE` or `PETSC_FALSE`

326:   Level: advanced

328:   Note:
329:   See `SNESKSPSetUseEW()` for customization details.

331: .seealso: [](ch_tao), `Tao`, `SNESKSPSetUseEW()`
332: @*/
333: PetscErrorCode TaoKSPSetUseEW(Tao tao, PetscBool flag)
334: {
335:   PetscFunctionBegin;
338:   tao->ksp_ewconv = flag;
339:   PetscFunctionReturn(PETSC_SUCCESS);
340: }

342: /*@
343:   TaoSetFromOptions - Sets various Tao parameters from the options database

345:   Collective

347:   Input Parameter:
348: . tao - the `Tao` solver context

350:   Options Database Keys:
351: + -tao_type <type>             - The algorithm that Tao uses (lmvm, nls, etc.)
352: . -tao_gatol <gatol>           - absolute error tolerance for ||gradient||
353: . -tao_grtol <grtol>           - relative error tolerance for ||gradient||
354: . -tao_gttol <gttol>           - reduction of ||gradient|| relative to initial gradient
355: . -tao_max_it <max>            - sets maximum number of iterations
356: . -tao_max_funcs <max>         - sets maximum number of function evaluations
357: . -tao_fmin <fmin>             - stop if function value reaches fmin
358: . -tao_steptol <tol>           - stop if trust region radius less than <tol>
359: . -tao_trust0 <t>              - initial trust region radius
360: . -tao_view_solution           - view the solution at the end of the optimization process
361: . -tao_monitor                 - prints function value and residual norm at each iteration
362: . -tao_monitor_short           - same as `-tao_monitor`, but truncates very small values
363: . -tao_monitor_constraint_norm - prints objective value, gradient, and constraint norm at each iteration
364: . -tao_monitor_globalization   - prints information about the globalization at each iteration
365: . -tao_monitor_solution        - prints solution vector at each iteration
366: . -tao_monitor_ls_residual     - prints least-squares residual vector at each iteration
367: . -tao_monitor_step            - prints step vector at each iteration
368: . -tao_monitor_gradient        - prints gradient vector at each iteration
369: . -tao_monitor_solution_draw   - graphically view solution vector at each iteration
370: . -tao_monitor_step_draw       - graphically view step vector at each iteration
371: . -tao_monitor_gradient_draw   - graphically view gradient at each iteration
372: . -tao_monitor_cancel          - cancels all monitors (except those set with command line)
373: . -tao_fd_gradient             - use gradient computed with finite differences
374: . -tao_fd_hessian              - use hessian computed with finite differences
375: . -tao_mf_hessian              - use matrix-free Hessian computed with finite differences
376: . -tao_view                    - prints information about the Tao after solving
377: - -tao_converged_reason        - prints the reason Tao stopped iterating

379:   Level: beginner

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

385: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
386: @*/
387: PetscErrorCode TaoSetFromOptions(Tao tao)
388: {
389:   TaoType     default_type = TAOLMVM;
390:   char        type[256], monfilename[PETSC_MAX_PATH_LEN];
391:   PetscViewer monviewer;
392:   PetscBool   flg, found;
393:   MPI_Comm    comm;
394:   PetscReal   catol, crtol, gatol, grtol, gttol;

396:   PetscFunctionBegin;
398:   PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));

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

402:   PetscObjectOptionsBegin((PetscObject)tao);
403:   /* Check for type from options */
404:   PetscCall(PetscOptionsFList("-tao_type", "Tao Solver type", "TaoSetType", TaoList, default_type, type, 256, &flg));
405:   if (flg) {
406:     PetscCall(TaoSetType(tao, type));
407:   } else if (!((PetscObject)tao)->type_name) {
408:     PetscCall(TaoSetType(tao, default_type));
409:   }

411:   /* Tao solvers do not set the prefix, set it here if not yet done
412:      We do it after SetType since solver may have been changed */
413:   if (tao->linesearch) {
414:     const char *prefix;
415:     PetscCall(TaoLineSearchGetOptionsPrefix(tao->linesearch, &prefix));
416:     if (!prefix) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, ((PetscObject)tao)->prefix));
417:   }

419:   catol = tao->catol;
420:   crtol = tao->crtol;
421:   PetscCall(PetscOptionsReal("-tao_catol", "Stop if constraints violations within", "TaoSetConstraintTolerances", tao->catol, &catol, NULL));
422:   PetscCall(PetscOptionsReal("-tao_crtol", "Stop if relative constraint violations within", "TaoSetConstraintTolerances", tao->crtol, &crtol, NULL));
423:   PetscCall(TaoSetConstraintTolerances(tao, catol, crtol));

425:   gatol = tao->gatol;
426:   grtol = tao->grtol;
427:   gttol = tao->gttol;
428:   PetscCall(PetscOptionsReal("-tao_gatol", "Stop if norm of gradient less than", "TaoSetTolerances", tao->gatol, &gatol, NULL));
429:   PetscCall(PetscOptionsReal("-tao_grtol", "Stop if norm of gradient divided by the function value is less than", "TaoSetTolerances", tao->grtol, &grtol, NULL));
430:   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));
431:   PetscCall(TaoSetTolerances(tao, gatol, grtol, gttol));

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

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

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

444:   PetscCall(PetscOptionsDeprecated("-tao_solution_monitor", "-tao_monitor_solution", "3.21", NULL));
445:   PetscCall(PetscOptionsDeprecated("-tao_gradient_monitor", "-tao_monitor_gradient", "3.21", NULL));
446:   PetscCall(PetscOptionsDeprecated("-tao_stepdirection_monitor", "-tao_monitor_step", "3.21", NULL));
447:   PetscCall(PetscOptionsDeprecated("-tao_residual_monitor", "-tao_monitor_residual", "3.21", NULL));
448:   PetscCall(PetscOptionsDeprecated("-tao_smonitor", "-tao_monitor_short", "3.21", NULL));
449:   PetscCall(PetscOptionsDeprecated("-tao_cmonitor", "-tao_monitor_constraint_norm", "3.21", NULL));
450:   PetscCall(PetscOptionsDeprecated("-tao_gmonitor", "-tao_monitor_globalization", "3.21", NULL));
451:   PetscCall(PetscOptionsDeprecated("-tao_draw_solution", "-tao_monitor_solution_draw", "3.21", NULL));
452:   PetscCall(PetscOptionsDeprecated("-tao_draw_gradient", "-tao_monitor_gradient_draw", "3.21", NULL));
453:   PetscCall(PetscOptionsDeprecated("-tao_draw_step", "-tao_monitor_step_draw", "3.21", NULL));

455:   PetscCall(PetscOptionsString("-tao_monitor_solution", "View solution vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
456:   if (flg) {
457:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
458:     PetscCall(TaoMonitorSet(tao, TaoMonitorSolution, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
459:   }

461:   PetscCall(PetscOptionsBool("-tao_converged_reason", "Print reason for Tao converged", "TaoSolve", tao->printreason, &tao->printreason, NULL));
462:   PetscCall(PetscOptionsString("-tao_monitor_gradient", "View gradient vector for each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
463:   if (flg) {
464:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
465:     PetscCall(TaoMonitorSet(tao, TaoMonitorGradient, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
466:   }

468:   PetscCall(PetscOptionsString("-tao_monitor_step", "View step vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
469:   if (flg) {
470:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
471:     PetscCall(TaoMonitorSet(tao, TaoMonitorStep, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
472:   }

474:   PetscCall(PetscOptionsString("-tao_monitor_residual", "View least-squares residual vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
475:   if (flg) {
476:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
477:     PetscCall(TaoMonitorSet(tao, TaoMonitorResidual, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
478:   }

480:   PetscCall(PetscOptionsString("-tao_monitor", "Use the default convergence monitor", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
481:   if (flg) {
482:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
483:     PetscCall(TaoMonitorSet(tao, TaoMonitorDefault, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
484:   }

486:   PetscCall(PetscOptionsString("-tao_monitor_globalization", "Use the convergence monitor with extra globalization info", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
487:   if (flg) {
488:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
489:     PetscCall(TaoMonitorSet(tao, TaoMonitorGlobalization, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
490:   }

492:   PetscCall(PetscOptionsString("-tao_monitor_short", "Use the short convergence monitor", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
493:   if (flg) {
494:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
495:     PetscCall(TaoMonitorSet(tao, TaoMonitorDefaultShort, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
496:   }

498:   PetscCall(PetscOptionsString("-tao_monitor_constraint_norm", "Use the default convergence monitor with constraint norm", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
499:   if (flg) {
500:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
501:     PetscCall(TaoMonitorSet(tao, TaoMonitorConstraintNorm, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
502:   }

504:   flg = PETSC_FALSE;
505:   PetscCall(PetscOptionsDeprecated("-tao_cancelmonitors", "-tao_monitor_cancel", "3.21", NULL));
506:   PetscCall(PetscOptionsBool("-tao_monitor_cancel", "cancel all monitors and call any registered destroy routines", "TaoMonitorCancel", flg, &flg, NULL));
507:   if (flg) PetscCall(TaoMonitorCancel(tao));

509:   flg = PETSC_FALSE;
510:   PetscCall(PetscOptionsBool("-tao_monitor_solution_draw", "Plot solution vector at each iteration", "TaoMonitorSet", flg, &flg, NULL));
511:   if (flg) {
512:     TaoMonitorDrawCtx drawctx;
513:     PetscInt          howoften = 1;
514:     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
515:     PetscCall(TaoMonitorSet(tao, TaoMonitorSolutionDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
516:   }

518:   flg = PETSC_FALSE;
519:   PetscCall(PetscOptionsBool("-tao_monitor_step_draw", "Plots step at each iteration", "TaoMonitorSet", flg, &flg, NULL));
520:   if (flg) PetscCall(TaoMonitorSet(tao, TaoMonitorStepDraw, NULL, NULL));

522:   flg = PETSC_FALSE;
523:   PetscCall(PetscOptionsBool("-tao_monitor_gradient_draw", "plots gradient at each iteration", "TaoMonitorSet", flg, &flg, NULL));
524:   if (flg) {
525:     TaoMonitorDrawCtx drawctx;
526:     PetscInt          howoften = 1;
527:     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
528:     PetscCall(TaoMonitorSet(tao, TaoMonitorGradientDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
529:   }
530:   flg = PETSC_FALSE;
531:   PetscCall(PetscOptionsBool("-tao_fd_gradient", "compute gradient using finite differences", "TaoDefaultComputeGradient", flg, &flg, NULL));
532:   if (flg) PetscCall(TaoSetGradient(tao, NULL, TaoDefaultComputeGradient, NULL));
533:   flg = PETSC_FALSE;
534:   PetscCall(PetscOptionsBool("-tao_fd_hessian", "compute Hessian using finite differences", "TaoDefaultComputeHessian", flg, &flg, NULL));
535:   if (flg) {
536:     Mat H;

538:     PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
539:     PetscCall(MatSetType(H, MATAIJ));
540:     PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessian, NULL));
541:     PetscCall(MatDestroy(&H));
542:   }
543:   flg = PETSC_FALSE;
544:   PetscCall(PetscOptionsBool("-tao_mf_hessian", "compute matrix-free Hessian using finite differences", "TaoDefaultComputeHessianMFFD", flg, &flg, NULL));
545:   if (flg) {
546:     Mat H;

548:     PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
549:     PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessianMFFD, NULL));
550:     PetscCall(MatDestroy(&H));
551:   }
552:   PetscCall(PetscOptionsBool("-tao_recycle_history", "enable recycling/re-using information from the previous TaoSolve() call for some algorithms", "TaoSetRecycleHistory", flg, &flg, &found));
553:   if (found) PetscCall(TaoSetRecycleHistory(tao, flg));
554:   PetscCall(PetscOptionsEnum("-tao_subset_type", "subset type", "", TaoSubSetTypes, (PetscEnum)tao->subset_type, (PetscEnum *)&tao->subset_type, NULL));

556:   if (tao->ksp) {
557:     PetscCall(PetscOptionsBool("-tao_ksp_ew", "Use Eisentat-Walker linear system convergence test", "TaoKSPSetUseEW", tao->ksp_ewconv, &tao->ksp_ewconv, NULL));
558:     PetscCall(TaoKSPSetUseEW(tao, tao->ksp_ewconv));
559:   }

561:   PetscTryTypeMethod(tao, setfromoptions, PetscOptionsObject);

563:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
564:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)tao, PetscOptionsObject));
565:   PetscOptionsEnd();

567:   if (tao->linesearch) PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
568:   PetscFunctionReturn(PETSC_SUCCESS);
569: }

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

574:   Collective

576:   Input Parameters:
577: + A    - the  `Tao` context
578: . obj  - Optional object that provides the prefix for the options database
579: - name - command line option

581:   Level: intermediate

583: .seealso: [](ch_tao), `Tao`, `TaoView`, `PetscObjectViewFromOptions()`, `TaoCreate()`
584: @*/
585: PetscErrorCode TaoViewFromOptions(Tao A, PetscObject obj, const char name[])
586: {
587:   PetscFunctionBegin;
589:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
590:   PetscFunctionReturn(PETSC_SUCCESS);
591: }

593: /*@
594:   TaoView - Prints information about the `Tao` object

596:   Collective

598:   Input Parameters:
599: + tao    - the `Tao` context
600: - viewer - visualization context

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

605:   Level: beginner

607:   Notes:
608:   The available visualization contexts include
609: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
610: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
611:   output where only the first processor opens
612:   the file.  All other processors send their
613:   data to the first processor to print.

615: .seealso: [](ch_tao), `Tao`, `PetscViewerASCIIOpen()`
616: @*/
617: PetscErrorCode TaoView(Tao tao, PetscViewer viewer)
618: {
619:   PetscBool isascii, isstring;
620:   TaoType   type;

622:   PetscFunctionBegin;
624:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)tao)->comm, &viewer));
626:   PetscCheckSameComm(tao, 1, viewer, 2);

628:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
629:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
630:   if (isascii) {
631:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)tao, viewer));

633:     PetscCall(PetscViewerASCIIPushTab(viewer));
634:     PetscTryTypeMethod(tao, view, viewer);
635:     if (tao->linesearch) PetscCall(TaoLineSearchView(tao->linesearch, viewer));
636:     if (tao->ksp) {
637:       PetscCall(KSPView(tao->ksp, viewer));
638:       PetscCall(PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", tao->ksp_tot_its));
639:     }

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

643:     PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: gatol=%g,", (double)tao->gatol));
644:     PetscCall(PetscViewerASCIIPrintf(viewer, " grtol=%g,", (double)tao->grtol));
645:     PetscCall(PetscViewerASCIIPrintf(viewer, " steptol=%g,", (double)tao->steptol));
646:     PetscCall(PetscViewerASCIIPrintf(viewer, " gttol=%g\n", (double)tao->gttol));
647:     PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Function/Gradient:=%g\n", (double)tao->residual));

649:     if (tao->constrained) {
650:       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances:"));
651:       PetscCall(PetscViewerASCIIPrintf(viewer, " catol=%g,", (double)tao->catol));
652:       PetscCall(PetscViewerASCIIPrintf(viewer, " crtol=%g\n", (double)tao->crtol));
653:       PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Constraints:=%g\n", (double)tao->cnorm));
654:     }

656:     if (tao->trust < tao->steptol) {
657:       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: steptol=%g\n", (double)tao->steptol));
658:       PetscCall(PetscViewerASCIIPrintf(viewer, "Final trust region radius:=%g\n", (double)tao->trust));
659:     }

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

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

667:     if (tao->nfuncs > 0) {
668:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT ",", tao->nfuncs));
669:       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: unlimited)\n"));
670:       else PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: %" PetscInt_FMT ")\n", tao->max_funcs));
671:     }
672:     if (tao->ngrads > 0) {
673:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT ",", tao->ngrads));
674:       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: unlimited)\n"));
675:       else PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: %" PetscInt_FMT ")\n", tao->max_funcs));
676:     }
677:     if (tao->nfuncgrads > 0) {
678:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT ",", tao->nfuncgrads));
679:       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "    (max: unlimited)\n"));
680:       else PetscCall(PetscViewerASCIIPrintf(viewer, "    (max: %" PetscInt_FMT ")\n", tao->max_funcs));
681:     }
682:     if (tao->nhess > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", tao->nhess));
683:     if (tao->nconstraints > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of constraint function evaluations=%" PetscInt_FMT "\n", tao->nconstraints));
684:     if (tao->njac > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Jacobian evaluations=%" PetscInt_FMT "\n", tao->njac));

686:     if (tao->reason > 0) {
687:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solution converged: "));
688:       switch (tao->reason) {
689:       case TAO_CONVERGED_GATOL:
690:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)|| <= gatol\n"));
691:         break;
692:       case TAO_CONVERGED_GRTOL:
693:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/|f(X)| <= grtol\n"));
694:         break;
695:       case TAO_CONVERGED_GTTOL:
696:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/||g(X0)|| <= gttol\n"));
697:         break;
698:       case TAO_CONVERGED_STEPTOL:
699:         PetscCall(PetscViewerASCIIPrintf(viewer, " Steptol -- step size small\n"));
700:         break;
701:       case TAO_CONVERGED_MINF:
702:         PetscCall(PetscViewerASCIIPrintf(viewer, " Minf --  f < fmin\n"));
703:         break;
704:       case TAO_CONVERGED_USER:
705:         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
706:         break;
707:       default:
708:         PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
709:         break;
710:       }
711:     } else if (tao->reason == TAO_CONTINUE_ITERATING) {
712:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solver never run\n"));
713:     } else {
714:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solver failed: "));
715:       switch (tao->reason) {
716:       case TAO_DIVERGED_MAXITS:
717:         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Iterations\n"));
718:         break;
719:       case TAO_DIVERGED_NAN:
720:         PetscCall(PetscViewerASCIIPrintf(viewer, " NAN or Inf encountered\n"));
721:         break;
722:       case TAO_DIVERGED_MAXFCN:
723:         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Function Evaluations\n"));
724:         break;
725:       case TAO_DIVERGED_LS_FAILURE:
726:         PetscCall(PetscViewerASCIIPrintf(viewer, " Line Search Failure\n"));
727:         break;
728:       case TAO_DIVERGED_TR_REDUCTION:
729:         PetscCall(PetscViewerASCIIPrintf(viewer, " Trust Region too small\n"));
730:         break;
731:       case TAO_DIVERGED_USER:
732:         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
733:         break;
734:       default:
735:         PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
736:         break;
737:       }
738:     }
739:     PetscCall(PetscViewerASCIIPopTab(viewer));
740:   } else if (isstring) {
741:     PetscCall(TaoGetType(tao, &type));
742:     PetscCall(PetscViewerStringSPrintf(viewer, " %-3.3s", type));
743:   }
744:   PetscFunctionReturn(PETSC_SUCCESS);
745: }

747: /*@
748:   TaoSetRecycleHistory - Sets the boolean flag to enable/disable re-using
749:   iterate information from the previous `TaoSolve()`. This feature is disabled by
750:   default.

752:   Logically Collective

754:   Input Parameters:
755: + tao     - the `Tao` context
756: - recycle - boolean flag

758:   Options Database Key:
759: . -tao_recycle_history <true,false> - reuse the history

761:   Level: intermediate

763:   Notes:
764:   For conjugate gradient methods (`TAOBNCG`), this re-uses the latest search direction
765:   from the previous `TaoSolve()` call when computing the first search direction in a
766:   new solution. By default, CG methods set the first search direction to the
767:   negative gradient.

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

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

776: .seealso: [](ch_tao), `Tao`, `TaoGetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
777: @*/
778: PetscErrorCode TaoSetRecycleHistory(Tao tao, PetscBool recycle)
779: {
780:   PetscFunctionBegin;
783:   tao->recycle = recycle;
784:   PetscFunctionReturn(PETSC_SUCCESS);
785: }

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

791:   Logically Collective

793:   Input Parameter:
794: . tao - the `Tao` context

796:   Output Parameter:
797: . recycle - boolean flag

799:   Level: intermediate

801: .seealso: [](ch_tao), `Tao`, `TaoSetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
802: @*/
803: PetscErrorCode TaoGetRecycleHistory(Tao tao, PetscBool *recycle)
804: {
805:   PetscFunctionBegin;
807:   PetscAssertPointer(recycle, 2);
808:   *recycle = tao->recycle;
809:   PetscFunctionReturn(PETSC_SUCCESS);
810: }

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

815:   Logically Collective

817:   Input Parameters:
818: + tao   - the `Tao` context
819: . gatol - stop if norm of gradient is less than this
820: . grtol - stop if relative norm of gradient is less than this
821: - gttol - stop if norm of gradient is reduced by this factor

823:   Options Database Keys:
824: + -tao_gatol <gatol> - Sets gatol
825: . -tao_grtol <grtol> - Sets grtol
826: - -tao_gttol <gttol> - Sets gttol

828:   Stopping Criteria\:
829: .vb
830:   ||g(X)||                            <= gatol
831:   ||g(X)|| / |f(X)|                   <= grtol
832:   ||g(X)|| / ||g(X0)||                <= gttol
833: .ve

835:   Level: beginner

837:   Notes:
838:   Use `PETSC_CURRENT` to leave one or more tolerances unchanged.

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

842:   Fortran Note:
843:   Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`

845: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`
846: @*/
847: PetscErrorCode TaoSetTolerances(Tao tao, PetscReal gatol, PetscReal grtol, PetscReal gttol)
848: {
849:   PetscFunctionBegin;

855:   if (gatol == (PetscReal)PETSC_DETERMINE) {
856:     tao->gatol = tao->default_gatol;
857:   } else if (gatol != (PetscReal)PETSC_CURRENT) {
858:     PetscCheck(gatol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gatol not allowed");
859:     tao->gatol = gatol;
860:   }

862:   if (grtol == (PetscReal)PETSC_DETERMINE) {
863:     tao->grtol = tao->default_grtol;
864:   } else if (grtol != (PetscReal)PETSC_CURRENT) {
865:     PetscCheck(grtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative grtol not allowed");
866:     tao->grtol = grtol;
867:   }

869:   if (gttol == (PetscReal)PETSC_DETERMINE) {
870:     tao->gttol = tao->default_gttol;
871:   } else if (gttol != (PetscReal)PETSC_CURRENT) {
872:     PetscCheck(gttol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gttol not allowed");
873:     tao->gttol = gttol;
874:   }
875:   PetscFunctionReturn(PETSC_SUCCESS);
876: }

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

881:   Logically Collective

883:   Input Parameters:
884: + tao   - the `Tao` context
885: . catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for `gatol` convergence criteria
886: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for `gatol`, `gttol` convergence criteria

888:   Options Database Keys:
889: + -tao_catol <catol> - Sets catol
890: - -tao_crtol <crtol> - Sets crtol

892:   Level: intermediate

894:   Notes:
895:   Use `PETSC_CURRENT` to leave one or tolerance unchanged.

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

899:   Fortran Note:
900:   Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`

902: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoGetConstraintTolerances()`, `TaoSetTolerances()`
903: @*/
904: PetscErrorCode TaoSetConstraintTolerances(Tao tao, PetscReal catol, PetscReal crtol)
905: {
906:   PetscFunctionBegin;

911:   if (catol == (PetscReal)PETSC_DETERMINE) {
912:     tao->catol = tao->default_catol;
913:   } else if (catol != (PetscReal)PETSC_CURRENT) {
914:     PetscCheck(catol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative catol not allowed");
915:     tao->catol = catol;
916:   }

918:   if (crtol == (PetscReal)PETSC_DETERMINE) {
919:     tao->crtol = tao->default_crtol;
920:   } else if (crtol != (PetscReal)PETSC_CURRENT) {
921:     PetscCheck(crtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative crtol not allowed");
922:     tao->crtol = crtol;
923:   }
924:   PetscFunctionReturn(PETSC_SUCCESS);
925: }

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

930:   Not Collective

932:   Input Parameter:
933: . tao - the `Tao` context

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

939:   Level: intermediate

941: .seealso: [](ch_tao), `Tao`, `TaoConvergedReasons`,`TaoGetTolerances()`, `TaoSetTolerances()`, `TaoSetConstraintTolerances()`
942: @*/
943: PetscErrorCode TaoGetConstraintTolerances(Tao tao, PetscReal *catol, PetscReal *crtol)
944: {
945:   PetscFunctionBegin;
947:   if (catol) *catol = tao->catol;
948:   if (crtol) *crtol = tao->crtol;
949:   PetscFunctionReturn(PETSC_SUCCESS);
950: }

952: /*@
953:   TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
954:   When an approximate solution with an objective value below this number
955:   has been found, the solver will terminate.

957:   Logically Collective

959:   Input Parameters:
960: + tao  - the Tao solver context
961: - fmin - the tolerance

963:   Options Database Key:
964: . -tao_fmin <fmin> - sets the minimum function value

966:   Level: intermediate

968: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetTolerances()`
969: @*/
970: PetscErrorCode TaoSetFunctionLowerBound(Tao tao, PetscReal fmin)
971: {
972:   PetscFunctionBegin;
975:   tao->fmin = fmin;
976:   PetscFunctionReturn(PETSC_SUCCESS);
977: }

979: /*@
980:   TaoGetFunctionLowerBound - Gets the bound on the solution objective value.
981:   When an approximate solution with an objective value below this number
982:   has been found, the solver will terminate.

984:   Not Collective

986:   Input Parameter:
987: . tao - the `Tao` solver context

989:   Output Parameter:
990: . fmin - the minimum function value

992:   Level: intermediate

994: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetFunctionLowerBound()`
995: @*/
996: PetscErrorCode TaoGetFunctionLowerBound(Tao tao, PetscReal *fmin)
997: {
998:   PetscFunctionBegin;
1000:   PetscAssertPointer(fmin, 2);
1001:   *fmin = tao->fmin;
1002:   PetscFunctionReturn(PETSC_SUCCESS);
1003: }

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

1008:   Logically Collective

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

1014:   Options Database Key:
1015: . -tao_max_funcs <nfcn> - sets the maximum number of function evaluations

1017:   Level: intermediate

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

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

1025: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumIterations()`
1026: @*/
1027: PetscErrorCode TaoSetMaximumFunctionEvaluations(Tao tao, PetscInt nfcn)
1028: {
1029:   PetscFunctionBegin;
1032:   if (nfcn == PETSC_DETERMINE) {
1033:     tao->max_funcs = tao->default_max_funcs;
1034:   } else if (nfcn == PETSC_UNLIMITED || nfcn < 0) {
1035:     tao->max_funcs = PETSC_UNLIMITED;
1036:   } else {
1037:     PetscCheck(nfcn >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations  must be positive");
1038:     tao->max_funcs = nfcn;
1039:   }
1040:   PetscFunctionReturn(PETSC_SUCCESS);
1041: }

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

1046:   Logically Collective

1048:   Input Parameter:
1049: . tao - the `Tao` solver context

1051:   Output Parameter:
1052: . nfcn - the maximum number of function evaluations

1054:   Level: intermediate

1056: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1057: @*/
1058: PetscErrorCode TaoGetMaximumFunctionEvaluations(Tao tao, PetscInt *nfcn)
1059: {
1060:   PetscFunctionBegin;
1062:   PetscAssertPointer(nfcn, 2);
1063:   *nfcn = tao->max_funcs;
1064:   PetscFunctionReturn(PETSC_SUCCESS);
1065: }

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

1070:   Not Collective

1072:   Input Parameter:
1073: . tao - the `Tao` solver context

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

1078:   Level: intermediate

1080: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1081: @*/
1082: PetscErrorCode TaoGetCurrentFunctionEvaluations(Tao tao, PetscInt *nfuncs)
1083: {
1084:   PetscFunctionBegin;
1086:   PetscAssertPointer(nfuncs, 2);
1087:   *nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1088:   PetscFunctionReturn(PETSC_SUCCESS);
1089: }

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

1094:   Logically Collective

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

1100:   Options Database Key:
1101: . -tao_max_it <its> - sets the maximum number of iterations

1103:   Level: intermediate

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

1108:   Developer Note:
1109:   DeprAlso accepts the deprecated negative values to indicate no limit

1111: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumFunctionEvaluations()`
1112: @*/
1113: PetscErrorCode TaoSetMaximumIterations(Tao tao, PetscInt maxits)
1114: {
1115:   PetscFunctionBegin;
1118:   if (maxits == PETSC_DETERMINE) {
1119:     tao->max_it = tao->default_max_it;
1120:   } else if (maxits == PETSC_UNLIMITED) {
1121:     tao->max_it = PETSC_INT_MAX;
1122:   } else {
1123:     PetscCheck(maxits > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations must be positive");
1124:     tao->max_it = maxits;
1125:   }
1126:   PetscFunctionReturn(PETSC_SUCCESS);
1127: }

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

1132:   Not Collective

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

1137:   Output Parameter:
1138: . maxits - the maximum number of iterates

1140:   Level: intermediate

1142: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumIterations()`, `TaoGetMaximumFunctionEvaluations()`
1143: @*/
1144: PetscErrorCode TaoGetMaximumIterations(Tao tao, PetscInt *maxits)
1145: {
1146:   PetscFunctionBegin;
1148:   PetscAssertPointer(maxits, 2);
1149:   *maxits = tao->max_it;
1150:   PetscFunctionReturn(PETSC_SUCCESS);
1151: }

1153: /*@
1154:   TaoSetInitialTrustRegionRadius - Sets the initial trust region radius.

1156:   Logically Collective

1158:   Input Parameters:
1159: + tao    - a `Tao` optimization solver
1160: - radius - the trust region radius

1162:   Options Database Key:
1163: . -tao_trust0 <t0> - sets initial trust region radius

1165:   Level: intermediate

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

1170: .seealso: [](ch_tao), `Tao`, `TaoGetTrustRegionRadius()`, `TaoSetTrustRegionTolerance()`, `TAONTR`
1171: @*/
1172: PetscErrorCode TaoSetInitialTrustRegionRadius(Tao tao, PetscReal radius)
1173: {
1174:   PetscFunctionBegin;
1177:   if (radius == PETSC_DETERMINE) {
1178:     tao->trust0 = tao->default_trust0;
1179:   } else {
1180:     PetscCheck(radius > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Radius must be positive");
1181:     tao->trust0 = radius;
1182:   }
1183:   PetscFunctionReturn(PETSC_SUCCESS);
1184: }

1186: /*@
1187:   TaoGetInitialTrustRegionRadius - Gets the initial trust region radius.

1189:   Not Collective

1191:   Input Parameter:
1192: . tao - a `Tao` optimization solver

1194:   Output Parameter:
1195: . radius - the trust region radius

1197:   Level: intermediate

1199: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetCurrentTrustRegionRadius()`, `TAONTR`
1200: @*/
1201: PetscErrorCode TaoGetInitialTrustRegionRadius(Tao tao, PetscReal *radius)
1202: {
1203:   PetscFunctionBegin;
1205:   PetscAssertPointer(radius, 2);
1206:   *radius = tao->trust0;
1207:   PetscFunctionReturn(PETSC_SUCCESS);
1208: }

1210: /*@
1211:   TaoGetCurrentTrustRegionRadius - Gets the current trust region radius.

1213:   Not Collective

1215:   Input Parameter:
1216: . tao - a `Tao` optimization solver

1218:   Output Parameter:
1219: . radius - the trust region radius

1221:   Level: intermediate

1223: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetInitialTrustRegionRadius()`, `TAONTR`
1224: @*/
1225: PetscErrorCode TaoGetCurrentTrustRegionRadius(Tao tao, PetscReal *radius)
1226: {
1227:   PetscFunctionBegin;
1229:   PetscAssertPointer(radius, 2);
1230:   *radius = tao->trust;
1231:   PetscFunctionReturn(PETSC_SUCCESS);
1232: }

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

1237:   Not Collective

1239:   Input Parameter:
1240: . tao - the `Tao` context

1242:   Output Parameters:
1243: + gatol - stop if norm of gradient is less than this
1244: . grtol - stop if relative norm of gradient is less than this
1245: - gttol - stop if norm of gradient is reduced by a this factor

1247:   Level: intermediate

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

1252: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`
1253: @*/
1254: PetscErrorCode TaoGetTolerances(Tao tao, PetscReal *gatol, PetscReal *grtol, PetscReal *gttol)
1255: {
1256:   PetscFunctionBegin;
1258:   if (gatol) *gatol = tao->gatol;
1259:   if (grtol) *grtol = tao->grtol;
1260:   if (gttol) *gttol = tao->gttol;
1261:   PetscFunctionReturn(PETSC_SUCCESS);
1262: }

1264: /*@
1265:   TaoGetKSP - Gets the linear solver used by the optimization solver.

1267:   Not Collective

1269:   Input Parameter:
1270: . tao - the `Tao` solver

1272:   Output Parameter:
1273: . ksp - the `KSP` linear solver used in the optimization solver

1275:   Level: intermediate

1277: .seealso: [](ch_tao), `Tao`, `KSP`
1278: @*/
1279: PetscErrorCode TaoGetKSP(Tao tao, KSP *ksp)
1280: {
1281:   PetscFunctionBegin;
1283:   PetscAssertPointer(ksp, 2);
1284:   *ksp = tao->ksp;
1285:   PetscFunctionReturn(PETSC_SUCCESS);
1286: }

1288: /*@
1289:   TaoGetLinearSolveIterations - Gets the total number of linear iterations
1290:   used by the `Tao` solver

1292:   Not Collective

1294:   Input Parameter:
1295: . tao - the `Tao` context

1297:   Output Parameter:
1298: . lits - number of linear iterations

1300:   Level: intermediate

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

1305: .seealso: [](ch_tao), `Tao`, `TaoGetKSP()`
1306: @*/
1307: PetscErrorCode TaoGetLinearSolveIterations(Tao tao, PetscInt *lits)
1308: {
1309:   PetscFunctionBegin;
1311:   PetscAssertPointer(lits, 2);
1312:   *lits = tao->ksp_tot_its;
1313:   PetscFunctionReturn(PETSC_SUCCESS);
1314: }

1316: /*@
1317:   TaoGetLineSearch - Gets the line search used by the optimization solver.

1319:   Not Collective

1321:   Input Parameter:
1322: . tao - the `Tao` solver

1324:   Output Parameter:
1325: . ls - the line search used in the optimization solver

1327:   Level: intermediate

1329: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`
1330: @*/
1331: PetscErrorCode TaoGetLineSearch(Tao tao, TaoLineSearch *ls)
1332: {
1333:   PetscFunctionBegin;
1335:   PetscAssertPointer(ls, 2);
1336:   *ls = tao->linesearch;
1337:   PetscFunctionReturn(PETSC_SUCCESS);
1338: }

1340: /*@
1341:   TaoAddLineSearchCounts - Adds the number of function evaluations spent
1342:   in the line search to the running total.

1344:   Input Parameters:
1345: . tao - the `Tao` solver

1347:   Level: developer

1349: .seealso: [](ch_tao), `Tao`, `TaoGetLineSearch()`, `TaoLineSearchApply()`
1350: @*/
1351: PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1352: {
1353:   PetscBool flg;
1354:   PetscInt  nfeval, ngeval, nfgeval;

1356:   PetscFunctionBegin;
1358:   if (tao->linesearch) {
1359:     PetscCall(TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg));
1360:     if (!flg) {
1361:       PetscCall(TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval));
1362:       tao->nfuncs += nfeval;
1363:       tao->ngrads += ngeval;
1364:       tao->nfuncgrads += nfgeval;
1365:     }
1366:   }
1367:   PetscFunctionReturn(PETSC_SUCCESS);
1368: }

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

1373:   Not Collective

1375:   Input Parameter:
1376: . tao - the `Tao` context

1378:   Output Parameter:
1379: . X - the current solution

1381:   Level: intermediate

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

1386: .seealso: [](ch_tao), `Tao`, `TaoSetSolution()`, `TaoSolve()`
1387: @*/
1388: PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1389: {
1390:   PetscFunctionBegin;
1392:   PetscAssertPointer(X, 2);
1393:   *X = tao->solution;
1394:   PetscFunctionReturn(PETSC_SUCCESS);
1395: }

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

1402:   Collective

1404:   Input Parameter:
1405: . tao - the `Tao` context

1407:   Level: developer

1409: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
1410: @*/
1411: PetscErrorCode TaoResetStatistics(Tao tao)
1412: {
1413:   PetscFunctionBegin;
1415:   tao->niter        = 0;
1416:   tao->nfuncs       = 0;
1417:   tao->nfuncgrads   = 0;
1418:   tao->ngrads       = 0;
1419:   tao->nhess        = 0;
1420:   tao->njac         = 0;
1421:   tao->nconstraints = 0;
1422:   tao->ksp_its      = 0;
1423:   tao->ksp_tot_its  = 0;
1424:   tao->reason       = TAO_CONTINUE_ITERATING;
1425:   tao->residual     = 0.0;
1426:   tao->cnorm        = 0.0;
1427:   tao->step         = 0.0;
1428:   tao->lsflag       = PETSC_FALSE;
1429:   if (tao->hist_reset) tao->hist_len = 0;
1430:   PetscFunctionReturn(PETSC_SUCCESS);
1431: }

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

1438:   Logically Collective

1440:   Input Parameters:
1441: + tao  - The `Tao` solver
1442: . func - The function
1443: - ctx  - The update function context

1445:   Calling sequence of `func`:
1446: + tao - The optimizer context
1447: . it  - The current iteration index
1448: - ctx - The update context

1450:   Level: advanced

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

1456: .seealso: [](ch_tao), `Tao`, `TaoSolve()`
1457: @*/
1458: PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao tao, PetscInt it, void *ctx), void *ctx)
1459: {
1460:   PetscFunctionBegin;
1462:   tao->ops->update = func;
1463:   tao->user_update = ctx;
1464:   PetscFunctionReturn(PETSC_SUCCESS);
1465: }

1467: /*@C
1468:   TaoSetConvergenceTest - Sets the function that is to be used to test
1469:   for convergence of the iterative minimization solution.  The new convergence
1470:   testing routine will replace Tao's default convergence test.

1472:   Logically Collective

1474:   Input Parameters:
1475: + tao  - the `Tao` object
1476: . conv - the routine to test for convergence
1477: - ctx  - [optional] context for private data for the convergence routine
1478:         (may be `NULL`)

1480:   Calling sequence of `conv`:
1481: + tao - the `Tao` object
1482: - ctx - [optional] convergence context

1484:   Level: advanced

1486:   Note:
1487:   The new convergence testing routine should call `TaoSetConvergedReason()`.

1489: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoMonitorSet()`
1490: @*/
1491: PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao, void *), void *ctx)
1492: {
1493:   PetscFunctionBegin;
1495:   tao->ops->convergencetest = conv;
1496:   tao->cnvP                 = ctx;
1497:   PetscFunctionReturn(PETSC_SUCCESS);
1498: }

1500: /*@C
1501:   TaoMonitorSet - Sets an additional function that is to be used at every
1502:   iteration of the solver to display the iteration's
1503:   progress.

1505:   Logically Collective

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

1513:   Calling sequence of `func`:
1514: + tao - the `Tao` solver context
1515: - ctx - [optional] monitoring context

1517:   Level: intermediate

1519:   Notes:
1520:   See `TaoSetFromOptions()` for a monitoring options.

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

1526:   Fortran Notes:
1527:   Only one monitor function may be set

1529: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoMonitorDefault()`, `TaoMonitorCancel()`, `TaoSetDestroyRoutine()`, `TaoView()`, `PetscCtxDestroyFn`
1530: @*/
1531: PetscErrorCode TaoMonitorSet(Tao tao, PetscErrorCode (*func)(Tao, void *), void *ctx, PetscCtxDestroyFn *dest)
1532: {
1533:   PetscFunctionBegin;
1535:   PetscCheck(tao->numbermonitors < MAXTAOMONITORS, PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Cannot attach another monitor -- max=%d", MAXTAOMONITORS);
1536:   for (PetscInt i = 0; i < tao->numbermonitors; i++) {
1537:     PetscBool identical;

1539:     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)func, ctx, dest, (PetscErrorCode (*)(void))(PetscVoidFn *)tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical));
1540:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1541:   }
1542:   tao->monitor[tao->numbermonitors]        = func;
1543:   tao->monitorcontext[tao->numbermonitors] = ctx;
1544:   tao->monitordestroy[tao->numbermonitors] = dest;
1545:   ++tao->numbermonitors;
1546:   PetscFunctionReturn(PETSC_SUCCESS);
1547: }

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

1552:   Logically Collective

1554:   Input Parameter:
1555: . tao - the `Tao` solver context

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

1562:   Level: advanced

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

1567: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1568: @*/
1569: PetscErrorCode TaoMonitorCancel(Tao tao)
1570: {
1571:   PetscInt i;

1573:   PetscFunctionBegin;
1575:   for (i = 0; i < tao->numbermonitors; i++) {
1576:     if (tao->monitordestroy[i]) PetscCall((*tao->monitordestroy[i])(&tao->monitorcontext[i]));
1577:   }
1578:   tao->numbermonitors = 0;
1579:   PetscFunctionReturn(PETSC_SUCCESS);
1580: }

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

1585:   Collective

1587:   Input Parameters:
1588: + tao - the `Tao` context
1589: - ctx - `PetscViewer` context or `NULL`

1591:   Options Database Key:
1592: . -tao_monitor - turn on default monitoring

1594:   Level: advanced

1596:   Note:
1597:   This monitor prints the function value and gradient
1598:   norm at each iteration.

1600: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1601: @*/
1602: PetscErrorCode TaoMonitorDefault(Tao tao, void *ctx)
1603: {
1604:   PetscInt    its, tabs;
1605:   PetscReal   fct, gnorm;
1606:   PetscViewer viewer = (PetscViewer)ctx;

1608:   PetscFunctionBegin;
1611:   its   = tao->niter;
1612:   fct   = tao->fc;
1613:   gnorm = tao->residual;
1614:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1615:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1616:   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1617:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1618:     tao->header_printed = PETSC_TRUE;
1619:   }
1620:   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1621:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1622:   if (gnorm >= PETSC_INFINITY) {
1623:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf \n"));
1624:   } else {
1625:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g \n", (double)gnorm));
1626:   }
1627:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1628:   PetscFunctionReturn(PETSC_SUCCESS);
1629: }

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

1634:   Collective

1636:   Input Parameters:
1637: + tao - the `Tao` context
1638: - ctx - `PetscViewer` context or `NULL`

1640:   Options Database Key:
1641: . -tao_monitor_globalization - turn on monitoring with globalization information

1643:   Level: advanced

1645:   Note:
1646:   This monitor prints the function value and gradient norm at each
1647:   iteration, as well as the step size and trust radius. Note that the
1648:   step size and trust radius may be the same for some algorithms.

1650: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1651: @*/
1652: PetscErrorCode TaoMonitorGlobalization(Tao tao, void *ctx)
1653: {
1654:   PetscInt    its, tabs;
1655:   PetscReal   fct, gnorm, stp, tr;
1656:   PetscViewer viewer = (PetscViewer)ctx;

1658:   PetscFunctionBegin;
1661:   its   = tao->niter;
1662:   fct   = tao->fc;
1663:   gnorm = tao->residual;
1664:   stp   = tao->step;
1665:   tr    = tao->trust;
1666:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1667:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1668:   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1669:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1670:     tao->header_printed = PETSC_TRUE;
1671:   }
1672:   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1673:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1674:   if (gnorm >= PETSC_INFINITY) {
1675:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf,"));
1676:   } else {
1677:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g,", (double)gnorm));
1678:   }
1679:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Step: %g,  Trust: %g\n", (double)stp, (double)tr));
1680:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1681:   PetscFunctionReturn(PETSC_SUCCESS);
1682: }

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

1687:   Collective

1689:   Input Parameters:
1690: + tao - the `Tao` context
1691: - ctx - `PetscViewer` context of type `PETSCVIEWERASCII`

1693:   Options Database Key:
1694: . -tao_monitor_short - turn on default short monitoring

1696:   Level: advanced

1698:   Note:
1699:   Same as `TaoMonitorDefault()` except
1700:   it prints fewer digits of the residual as the residual gets smaller.
1701:   This is because the later digits are meaningless and are often
1702:   different on different machines; by using this routine different
1703:   machines will usually generate the same output.

1705: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1706: @*/
1707: PetscErrorCode TaoMonitorDefaultShort(Tao tao, void *ctx)
1708: {
1709:   PetscInt    its, tabs;
1710:   PetscReal   fct, gnorm;
1711:   PetscViewer viewer = (PetscViewer)ctx;

1713:   PetscFunctionBegin;
1716:   its   = tao->niter;
1717:   fct   = tao->fc;
1718:   gnorm = tao->residual;
1719:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1720:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1721:   PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %3" PetscInt_FMT ",", its));
1722:   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value %g,", (double)fct));
1723:   if (gnorm >= PETSC_INFINITY) {
1724:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf \n"));
1725:   } else if (gnorm > 1.e-6) {
1726:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm));
1727:   } else if (gnorm > 1.e-11) {
1728:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-6 \n"));
1729:   } else {
1730:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-11 \n"));
1731:   }
1732:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1733:   PetscFunctionReturn(PETSC_SUCCESS);
1734: }

1736: /*@
1737:   TaoMonitorConstraintNorm - same as `TaoMonitorDefault()` except
1738:   it prints the norm of the constraint function.

1740:   Collective

1742:   Input Parameters:
1743: + tao - the `Tao` context
1744: - ctx - `PetscViewer` context or `NULL`

1746:   Options Database Key:
1747: . -tao_monitor_constraint_norm - monitor the constraints

1749:   Level: advanced

1751: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1752: @*/
1753: PetscErrorCode TaoMonitorConstraintNorm(Tao tao, void *ctx)
1754: {
1755:   PetscInt    its, tabs;
1756:   PetscReal   fct, gnorm;
1757:   PetscViewer viewer = (PetscViewer)ctx;

1759:   PetscFunctionBegin;
1762:   its   = tao->niter;
1763:   fct   = tao->fc;
1764:   gnorm = tao->residual;
1765:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1766:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1767:   PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", its));
1768:   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct));
1769:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g ", (double)gnorm));
1770:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Constraint: %g \n", (double)tao->cnorm));
1771:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1772:   PetscFunctionReturn(PETSC_SUCCESS);
1773: }

1775: /*@C
1776:   TaoMonitorSolution - Views the solution at each iteration of `TaoSolve()`

1778:   Collective

1780:   Input Parameters:
1781: + tao - the `Tao` context
1782: - ctx - `PetscViewer` context or `NULL`

1784:   Options Database Key:
1785: . -tao_monitor_solution - view the solution

1787:   Level: advanced

1789: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1790: @*/
1791: PetscErrorCode TaoMonitorSolution(Tao tao, void *ctx)
1792: {
1793:   PetscViewer viewer = (PetscViewer)ctx;

1795:   PetscFunctionBegin;
1798:   PetscCall(VecView(tao->solution, viewer));
1799:   PetscFunctionReturn(PETSC_SUCCESS);
1800: }

1802: /*@C
1803:   TaoMonitorGradient - Views the gradient at each iteration of `TaoSolve()`

1805:   Collective

1807:   Input Parameters:
1808: + tao - the `Tao` context
1809: - ctx - `PetscViewer` context or `NULL`

1811:   Options Database Key:
1812: . -tao_monitor_gradient - view the gradient at each iteration

1814:   Level: advanced

1816: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1817: @*/
1818: PetscErrorCode TaoMonitorGradient(Tao tao, void *ctx)
1819: {
1820:   PetscViewer viewer = (PetscViewer)ctx;

1822:   PetscFunctionBegin;
1825:   PetscCall(VecView(tao->gradient, viewer));
1826:   PetscFunctionReturn(PETSC_SUCCESS);
1827: }

1829: /*@C
1830:   TaoMonitorStep - Views the step-direction at each iteration of `TaoSolve()`

1832:   Collective

1834:   Input Parameters:
1835: + tao - the `Tao` context
1836: - ctx - `PetscViewer` context or `NULL`

1838:   Options Database Key:
1839: . -tao_monitor_step - view the step vector at each iteration

1841:   Level: advanced

1843: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1844: @*/
1845: PetscErrorCode TaoMonitorStep(Tao tao, void *ctx)
1846: {
1847:   PetscViewer viewer = (PetscViewer)ctx;

1849:   PetscFunctionBegin;
1852:   PetscCall(VecView(tao->stepdirection, viewer));
1853:   PetscFunctionReturn(PETSC_SUCCESS);
1854: }

1856: /*@C
1857:   TaoMonitorSolutionDraw - Plots the solution at each iteration of `TaoSolve()`

1859:   Collective

1861:   Input Parameters:
1862: + tao - the `Tao` context
1863: - ctx - `TaoMonitorDraw` context

1865:   Options Database Key:
1866: . -tao_monitor_solution_draw - draw the solution at each iteration

1868:   Level: advanced

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

1874: .seealso: [](ch_tao), `Tao`, `TaoMonitorSolution()`, `TaoMonitorSet()`, `TaoMonitorGradientDraw()`, `TaoMonitorDrawCtxCreate()`,
1875:           `TaoMonitorDrawCtxDestroy()`
1876: @*/
1877: PetscErrorCode TaoMonitorSolutionDraw(Tao tao, void *ctx)
1878: {
1879:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

1881:   PetscFunctionBegin;
1883:   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1884:   PetscCall(VecView(tao->solution, ictx->viewer));
1885:   PetscFunctionReturn(PETSC_SUCCESS);
1886: }

1888: /*@C
1889:   TaoMonitorGradientDraw - Plots the gradient at each iteration of `TaoSolve()`

1891:   Collective

1893:   Input Parameters:
1894: + tao - the `Tao` context
1895: - ctx - `PetscViewer` context

1897:   Options Database Key:
1898: . -tao_monitor_gradient_draw - draw the gradient at each iteration

1900:   Level: advanced

1902: .seealso: [](ch_tao), `Tao`, `TaoMonitorGradient()`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw()`
1903: @*/
1904: PetscErrorCode TaoMonitorGradientDraw(Tao tao, void *ctx)
1905: {
1906:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

1908:   PetscFunctionBegin;
1910:   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1911:   PetscCall(VecView(tao->gradient, ictx->viewer));
1912:   PetscFunctionReturn(PETSC_SUCCESS);
1913: }

1915: /*@C
1916:   TaoMonitorStepDraw - Plots the step direction at each iteration of `TaoSolve()`

1918:   Collective

1920:   Input Parameters:
1921: + tao - the `Tao` context
1922: - ctx - the `PetscViewer` context

1924:   Options Database Key:
1925: . -tao_monitor_step_draw - draw the step direction at each iteration

1927:   Level: advanced

1929: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw`
1930: @*/
1931: PetscErrorCode TaoMonitorStepDraw(Tao tao, void *ctx)
1932: {
1933:   PetscViewer viewer = (PetscViewer)ctx;

1935:   PetscFunctionBegin;
1938:   PetscCall(VecView(tao->stepdirection, viewer));
1939:   PetscFunctionReturn(PETSC_SUCCESS);
1940: }

1942: /*@C
1943:   TaoMonitorResidual - Views the least-squares residual at each iteration of `TaoSolve()`

1945:   Collective

1947:   Input Parameters:
1948: + tao - the `Tao` context
1949: - ctx - the `PetscViewer` context or `NULL`

1951:   Options Database Key:
1952: . -tao_monitor_ls_residual - view the residual at each iteration

1954:   Level: advanced

1956: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1957: @*/
1958: PetscErrorCode TaoMonitorResidual(Tao tao, void *ctx)
1959: {
1960:   PetscViewer viewer = (PetscViewer)ctx;

1962:   PetscFunctionBegin;
1965:   PetscCall(VecView(tao->ls_res, viewer));
1966:   PetscFunctionReturn(PETSC_SUCCESS);
1967: }

1969: /*@
1970:   TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
1971:   or terminate.

1973:   Collective

1975:   Input Parameters:
1976: + tao   - the `Tao` context
1977: - dummy - unused dummy context

1979:   Level: developer

1981:   Notes:
1982:   This routine checks the residual in the optimality conditions, the
1983:   relative residual in the optimity conditions, the number of function
1984:   evaluations, and the function value to test convergence.  Some
1985:   solvers may use different convergence routines.

1987: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
1988: @*/
1989: PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
1990: {
1991:   PetscInt           niter = tao->niter, nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1992:   PetscInt           max_funcs = tao->max_funcs;
1993:   PetscReal          gnorm = tao->residual, gnorm0 = tao->gnorm0;
1994:   PetscReal          f = tao->fc, steptol = tao->steptol, trradius = tao->step;
1995:   PetscReal          gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
1996:   PetscReal          catol = tao->catol, crtol = tao->crtol;
1997:   PetscReal          fmin = tao->fmin, cnorm = tao->cnorm;
1998:   TaoConvergedReason reason = tao->reason;

2000:   PetscFunctionBegin;
2002:   if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);

2004:   if (PetscIsInfOrNanReal(f)) {
2005:     PetscCall(PetscInfo(tao, "Failed to converged, function value is Inf or NaN\n"));
2006:     reason = TAO_DIVERGED_NAN;
2007:   } else if (f <= fmin && cnorm <= catol) {
2008:     PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
2009:     reason = TAO_CONVERGED_MINF;
2010:   } else if (gnorm <= gatol && cnorm <= catol) {
2011:     PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
2012:     reason = TAO_CONVERGED_GATOL;
2013:   } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
2014:     PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
2015:     reason = TAO_CONVERGED_GRTOL;
2016:   } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
2017:     PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
2018:     reason = TAO_CONVERGED_GTTOL;
2019:   } else if (max_funcs != PETSC_UNLIMITED && nfuncs > max_funcs) {
2020:     PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
2021:     reason = TAO_DIVERGED_MAXFCN;
2022:   } else if (tao->lsflag != 0) {
2023:     PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
2024:     reason = TAO_DIVERGED_LS_FAILURE;
2025:   } else if (trradius < steptol && niter > 0) {
2026:     PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
2027:     reason = TAO_CONVERGED_STEPTOL;
2028:   } else if (niter >= tao->max_it) {
2029:     PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
2030:     reason = TAO_DIVERGED_MAXITS;
2031:   } else {
2032:     reason = TAO_CONTINUE_ITERATING;
2033:   }
2034:   tao->reason = reason;
2035:   PetscFunctionReturn(PETSC_SUCCESS);
2036: }

2038: /*@
2039:   TaoSetOptionsPrefix - Sets the prefix used for searching for all
2040:   Tao options in the database.

2042:   Logically Collective

2044:   Input Parameters:
2045: + tao - the `Tao` context
2046: - p   - the prefix string to prepend to all Tao option requests

2048:   Level: advanced

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

2054:   For example, to distinguish between the runtime options for two
2055:   different Tao solvers, one could call
2056: .vb
2057:       TaoSetOptionsPrefix(tao1,"sys1_")
2058:       TaoSetOptionsPrefix(tao2,"sys2_")
2059: .ve

2061:   This would enable use of different options for each system, such as
2062: .vb
2063:       -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2064:       -sys2_tao_method lmvm  -sys2_tao_grtol 1.e-4
2065: .ve

2067: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2068: @*/
2069: PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2070: {
2071:   PetscFunctionBegin;
2073:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2074:   if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2075:   if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2076:   PetscFunctionReturn(PETSC_SUCCESS);
2077: }

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

2082:   Logically Collective

2084:   Input Parameters:
2085: + tao - the `Tao` solver context
2086: - p   - the prefix string to prepend to all `Tao` option requests

2088:   Level: advanced

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

2094: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2095: @*/
2096: PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2097: {
2098:   PetscFunctionBegin;
2100:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2101:   if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2102:   if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2103:   PetscFunctionReturn(PETSC_SUCCESS);
2104: }

2106: /*@
2107:   TaoGetOptionsPrefix - Gets the prefix used for searching for all
2108:   Tao options in the database

2110:   Not Collective

2112:   Input Parameter:
2113: . tao - the `Tao` context

2115:   Output Parameter:
2116: . p - pointer to the prefix string used is returned

2118:   Level: advanced

2120: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2121: @*/
2122: PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2123: {
2124:   PetscFunctionBegin;
2126:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2127:   PetscFunctionReturn(PETSC_SUCCESS);
2128: }

2130: /*@
2131:   TaoSetType - Sets the `TaoType` for the minimization solver.

2133:   Collective

2135:   Input Parameters:
2136: + tao  - the `Tao` solver context
2137: - type - a known method

2139:   Options Database Key:
2140: . -tao_type <type> - Sets the method; use -help for a list
2141:    of available methods (for instance, "-tao_type lmvm" or "-tao_type tron")

2143:   Level: intermediate

2145: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2146: @*/
2147: PetscErrorCode TaoSetType(Tao tao, TaoType type)
2148: {
2149:   PetscErrorCode (*create_xxx)(Tao);
2150:   PetscBool issame;

2152:   PetscFunctionBegin;

2155:   PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2156:   if (issame) PetscFunctionReturn(PETSC_SUCCESS);

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

2161:   /* Destroy the existing solver information */
2162:   PetscTryTypeMethod(tao, destroy);
2163:   PetscCall(KSPDestroy(&tao->ksp));
2164:   PetscCall(TaoLineSearchDestroy(&tao->linesearch));

2166:   /* Reinitialize type-specific function pointers in TaoOps structure */
2167:   tao->ops->setup          = NULL;
2168:   tao->ops->computedual    = NULL;
2169:   tao->ops->solve          = NULL;
2170:   tao->ops->view           = NULL;
2171:   tao->ops->setfromoptions = NULL;
2172:   tao->ops->destroy        = NULL;

2174:   tao->setupcalled = PETSC_FALSE;

2176:   PetscCall((*create_xxx)(tao));
2177:   PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2178:   PetscFunctionReturn(PETSC_SUCCESS);
2179: }

2181: /*@C
2182:   TaoRegister - Adds a method to the Tao package for minimization.

2184:   Not Collective, No Fortran Support

2186:   Input Parameters:
2187: + sname - name of a new user-defined solver
2188: - func  - routine to Create method context

2190:   Example Usage:
2191: .vb
2192:    TaoRegister("my_solver", MySolverCreate);
2193: .ve

2195:   Then, your solver can be chosen with the procedural interface via
2196: .vb
2197:   TaoSetType(tao, "my_solver")
2198: .ve
2199:   or at runtime via the option
2200: .vb
2201:   -tao_type my_solver
2202: .ve

2204:   Level: advanced

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

2209: .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2210: @*/
2211: PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao))
2212: {
2213:   PetscFunctionBegin;
2214:   PetscCall(TaoInitializePackage());
2215:   PetscCall(PetscFunctionListAdd(&TaoList, sname, func));
2216:   PetscFunctionReturn(PETSC_SUCCESS);
2217: }

2219: /*@C
2220:   TaoRegisterDestroy - Frees the list of minimization solvers that were
2221:   registered by `TaoRegister()`.

2223:   Not Collective

2225:   Level: advanced

2227: .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2228: @*/
2229: PetscErrorCode TaoRegisterDestroy(void)
2230: {
2231:   PetscFunctionBegin;
2232:   PetscCall(PetscFunctionListDestroy(&TaoList));
2233:   TaoRegisterAllCalled = PETSC_FALSE;
2234:   PetscFunctionReturn(PETSC_SUCCESS);
2235: }

2237: /*@
2238:   TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2239:   at this time.

2241:   Not Collective

2243:   Input Parameter:
2244: . tao - the `Tao` context

2246:   Output Parameter:
2247: . iter - iteration number

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

2252:   Level: intermediate

2254: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2255: @*/
2256: PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2257: {
2258:   PetscFunctionBegin;
2260:   PetscAssertPointer(iter, 2);
2261:   *iter = tao->niter;
2262:   PetscFunctionReturn(PETSC_SUCCESS);
2263: }

2265: /*@
2266:   TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2267:   at this time.

2269:   Not Collective

2271:   Input Parameter:
2272: . tao - the `Tao` context

2274:   Output Parameter:
2275: . value - the current value

2277:   Level: intermediate

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

2283: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2284: @*/
2285: PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2286: {
2287:   PetscFunctionBegin;
2289:   PetscAssertPointer(value, 2);
2290:   *value = tao->residual;
2291:   PetscFunctionReturn(PETSC_SUCCESS);
2292: }

2294: /*@
2295:   TaoSetIterationNumber - Sets the current iteration number.

2297:   Logically Collective

2299:   Input Parameters:
2300: + tao  - the `Tao` context
2301: - iter - iteration number

2303:   Level: developer

2305: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2306: @*/
2307: PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2308: {
2309:   PetscFunctionBegin;
2312:   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2313:   tao->niter = iter;
2314:   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2315:   PetscFunctionReturn(PETSC_SUCCESS);
2316: }

2318: /*@
2319:   TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2320:   completed. This number keeps accumulating if multiple solves
2321:   are called with the `Tao` object.

2323:   Not Collective

2325:   Input Parameter:
2326: . tao - the `Tao` context

2328:   Output Parameter:
2329: . iter - number of iterations

2331:   Level: intermediate

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

2337: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2338: @*/
2339: PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2340: {
2341:   PetscFunctionBegin;
2343:   PetscAssertPointer(iter, 2);
2344:   *iter = tao->ntotalits;
2345:   PetscFunctionReturn(PETSC_SUCCESS);
2346: }

2348: /*@
2349:   TaoSetTotalIterationNumber - Sets the current total iteration number.

2351:   Logically Collective

2353:   Input Parameters:
2354: + tao  - the `Tao` context
2355: - iter - the iteration number

2357:   Level: developer

2359: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2360: @*/
2361: PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2362: {
2363:   PetscFunctionBegin;
2366:   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2367:   tao->ntotalits = iter;
2368:   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2369:   PetscFunctionReturn(PETSC_SUCCESS);
2370: }

2372: /*@
2373:   TaoSetConvergedReason - Sets the termination flag on a `Tao` object

2375:   Logically Collective

2377:   Input Parameters:
2378: + tao    - the `Tao` context
2379: - reason - the `TaoConvergedReason`

2381:   Level: intermediate

2383: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2384: @*/
2385: PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2386: {
2387:   PetscFunctionBegin;
2390:   tao->reason = reason;
2391:   PetscFunctionReturn(PETSC_SUCCESS);
2392: }

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

2397:   Not Collective

2399:   Input Parameter:
2400: . tao - the `Tao` solver context

2402:   Output Parameter:
2403: . reason - value of `TaoConvergedReason`

2405:   Level: intermediate

2407: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`
2408: @*/
2409: PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2410: {
2411:   PetscFunctionBegin;
2413:   PetscAssertPointer(reason, 2);
2414:   *reason = tao->reason;
2415:   PetscFunctionReturn(PETSC_SUCCESS);
2416: }

2418: /*@
2419:   TaoGetSolutionStatus - Get the current iterate, objective value,
2420:   residual, infeasibility, and termination from a `Tao` object

2422:   Not Collective

2424:   Input Parameter:
2425: . tao - the `Tao` context

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

2435:   Level: intermediate

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

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

2442: .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2443: @*/
2444: PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2445: {
2446:   PetscFunctionBegin;
2448:   if (its) *its = tao->niter;
2449:   if (f) *f = tao->fc;
2450:   if (gnorm) *gnorm = tao->residual;
2451:   if (cnorm) *cnorm = tao->cnorm;
2452:   if (reason) *reason = tao->reason;
2453:   if (xdiff) *xdiff = tao->step;
2454:   PetscFunctionReturn(PETSC_SUCCESS);
2455: }

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

2460:   Not Collective

2462:   Input Parameter:
2463: . tao - the `Tao` solver context

2465:   Output Parameter:
2466: . type - the `TaoType`

2468:   Level: intermediate

2470: .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`
2471: @*/
2472: PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2473: {
2474:   PetscFunctionBegin;
2476:   PetscAssertPointer(type, 2);
2477:   *type = ((PetscObject)tao)->type_name;
2478:   PetscFunctionReturn(PETSC_SUCCESS);
2479: }

2481: /*@C
2482:   TaoMonitor - Monitor the solver and the current solution.  This
2483:   routine will record the iteration number and residual statistics,
2484:   and call any monitors specified by the user.

2486:   Input Parameters:
2487: + tao        - the `Tao` context
2488: . its        - the current iterate number (>=0)
2489: . f          - the current objective function value
2490: . res        - the gradient norm, square root of the duality gap, or other measure indicating distance from optimality.  This measure will be recorded and
2491:           used for some termination tests.
2492: . cnorm      - the infeasibility of the current solution with regard to the constraints.
2493: - steplength - multiple of the step direction added to the previous iterate.

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

2498:   Level: developer

2500: .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoMonitorSet()`
2501: @*/
2502: PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2503: {
2504:   PetscInt i;

2506:   PetscFunctionBegin;
2508:   tao->fc       = f;
2509:   tao->residual = res;
2510:   tao->cnorm    = cnorm;
2511:   tao->step     = steplength;
2512:   if (!its) {
2513:     tao->cnorm0 = cnorm;
2514:     tao->gnorm0 = res;
2515:   }
2516:   PetscCall(VecLockReadPush(tao->solution));
2517:   for (i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2518:   PetscCall(VecLockReadPop(tao->solution));
2519:   PetscFunctionReturn(PETSC_SUCCESS);
2520: }

2522: /*@
2523:   TaoSetConvergenceHistory - Sets the array used to hold the convergence history.

2525:   Logically Collective

2527:   Input Parameters:
2528: + tao   - the `Tao` solver context
2529: . obj   - array to hold objective value history
2530: . resid - array to hold residual history
2531: . cnorm - array to hold constraint violation history
2532: . lits  - integer array holds the number of linear iterations for each Tao iteration
2533: . na    - size of `obj`, `resid`, and `cnorm`
2534: - reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2535:            else it continues storing new values for new minimizations after the old ones

2537:   Level: intermediate

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

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

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

2552: .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2553: @*/
2554: PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2555: {
2556:   PetscFunctionBegin;
2558:   if (obj) PetscAssertPointer(obj, 2);
2559:   if (resid) PetscAssertPointer(resid, 3);
2560:   if (cnorm) PetscAssertPointer(cnorm, 4);
2561:   if (lits) PetscAssertPointer(lits, 5);

2563:   if (na == PETSC_DECIDE || na == PETSC_CURRENT) na = 1000;
2564:   if (!obj && !resid && !cnorm && !lits) {
2565:     PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2566:     tao->hist_malloc = PETSC_TRUE;
2567:   }

2569:   tao->hist_obj   = obj;
2570:   tao->hist_resid = resid;
2571:   tao->hist_cnorm = cnorm;
2572:   tao->hist_lits  = lits;
2573:   tao->hist_max   = na;
2574:   tao->hist_reset = reset;
2575:   tao->hist_len   = 0;
2576:   PetscFunctionReturn(PETSC_SUCCESS);
2577: }

2579: /*@C
2580:   TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.

2582:   Collective

2584:   Input Parameter:
2585: . tao - the `Tao` context

2587:   Output Parameters:
2588: + obj   - array used to hold objective value history
2589: . resid - array used to hold residual history
2590: . cnorm - array used to hold constraint violation history
2591: . lits  - integer array used to hold linear solver iteration count
2592: - nhist - size of `obj`, `resid`, `cnorm`, and `lits`

2594:   Level: advanced

2596:   Notes:
2597:   This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2598:   and `TaoSolve()`, otherwise it returns useless information.

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

2604:   Fortran Notes:
2605:   The calling sequence is
2606: .vb
2607:    call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2608: .ve
2609:   In other words this gets the current number of entries in the history. Access the history through the array you passed to `TaoSetConvergenceHistory()`

2611: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2612: @*/
2613: PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2614: {
2615:   PetscFunctionBegin;
2617:   if (obj) *obj = tao->hist_obj;
2618:   if (cnorm) *cnorm = tao->hist_cnorm;
2619:   if (resid) *resid = tao->hist_resid;
2620:   if (lits) *lits = tao->hist_lits;
2621:   if (nhist) *nhist = tao->hist_len;
2622:   PetscFunctionReturn(PETSC_SUCCESS);
2623: }

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

2629:   Logically Collective

2631:   Input Parameters:
2632: + tao - the `Tao` context
2633: - ctx - the user context

2635:   Level: intermediate

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

2642: .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`
2643: @*/
2644: PetscErrorCode TaoSetApplicationContext(Tao tao, void *ctx)
2645: {
2646:   PetscFunctionBegin;
2648:   tao->ctx = ctx;
2649:   PetscFunctionReturn(PETSC_SUCCESS);
2650: }

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

2655:   Not Collective

2657:   Input Parameter:
2658: . tao - the `Tao` context

2660:   Output Parameter:
2661: . ctx - a pointer to the user context

2663:   Level: intermediate

2665:   Fortran Notes:
2666:   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
2667:   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
2668: .vb
2669:   Interface TaoGetApplicationContext
2670:     Subroutine TaoGetApplicationContext(tao,ctx,ierr)
2671:   #include <petsc/finclude/petsctao.h>
2672:       use petsctao
2673:       Tao tao
2674:       type(tUsertype), pointer :: ctx
2675:       PetscErrorCode ierr
2676:     End Subroutine
2677:   End Interface TaoGetApplicationContext
2678: .ve

2680:   The prototype for `ctx` must be
2681: .vb
2682:   type(tUsertype), pointer :: ctx
2683: .ve

2685: .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2686: @*/
2687: PetscErrorCode TaoGetApplicationContext(Tao tao, PeCtx ctx)
2688: {
2689:   PetscFunctionBegin;
2691:   PetscAssertPointer(ctx, 2);
2692:   *(void **)ctx = tao->ctx;
2693:   PetscFunctionReturn(PETSC_SUCCESS);
2694: }

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

2699:   Collective

2701:   Input Parameters:
2702: + tao - the `Tao` context
2703: - M   - matrix that defines the norm

2705:   Level: beginner

2707: .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2708: @*/
2709: PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2710: {
2711:   PetscFunctionBegin;
2714:   PetscCall(PetscObjectReference((PetscObject)M));
2715:   PetscCall(MatDestroy(&tao->gradient_norm));
2716:   PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2717:   tao->gradient_norm = M;
2718:   PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2719:   PetscFunctionReturn(PETSC_SUCCESS);
2720: }

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

2725:   Not Collective

2727:   Input Parameter:
2728: . tao - the `Tao` context

2730:   Output Parameter:
2731: . M - gradient norm

2733:   Level: beginner

2735: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2736: @*/
2737: PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2738: {
2739:   PetscFunctionBegin;
2741:   PetscAssertPointer(M, 2);
2742:   *M = tao->gradient_norm;
2743:   PetscFunctionReturn(PETSC_SUCCESS);
2744: }

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

2749:   Collective

2751:   Input Parameters:
2752: + tao      - the `Tao` context
2753: . gradient - the gradient
2754: - type     - the norm type

2756:   Output Parameter:
2757: . gnorm - the gradient norm

2759:   Level: advanced

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

2764:   Developer Notes:
2765:   Should be named `TaoComputeGradientNorm()`.

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

2770: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2771: @*/
2772: PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2773: {
2774:   PetscFunctionBegin;
2778:   PetscAssertPointer(gnorm, 4);
2779:   if (tao->gradient_norm) {
2780:     PetscScalar gnorms;

2782:     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.");
2783:     PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2784:     PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2785:     *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2786:   } else {
2787:     PetscCall(VecNorm(gradient, type, gnorm));
2788:   }
2789:   PetscFunctionReturn(PETSC_SUCCESS);
2790: }

2792: /*@C
2793:   TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorSolutionDraw()`

2795:   Collective

2797:   Input Parameters:
2798: + comm     - the communicator to share the context
2799: . host     - the name of the X Windows host that will display the monitor
2800: . label    - the label to put at the top of the display window
2801: . x        - the horizontal coordinate of the lower left corner of the window to open
2802: . y        - the vertical coordinate of the lower left corner of the window to open
2803: . m        - the width of the window
2804: . n        - the height of the window
2805: - howoften - how many `Tao` iterations between displaying the monitor information

2807:   Output Parameter:
2808: . ctx - the monitor context

2810:   Options Database Keys:
2811: + -tao_monitor_solution_draw - use `TaoMonitorSolutionDraw()` to monitor the solution
2812: - -tao_draw_solution_initial - show initial guess as well as current solution

2814:   Level: intermediate

2816:   Note:
2817:   The context this creates, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
2818:   are passed to `TaoMonitorSet()`.

2820: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2821: @*/
2822: PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2823: {
2824:   PetscFunctionBegin;
2825:   PetscCall(PetscNew(ctx));
2826:   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
2827:   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
2828:   (*ctx)->howoften = howoften;
2829:   PetscFunctionReturn(PETSC_SUCCESS);
2830: }

2832: /*@C
2833:   TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorSolutionDraw()`

2835:   Collective

2837:   Input Parameter:
2838: . ictx - the monitor context

2840:   Level: intermediate

2842:   Note:
2843:   This is passed to `TaoMonitorSet()` as the final argument, along with `TaoMonitorSolutionDraw()`, and the context
2844:   obtained with `TaoMonitorDrawCtxCreate()`.

2846: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorSolutionDraw()`
2847: @*/
2848: PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2849: {
2850:   PetscFunctionBegin;
2851:   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
2852:   PetscCall(PetscFree(*ictx));
2853:   PetscFunctionReturn(PETSC_SUCCESS);
2854: }