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:   TaoCreate - Creates a Tao solver

 75:   Collective

 77:   Input Parameter:
 78: . comm - MPI communicator

 80:   Output Parameter:
 81: . newtao - the new `Tao` context

 83:   Options Database Key:
 84: . -tao_type - select which method Tao should use

 86:   Level: beginner

 88: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoDestroy()`, `TAOSetFromOptions()`, `TAOSetType()`
 89: @*/
 90: PetscErrorCode TaoCreate(MPI_Comm comm, Tao *newtao)
 91: {
 92:   Tao tao;

 94:   PetscFunctionBegin;
 95:   PetscAssertPointer(newtao, 2);
 96:   PetscCall(TaoInitializePackage());

 98:   PetscCall(TaoLineSearchInitializePackage());
 99:   PetscCall(PetscHeaderCreate(tao, TAO_CLASSID, "Tao", "Optimization solver", "Tao", comm, TaoDestroy, TaoView));

101:   /* Set non-NULL defaults */
102:   tao->ops->convergencetest = TaoDefaultConvergenceTest;
103:   tao->max_it               = 10000;
104:   tao->max_funcs            = -1;
105: #if defined(PETSC_USE_REAL_SINGLE)
106:   tao->gatol = 1e-5;
107:   tao->grtol = 1e-5;
108:   tao->crtol = 1e-5;
109:   tao->catol = 1e-5;
110: #else
111:   tao->gatol = 1e-8;
112:   tao->grtol = 1e-8;
113:   tao->crtol = 1e-8;
114:   tao->catol = 1e-8;
115: #endif
116:   tao->gttol      = 0.0;
117:   tao->steptol    = 0.0;
118:   tao->trust0     = PETSC_INFINITY;
119:   tao->fmin       = PETSC_NINFINITY;
120:   tao->hist_reset = PETSC_TRUE;
121:   PetscCall(TaoResetStatistics(tao));
122:   *newtao = tao;
123:   PetscFunctionReturn(PETSC_SUCCESS);
124: }

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

129:   Collective

131:   Input Parameter:
132: . tao - the `Tao` context

134:   Level: beginner

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

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

142: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoGetConvergedReason()`, `TaoSetUp()`
143:  @*/
144: PetscErrorCode TaoSolve(Tao tao)
145: {
146:   static PetscBool set = PETSC_FALSE;

148:   PetscFunctionBegin;
150:   PetscCall(PetscCitationsRegister("@TechReport{tao-user-ref,\n"
151:                                    "title   = {Toolkit for Advanced Optimization (TAO) Users Manual},\n"
152:                                    "author  = {Todd Munson and Jason Sarich and Stefan Wild and Steve Benson and Lois Curfman McInnes},\n"
153:                                    "Institution = {Argonne National Laboratory},\n"
154:                                    "Year   = 2014,\n"
155:                                    "Number = {ANL/MCS-TM-322 - Revision 3.5},\n"
156:                                    "url    = {https://www.mcs.anl.gov/research/projects/tao/}\n}\n",
157:                                    &set));
158:   tao->header_printed = PETSC_FALSE;
159:   PetscCall(TaoSetUp(tao));
160:   PetscCall(TaoResetStatistics(tao));
161:   if (tao->linesearch) PetscCall(TaoLineSearchReset(tao->linesearch));

163:   PetscCall(PetscLogEventBegin(TAO_Solve, tao, 0, 0, 0));
164:   PetscTryTypeMethod(tao, solve);
165:   PetscCall(PetscLogEventEnd(TAO_Solve, tao, 0, 0, 0));

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

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

171:   if (tao->printreason) {
172:     PetscViewer viewer = PETSC_VIEWER_STDOUT_(((PetscObject)tao)->comm);
173:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)tao)->tablevel));
174:     if (tao->reason > 0) {
175:       PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix ? ((PetscObject)tao)->prefix : "", TaoConvergedReasons[tao->reason], tao->niter));
176:     } else {
177:       PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO %s solve did not converge due to %s iteration %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix ? ((PetscObject)tao)->prefix : "", TaoConvergedReasons[tao->reason], tao->niter));
178:     }
179:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)tao)->tablevel));
180:   }
181:   PetscCall(TaoViewFromOptions(tao, NULL, "-tao_view"));
182:   PetscFunctionReturn(PETSC_SUCCESS);
183: }

185: /*@
186:   TaoSetUp - Sets up the internal data structures for the later use
187:   of a Tao solver

189:   Collective

191:   Input Parameter:
192: . tao - the `Tao` context

194:   Level: advanced

196:   Note:
197:   The user will not need to explicitly call `TaoSetUp()`, as it will
198:   automatically be called in `TaoSolve()`.  However, if the user
199:   desires to call it explicitly, it should come after `TaoCreate()`
200:   and any TaoSetSomething() routines, but before `TaoSolve()`.

202: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
203: @*/
204: PetscErrorCode TaoSetUp(Tao tao)
205: {
206:   PetscFunctionBegin;
208:   if (tao->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
209:   PetscCall(TaoSetUpEW_Private(tao));
210:   PetscCheck(tao->solution, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Must call TaoSetSolution");
211:   PetscTryTypeMethod(tao, setup);
212:   tao->setupcalled = PETSC_TRUE;
213:   PetscFunctionReturn(PETSC_SUCCESS);
214: }

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

219:   Collective

221:   Input Parameter:
222: . tao - the `Tao` context

224:   Level: beginner

226: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
227: @*/
228: PetscErrorCode TaoDestroy(Tao *tao)
229: {
230:   PetscFunctionBegin;
231:   if (!*tao) PetscFunctionReturn(PETSC_SUCCESS);
233:   if (--((PetscObject)*tao)->refct > 0) {
234:     *tao = NULL;
235:     PetscFunctionReturn(PETSC_SUCCESS);
236:   }

238:   PetscTryTypeMethod(*tao, destroy);
239:   PetscCall(KSPDestroy(&(*tao)->ksp));
240:   PetscCall(SNESDestroy(&(*tao)->snes_ewdummy));
241:   PetscCall(TaoLineSearchDestroy(&(*tao)->linesearch));

243:   if ((*tao)->ops->convergencedestroy) {
244:     PetscCall((*(*tao)->ops->convergencedestroy)((*tao)->cnvP));
245:     if ((*tao)->jacobian_state_inv) PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
246:   }
247:   PetscCall(VecDestroy(&(*tao)->solution));
248:   PetscCall(VecDestroy(&(*tao)->gradient));
249:   PetscCall(VecDestroy(&(*tao)->ls_res));

251:   if ((*tao)->gradient_norm) {
252:     PetscCall(PetscObjectDereference((PetscObject)(*tao)->gradient_norm));
253:     PetscCall(VecDestroy(&(*tao)->gradient_norm_tmp));
254:   }

256:   PetscCall(VecDestroy(&(*tao)->XL));
257:   PetscCall(VecDestroy(&(*tao)->XU));
258:   PetscCall(VecDestroy(&(*tao)->IL));
259:   PetscCall(VecDestroy(&(*tao)->IU));
260:   PetscCall(VecDestroy(&(*tao)->DE));
261:   PetscCall(VecDestroy(&(*tao)->DI));
262:   PetscCall(VecDestroy(&(*tao)->constraints));
263:   PetscCall(VecDestroy(&(*tao)->constraints_equality));
264:   PetscCall(VecDestroy(&(*tao)->constraints_inequality));
265:   PetscCall(VecDestroy(&(*tao)->stepdirection));
266:   PetscCall(MatDestroy(&(*tao)->hessian_pre));
267:   PetscCall(MatDestroy(&(*tao)->hessian));
268:   PetscCall(MatDestroy(&(*tao)->ls_jac));
269:   PetscCall(MatDestroy(&(*tao)->ls_jac_pre));
270:   PetscCall(MatDestroy(&(*tao)->jacobian_pre));
271:   PetscCall(MatDestroy(&(*tao)->jacobian));
272:   PetscCall(MatDestroy(&(*tao)->jacobian_state_pre));
273:   PetscCall(MatDestroy(&(*tao)->jacobian_state));
274:   PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
275:   PetscCall(MatDestroy(&(*tao)->jacobian_design));
276:   PetscCall(MatDestroy(&(*tao)->jacobian_equality));
277:   PetscCall(MatDestroy(&(*tao)->jacobian_equality_pre));
278:   PetscCall(MatDestroy(&(*tao)->jacobian_inequality));
279:   PetscCall(MatDestroy(&(*tao)->jacobian_inequality_pre));
280:   PetscCall(ISDestroy(&(*tao)->state_is));
281:   PetscCall(ISDestroy(&(*tao)->design_is));
282:   PetscCall(VecDestroy(&(*tao)->res_weights_v));
283:   PetscCall(TaoMonitorCancel(*tao));
284:   if ((*tao)->hist_malloc) PetscCall(PetscFree4((*tao)->hist_obj, (*tao)->hist_resid, (*tao)->hist_cnorm, (*tao)->hist_lits));
285:   if ((*tao)->res_weights_n) {
286:     PetscCall(PetscFree((*tao)->res_weights_rows));
287:     PetscCall(PetscFree((*tao)->res_weights_cols));
288:     PetscCall(PetscFree((*tao)->res_weights_w));
289:   }
290:   PetscCall(PetscHeaderDestroy(tao));
291:   PetscFunctionReturn(PETSC_SUCCESS);
292: }

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

297:   Logically Collective

299:   Input Parameters:
300: + tao  - Tao context
301: - flag - `PETSC_TRUE` or `PETSC_FALSE`

303:   Level: advanced

305:   Note:
306:   See `SNESKSPSetUseEW()` for customization details.

308: .seealso: [](ch_tao), `Tao`, `SNESKSPSetUseEW()`
309: @*/
310: PetscErrorCode TaoKSPSetUseEW(Tao tao, PetscBool flag)
311: {
312:   PetscFunctionBegin;
315:   tao->ksp_ewconv = flag;
316:   PetscFunctionReturn(PETSC_SUCCESS);
317: }

319: /*@
320:   TaoSetFromOptions - Sets various Tao parameters from the options database

322:   Collective

324:   Input Parameter:
325: . tao - the `Tao` solver context

327:   Options Database Keys:
328: + -tao_type <type>             - The algorithm that Tao uses (lmvm, nls, etc.)
329: . -tao_gatol <gatol>           - absolute error tolerance for ||gradient||
330: . -tao_grtol <grtol>           - relative error tolerance for ||gradient||
331: . -tao_gttol <gttol>           - reduction of ||gradient|| relative to initial gradient
332: . -tao_max_it <max>            - sets maximum number of iterations
333: . -tao_max_funcs <max>         - sets maximum number of function evaluations
334: . -tao_fmin <fmin>             - stop if function value reaches fmin
335: . -tao_steptol <tol>           - stop if trust region radius less than <tol>
336: . -tao_trust0 <t>              - initial trust region radius
337: . -tao_view_solution           - view the solution at the end of the optimization process
338: . -tao_monitor                 - prints function value and residual norm at each iteration
339: . -tao_monitor_short           - same as `-tao_monitor`, but truncates very small values
340: . -tao_monitor_constraint_norm - prints objective value, gradient, and constraint norm at each iteration
341: . -tao_monitor_globalization   - prints information about the globalization at each iteration
342: . -tao_monitor_solution        - prints solution vector at each iteration
343: . -tao_monitor_ls_residual     - prints least-squares residual vector at each iteration
344: . -tao_monitor_step            - prints step vector at each iteration
345: . -tao_monitor_gradient        - prints gradient vector at each iteration
346: . -tao_monitor_solution_draw   - graphically view solution vector at each iteration
347: . -tao_monitor_step_draw       - graphically view step vector at each iteration
348: . -tao_monitor_gradient_draw   - graphically view gradient at each iteration
349: . -tao_monitor_cancel          - cancels all monitors (except those set with command line)
350: . -tao_fd_gradient             - use gradient computed with finite differences
351: . -tao_fd_hessian              - use hessian computed with finite differences
352: . -tao_mf_hessian              - use matrix-free Hessian computed with finite differences
353: . -tao_view                    - prints information about the Tao after solving
354: - -tao_converged_reason        - prints the reason Tao stopped iterating

356:   Level: beginner

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

362: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
363: @*/
364: PetscErrorCode TaoSetFromOptions(Tao tao)
365: {
366:   TaoType     default_type = TAOLMVM;
367:   char        type[256], monfilename[PETSC_MAX_PATH_LEN];
368:   PetscViewer monviewer;
369:   PetscBool   flg, found;
370:   MPI_Comm    comm;

372:   PetscFunctionBegin;
374:   PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));

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

378:   PetscObjectOptionsBegin((PetscObject)tao);
379:   /* Check for type from options */
380:   PetscCall(PetscOptionsFList("-tao_type", "Tao Solver type", "TaoSetType", TaoList, default_type, type, 256, &flg));
381:   if (flg) {
382:     PetscCall(TaoSetType(tao, type));
383:   } else if (!((PetscObject)tao)->type_name) {
384:     PetscCall(TaoSetType(tao, default_type));
385:   }

387:   /* Tao solvers do not set the prefix, set it here if not yet done
388:      We do it after SetType since solver may have been changed */
389:   if (tao->linesearch) {
390:     const char *prefix;
391:     PetscCall(TaoLineSearchGetOptionsPrefix(tao->linesearch, &prefix));
392:     if (!prefix) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, ((PetscObject)tao)->prefix));
393:   }

395:   PetscCall(PetscOptionsReal("-tao_catol", "Stop if constraints violations within", "TaoSetConstraintTolerances", tao->catol, &tao->catol, &flg));
396:   if (flg) tao->catol_changed = PETSC_TRUE;
397:   PetscCall(PetscOptionsReal("-tao_crtol", "Stop if relative constraint violations within", "TaoSetConstraintTolerances", tao->crtol, &tao->crtol, &flg));
398:   if (flg) tao->crtol_changed = PETSC_TRUE;
399:   PetscCall(PetscOptionsReal("-tao_gatol", "Stop if norm of gradient less than", "TaoSetTolerances", tao->gatol, &tao->gatol, &flg));
400:   if (flg) tao->gatol_changed = PETSC_TRUE;
401:   PetscCall(PetscOptionsReal("-tao_grtol", "Stop if norm of gradient divided by the function value is less than", "TaoSetTolerances", tao->grtol, &tao->grtol, &flg));
402:   if (flg) tao->grtol_changed = PETSC_TRUE;
403:   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, &tao->gttol, &flg));
404:   if (flg) tao->gttol_changed = PETSC_TRUE;
405:   PetscCall(PetscOptionsInt("-tao_max_it", "Stop if iteration number exceeds", "TaoSetMaximumIterations", tao->max_it, &tao->max_it, &flg));
406:   if (flg) tao->max_it_changed = PETSC_TRUE;
407:   PetscCall(PetscOptionsInt("-tao_max_funcs", "Stop if number of function evaluations exceeds", "TaoSetMaximumFunctionEvaluations", tao->max_funcs, &tao->max_funcs, &flg));
408:   if (flg) tao->max_funcs_changed = PETSC_TRUE;
409:   PetscCall(PetscOptionsReal("-tao_fmin", "Stop if function less than", "TaoSetFunctionLowerBound", tao->fmin, &tao->fmin, &flg));
410:   if (flg) tao->fmin_changed = PETSC_TRUE;
411:   PetscCall(PetscOptionsReal("-tao_steptol", "Stop if step size or trust region radius less than", "", tao->steptol, &tao->steptol, &flg));
412:   if (flg) tao->steptol_changed = PETSC_TRUE;
413:   PetscCall(PetscOptionsReal("-tao_trust0", "Initial trust region radius", "TaoSetTrustRegionRadius", tao->trust0, &tao->trust0, &flg));
414:   if (flg) tao->trust0_changed = PETSC_TRUE;

416:   PetscCall(PetscOptionsDeprecated("-tao_solution_monitor", "-tao_monitor_solution", "3.21", NULL));
417:   PetscCall(PetscOptionsDeprecated("-tao_gradient_monitor", "-tao_monitor_gradient", "3.21", NULL));
418:   PetscCall(PetscOptionsDeprecated("-tao_stepdirection_monitor", "-tao_monitor_step", "3.21", NULL));
419:   PetscCall(PetscOptionsDeprecated("-tao_residual_monitor", "-tao_monitor_residual", "3.21", NULL));
420:   PetscCall(PetscOptionsDeprecated("-tao_smonitor", "-tao_monitor_short", "3.21", NULL));
421:   PetscCall(PetscOptionsDeprecated("-tao_cmonitor", "-tao_monitor_constraint_norm", "3.21", NULL));
422:   PetscCall(PetscOptionsDeprecated("-tao_gmonitor", "-tao_monitor_globalization", "3.21", NULL));
423:   PetscCall(PetscOptionsDeprecated("-tao_draw_solution", "-tao_monitor_solution_draw", "3.21", NULL));
424:   PetscCall(PetscOptionsDeprecated("-tao_draw_gradient", "-tao_monitor_gradient_draw", "3.21", NULL));
425:   PetscCall(PetscOptionsDeprecated("-tao_draw_step", "-tao_monitor_step_draw", "3.21", NULL));

427:   PetscCall(PetscOptionsString("-tao_monitor_solution", "View solution vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
428:   if (flg) {
429:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
430:     PetscCall(TaoMonitorSet(tao, TaoMonitorSolution, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
431:   }

433:   PetscCall(PetscOptionsBool("-tao_converged_reason", "Print reason for Tao converged", "TaoSolve", tao->printreason, &tao->printreason, NULL));
434:   PetscCall(PetscOptionsString("-tao_monitor_gradient", "View gradient vector for each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
435:   if (flg) {
436:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
437:     PetscCall(TaoMonitorSet(tao, TaoMonitorGradient, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
438:   }

440:   PetscCall(PetscOptionsString("-tao_monitor_step", "View step vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
441:   if (flg) {
442:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
443:     PetscCall(TaoMonitorSet(tao, TaoMonitorStep, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
444:   }

446:   PetscCall(PetscOptionsString("-tao_monitor_residual", "View least-squares residual vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
447:   if (flg) {
448:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
449:     PetscCall(TaoMonitorSet(tao, TaoMonitorResidual, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
450:   }

452:   PetscCall(PetscOptionsString("-tao_monitor", "Use the default convergence monitor", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
453:   if (flg) {
454:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
455:     PetscCall(TaoMonitorSet(tao, TaoMonitorDefault, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
456:   }

458:   PetscCall(PetscOptionsString("-tao_monitor_globalization", "Use the convergence monitor with extra globalization info", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
459:   if (flg) {
460:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
461:     PetscCall(TaoMonitorSet(tao, TaoMonitorGlobalization, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
462:   }

464:   PetscCall(PetscOptionsString("-tao_monitor_short", "Use the short convergence monitor", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
465:   if (flg) {
466:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
467:     PetscCall(TaoMonitorSet(tao, TaoMonitorDefaultShort, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
468:   }

470:   PetscCall(PetscOptionsString("-tao_monitor_constraint_norm", "Use the default convergence monitor with constraint norm", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
471:   if (flg) {
472:     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
473:     PetscCall(TaoMonitorSet(tao, TaoMonitorConstraintNorm, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
474:   }

476:   flg = PETSC_FALSE;
477:   PetscCall(PetscOptionsDeprecated("-tao_cancelmonitors", "-tao_monitor_cancel", "3.21", NULL));
478:   PetscCall(PetscOptionsBool("-tao_monitor_cancel", "cancel all monitors and call any registered destroy routines", "TaoMonitorCancel", flg, &flg, NULL));
479:   if (flg) PetscCall(TaoMonitorCancel(tao));

481:   flg = PETSC_FALSE;
482:   PetscCall(PetscOptionsBool("-tao_monitor_solution_draw", "Plot solution vector at each iteration", "TaoMonitorSet", flg, &flg, NULL));
483:   if (flg) {
484:     TaoMonitorDrawCtx drawctx;
485:     PetscInt          howoften = 1;
486:     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
487:     PetscCall(TaoMonitorSet(tao, TaoMonitorSolutionDraw, drawctx, (PetscErrorCode(*)(void **))TaoMonitorDrawCtxDestroy));
488:   }

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

494:   flg = PETSC_FALSE;
495:   PetscCall(PetscOptionsBool("-tao_monitor_gradient_draw", "plots gradient at each iteration", "TaoMonitorSet", flg, &flg, NULL));
496:   if (flg) {
497:     TaoMonitorDrawCtx drawctx;
498:     PetscInt          howoften = 1;
499:     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
500:     PetscCall(TaoMonitorSet(tao, TaoMonitorGradientDraw, drawctx, (PetscErrorCode(*)(void **))TaoMonitorDrawCtxDestroy));
501:   }
502:   flg = PETSC_FALSE;
503:   PetscCall(PetscOptionsBool("-tao_fd_gradient", "compute gradient using finite differences", "TaoDefaultComputeGradient", flg, &flg, NULL));
504:   if (flg) PetscCall(TaoSetGradient(tao, NULL, TaoDefaultComputeGradient, NULL));
505:   flg = PETSC_FALSE;
506:   PetscCall(PetscOptionsBool("-tao_fd_hessian", "compute Hessian using finite differences", "TaoDefaultComputeHessian", flg, &flg, NULL));
507:   if (flg) {
508:     Mat H;

510:     PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
511:     PetscCall(MatSetType(H, MATAIJ));
512:     PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessian, NULL));
513:     PetscCall(MatDestroy(&H));
514:   }
515:   flg = PETSC_FALSE;
516:   PetscCall(PetscOptionsBool("-tao_mf_hessian", "compute matrix-free Hessian using finite differences", "TaoDefaultComputeHessianMFFD", flg, &flg, NULL));
517:   if (flg) {
518:     Mat H;

520:     PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
521:     PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessianMFFD, NULL));
522:     PetscCall(MatDestroy(&H));
523:   }
524:   PetscCall(PetscOptionsBool("-tao_recycle_history", "enable recycling/re-using information from the previous TaoSolve() call for some algorithms", "TaoSetRecycleHistory", flg, &flg, &found));
525:   if (found) PetscCall(TaoSetRecycleHistory(tao, flg));
526:   PetscCall(PetscOptionsEnum("-tao_subset_type", "subset type", "", TaoSubSetTypes, (PetscEnum)tao->subset_type, (PetscEnum *)&tao->subset_type, NULL));

528:   if (tao->ksp) {
529:     PetscCall(PetscOptionsBool("-tao_ksp_ew", "Use Eisentat-Walker linear system convergence test", "TaoKSPSetUseEW", tao->ksp_ewconv, &tao->ksp_ewconv, NULL));
530:     PetscCall(TaoKSPSetUseEW(tao, tao->ksp_ewconv));
531:   }

533:   PetscTryTypeMethod(tao, setfromoptions, PetscOptionsObject);

535:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
536:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)tao, PetscOptionsObject));
537:   PetscOptionsEnd();

539:   if (tao->linesearch) PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
540:   PetscFunctionReturn(PETSC_SUCCESS);
541: }

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

546:   Collective

548:   Input Parameters:
549: + A    - the  `Tao` context
550: . obj  - Optional object that provides the prefix for the options database
551: - name - command line option

553:   Level: intermediate

555: .seealso: [](ch_tao), `Tao`, `TaoView`, `PetscObjectViewFromOptions()`, `TaoCreate()`
556: @*/
557: PetscErrorCode TaoViewFromOptions(Tao A, PetscObject obj, const char name[])
558: {
559:   PetscFunctionBegin;
561:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
562:   PetscFunctionReturn(PETSC_SUCCESS);
563: }

565: /*@
566:   TaoView - Prints information about the `Tao` object

568:   Collective

570:   Input Parameters:
571: + tao    - the `Tao` context
572: - viewer - visualization context

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

577:   Level: beginner

579:   Notes:
580:   The available visualization contexts include
581: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
582: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
583:   output where only the first processor opens
584:   the file.  All other processors send their
585:   data to the first processor to print.

587: .seealso: [](ch_tao), `Tao`, `PetscViewerASCIIOpen()`
588: @*/
589: PetscErrorCode TaoView(Tao tao, PetscViewer viewer)
590: {
591:   PetscBool isascii, isstring;
592:   TaoType   type;

594:   PetscFunctionBegin;
596:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)tao)->comm, &viewer));
598:   PetscCheckSameComm(tao, 1, viewer, 2);

600:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
601:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
602:   if (isascii) {
603:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)tao, viewer));

605:     if (tao->ops->view) {
606:       PetscCall(PetscViewerASCIIPushTab(viewer));
607:       PetscUseTypeMethod(tao, view, viewer);
608:       PetscCall(PetscViewerASCIIPopTab(viewer));
609:     }
610:     if (tao->linesearch) {
611:       PetscCall(PetscViewerASCIIPushTab(viewer));
612:       PetscCall(TaoLineSearchView(tao->linesearch, viewer));
613:       PetscCall(PetscViewerASCIIPopTab(viewer));
614:     }
615:     if (tao->ksp) {
616:       PetscCall(PetscViewerASCIIPushTab(viewer));
617:       PetscCall(KSPView(tao->ksp, viewer));
618:       PetscCall(PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", tao->ksp_tot_its));
619:       PetscCall(PetscViewerASCIIPopTab(viewer));
620:     }

622:     PetscCall(PetscViewerASCIIPushTab(viewer));

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

626:     PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: gatol=%g,", (double)tao->gatol));
627:     PetscCall(PetscViewerASCIIPrintf(viewer, " steptol=%g,", (double)tao->steptol));
628:     PetscCall(PetscViewerASCIIPrintf(viewer, " gttol=%g\n", (double)tao->gttol));
629:     PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Function/Gradient:=%g\n", (double)tao->residual));

631:     if (tao->constrained) {
632:       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances:"));
633:       PetscCall(PetscViewerASCIIPrintf(viewer, " catol=%g,", (double)tao->catol));
634:       PetscCall(PetscViewerASCIIPrintf(viewer, " crtol=%g\n", (double)tao->crtol));
635:       PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Constraints:=%g\n", (double)tao->cnorm));
636:     }

638:     if (tao->trust < tao->steptol) {
639:       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: steptol=%g\n", (double)tao->steptol));
640:       PetscCall(PetscViewerASCIIPrintf(viewer, "Final trust region radius:=%g\n", (double)tao->trust));
641:     }

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

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

649:     if (tao->nfuncs > 0) {
650:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT ",", tao->nfuncs));
651:       PetscCall(PetscViewerASCIIPrintf(viewer, "                max: %" PetscInt_FMT "\n", tao->max_funcs));
652:     }
653:     if (tao->ngrads > 0) {
654:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT ",", tao->ngrads));
655:       PetscCall(PetscViewerASCIIPrintf(viewer, "                max: %" PetscInt_FMT "\n", tao->max_funcs));
656:     }
657:     if (tao->nfuncgrads > 0) {
658:       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT ",", tao->nfuncgrads));
659:       PetscCall(PetscViewerASCIIPrintf(viewer, "    (max: %" PetscInt_FMT ")\n", tao->max_funcs));
660:     }
661:     if (tao->nhess > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", tao->nhess));
662:     if (tao->nconstraints > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of constraint function evaluations=%" PetscInt_FMT "\n", tao->nconstraints));
663:     if (tao->njac > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Jacobian evaluations=%" PetscInt_FMT "\n", tao->njac));

665:     if (tao->reason > 0) {
666:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solution converged: "));
667:       switch (tao->reason) {
668:       case TAO_CONVERGED_GATOL:
669:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)|| <= gatol\n"));
670:         break;
671:       case TAO_CONVERGED_GRTOL:
672:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/|f(X)| <= grtol\n"));
673:         break;
674:       case TAO_CONVERGED_GTTOL:
675:         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/||g(X0)|| <= gttol\n"));
676:         break;
677:       case TAO_CONVERGED_STEPTOL:
678:         PetscCall(PetscViewerASCIIPrintf(viewer, " Steptol -- step size small\n"));
679:         break;
680:       case TAO_CONVERGED_MINF:
681:         PetscCall(PetscViewerASCIIPrintf(viewer, " Minf --  f < fmin\n"));
682:         break;
683:       case TAO_CONVERGED_USER:
684:         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
685:         break;
686:       default:
687:         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
688:         break;
689:       }
690:     } else {
691:       PetscCall(PetscViewerASCIIPrintf(viewer, "Solver terminated: %d", tao->reason));
692:       switch (tao->reason) {
693:       case TAO_DIVERGED_MAXITS:
694:         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Iterations\n"));
695:         break;
696:       case TAO_DIVERGED_NAN:
697:         PetscCall(PetscViewerASCIIPrintf(viewer, " NAN or Inf encountered\n"));
698:         break;
699:       case TAO_DIVERGED_MAXFCN:
700:         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Function Evaluations\n"));
701:         break;
702:       case TAO_DIVERGED_LS_FAILURE:
703:         PetscCall(PetscViewerASCIIPrintf(viewer, " Line Search Failure\n"));
704:         break;
705:       case TAO_DIVERGED_TR_REDUCTION:
706:         PetscCall(PetscViewerASCIIPrintf(viewer, " Trust Region too small\n"));
707:         break;
708:       case TAO_DIVERGED_USER:
709:         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
710:         break;
711:       default:
712:         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
713:         break;
714:       }
715:     }
716:     PetscCall(PetscViewerASCIIPopTab(viewer));
717:   } else if (isstring) {
718:     PetscCall(TaoGetType(tao, &type));
719:     PetscCall(PetscViewerStringSPrintf(viewer, " %-3.3s", type));
720:   }
721:   PetscFunctionReturn(PETSC_SUCCESS);
722: }

724: /*@
725:   TaoSetRecycleHistory - Sets the boolean flag to enable/disable re-using
726:   iterate information from the previous `TaoSolve()`. This feature is disabled by
727:   default.

729:   Logically Collective

731:   Input Parameters:
732: + tao     - the `Tao` context
733: - recycle - boolean flag

735:   Options Database Key:
736: . -tao_recycle_history <true,false> - reuse the history

738:   Level: intermediate

740:   Notes:
741:   For conjugate gradient methods (`TAOBNCG`), this re-uses the latest search direction
742:   from the previous `TaoSolve()` call when computing the first search direction in a
743:   new solution. By default, CG methods set the first search direction to the
744:   negative gradient.

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

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

753: .seealso: [](ch_tao), `Tao`, `TaoGetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
754: @*/
755: PetscErrorCode TaoSetRecycleHistory(Tao tao, PetscBool recycle)
756: {
757:   PetscFunctionBegin;
760:   tao->recycle = recycle;
761:   PetscFunctionReturn(PETSC_SUCCESS);
762: }

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

768:   Logically Collective

770:   Input Parameter:
771: . tao - the `Tao` context

773:   Output Parameter:
774: . recycle - boolean flag

776:   Level: intermediate

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

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

792:   Logically Collective

794:   Input Parameters:
795: + tao   - the `Tao` context
796: . gatol - stop if norm of gradient is less than this
797: . grtol - stop if relative norm of gradient is less than this
798: - gttol - stop if norm of gradient is reduced by this factor

800:   Options Database Keys:
801: + -tao_gatol <gatol> - Sets gatol
802: . -tao_grtol <grtol> - Sets grtol
803: - -tao_gttol <gttol> - Sets gttol

805:   Stopping Criteria\:
806: .vb
807:   ||g(X)||                            <= gatol
808:   ||g(X)|| / |f(X)|                   <= grtol
809:   ||g(X)|| / ||g(X0)||                <= gttol
810: .ve

812:   Level: beginner

814:   Note:
815:   Use `PETSC_DEFAULT` to leave one or more tolerances unchanged.

817: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`
818: @*/
819: PetscErrorCode TaoSetTolerances(Tao tao, PetscReal gatol, PetscReal grtol, PetscReal gttol)
820: {
821:   PetscFunctionBegin;

827:   if (gatol != (PetscReal)PETSC_DEFAULT) {
828:     if (gatol < 0) {
829:       PetscCall(PetscInfo(tao, "Tried to set negative gatol -- ignored.\n"));
830:     } else {
831:       tao->gatol         = PetscMax(0, gatol);
832:       tao->gatol_changed = PETSC_TRUE;
833:     }
834:   }

836:   if (grtol != (PetscReal)PETSC_DEFAULT) {
837:     if (grtol < 0) {
838:       PetscCall(PetscInfo(tao, "Tried to set negative grtol -- ignored.\n"));
839:     } else {
840:       tao->grtol         = PetscMax(0, grtol);
841:       tao->grtol_changed = PETSC_TRUE;
842:     }
843:   }

845:   if (gttol != (PetscReal)PETSC_DEFAULT) {
846:     if (gttol < 0) {
847:       PetscCall(PetscInfo(tao, "Tried to set negative gttol -- ignored.\n"));
848:     } else {
849:       tao->gttol         = PetscMax(0, gttol);
850:       tao->gttol_changed = PETSC_TRUE;
851:     }
852:   }
853:   PetscFunctionReturn(PETSC_SUCCESS);
854: }

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

859:   Logically Collective

861:   Input Parameters:
862: + tao   - the `Tao` context
863: . catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for gatol convergence criteria
864: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for gatol, gttol convergence criteria

866:   Options Database Keys:
867: + -tao_catol <catol> - Sets catol
868: - -tao_crtol <crtol> - Sets crtol

870:   Level: intermediate

872:   Notes:
873:   Use `PETSC_DEFAULT` to leave any tolerance unchanged.

875: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoGetConstraintTolerances()`, `TaoSetTolerances()`
876: @*/
877: PetscErrorCode TaoSetConstraintTolerances(Tao tao, PetscReal catol, PetscReal crtol)
878: {
879:   PetscFunctionBegin;

884:   if (catol != (PetscReal)PETSC_DEFAULT) {
885:     if (catol < 0) {
886:       PetscCall(PetscInfo(tao, "Tried to set negative catol -- ignored.\n"));
887:     } else {
888:       tao->catol         = PetscMax(0, catol);
889:       tao->catol_changed = PETSC_TRUE;
890:     }
891:   }

893:   if (crtol != (PetscReal)PETSC_DEFAULT) {
894:     if (crtol < 0) {
895:       PetscCall(PetscInfo(tao, "Tried to set negative crtol -- ignored.\n"));
896:     } else {
897:       tao->crtol         = PetscMax(0, crtol);
898:       tao->crtol_changed = PETSC_TRUE;
899:     }
900:   }
901:   PetscFunctionReturn(PETSC_SUCCESS);
902: }

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

907:   Not Collective

909:   Input Parameter:
910: . tao - the `Tao` context

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

916:   Level: intermediate

918: .seealso: [](ch_tao), `Tao`, `TaoConvergedReasons`,`TaoGetTolerances()`, `TaoSetTolerances()`, `TaoSetConstraintTolerances()`
919: @*/
920: PetscErrorCode TaoGetConstraintTolerances(Tao tao, PetscReal *catol, PetscReal *crtol)
921: {
922:   PetscFunctionBegin;
924:   if (catol) *catol = tao->catol;
925:   if (crtol) *crtol = tao->crtol;
926:   PetscFunctionReturn(PETSC_SUCCESS);
927: }

929: /*@
930:   TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
931:   When an approximate solution with an objective value below this number
932:   has been found, the solver will terminate.

934:   Logically Collective

936:   Input Parameters:
937: + tao  - the Tao solver context
938: - fmin - the tolerance

940:   Options Database Key:
941: . -tao_fmin <fmin> - sets the minimum function value

943:   Level: intermediate

945: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetTolerances()`
946: @*/
947: PetscErrorCode TaoSetFunctionLowerBound(Tao tao, PetscReal fmin)
948: {
949:   PetscFunctionBegin;
952:   tao->fmin         = fmin;
953:   tao->fmin_changed = PETSC_TRUE;
954:   PetscFunctionReturn(PETSC_SUCCESS);
955: }

957: /*@
958:   TaoGetFunctionLowerBound - Gets the bound on the solution objective value.
959:   When an approximate solution with an objective value below this number
960:   has been found, the solver will terminate.

962:   Not Collective

964:   Input Parameter:
965: . tao - the `Tao` solver context

967:   Output Parameter:
968: . fmin - the minimum function value

970:   Level: intermediate

972: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetFunctionLowerBound()`
973: @*/
974: PetscErrorCode TaoGetFunctionLowerBound(Tao tao, PetscReal *fmin)
975: {
976:   PetscFunctionBegin;
978:   PetscAssertPointer(fmin, 2);
979:   *fmin = tao->fmin;
980:   PetscFunctionReturn(PETSC_SUCCESS);
981: }

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

986:   Logically Collective

988:   Input Parameters:
989: + tao  - the `Tao` solver context
990: - nfcn - the maximum number of function evaluations (>=0)

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

995:   Level: intermediate

997: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumIterations()`
998: @*/
999: PetscErrorCode TaoSetMaximumFunctionEvaluations(Tao tao, PetscInt nfcn)
1000: {
1001:   PetscFunctionBegin;
1004:   if (nfcn >= 0) {
1005:     tao->max_funcs = PetscMax(0, nfcn);
1006:   } else {
1007:     tao->max_funcs = -1;
1008:   }
1009:   tao->max_funcs_changed = PETSC_TRUE;
1010:   PetscFunctionReturn(PETSC_SUCCESS);
1011: }

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

1016:   Logically Collective

1018:   Input Parameter:
1019: . tao - the `Tao` solver context

1021:   Output Parameter:
1022: . nfcn - the maximum number of function evaluations

1024:   Level: intermediate

1026: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1027: @*/
1028: PetscErrorCode TaoGetMaximumFunctionEvaluations(Tao tao, PetscInt *nfcn)
1029: {
1030:   PetscFunctionBegin;
1032:   PetscAssertPointer(nfcn, 2);
1033:   *nfcn = tao->max_funcs;
1034:   PetscFunctionReturn(PETSC_SUCCESS);
1035: }

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

1040:   Not Collective

1042:   Input Parameter:
1043: . tao - the `Tao` solver context

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

1048:   Level: intermediate

1050: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1051: @*/
1052: PetscErrorCode TaoGetCurrentFunctionEvaluations(Tao tao, PetscInt *nfuncs)
1053: {
1054:   PetscFunctionBegin;
1056:   PetscAssertPointer(nfuncs, 2);
1057:   *nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1058:   PetscFunctionReturn(PETSC_SUCCESS);
1059: }

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

1064:   Logically Collective

1066:   Input Parameters:
1067: + tao    - the `Tao` solver context
1068: - maxits - the maximum number of iterates (>=0)

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

1073:   Level: intermediate

1075: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumFunctionEvaluations()`
1076: @*/
1077: PetscErrorCode TaoSetMaximumIterations(Tao tao, PetscInt maxits)
1078: {
1079:   PetscFunctionBegin;
1082:   tao->max_it         = PetscMax(0, maxits);
1083:   tao->max_it_changed = PETSC_TRUE;
1084:   PetscFunctionReturn(PETSC_SUCCESS);
1085: }

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

1090:   Not Collective

1092:   Input Parameter:
1093: . tao - the `Tao` solver context

1095:   Output Parameter:
1096: . maxits - the maximum number of iterates

1098:   Level: intermediate

1100: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumIterations()`, `TaoGetMaximumFunctionEvaluations()`
1101: @*/
1102: PetscErrorCode TaoGetMaximumIterations(Tao tao, PetscInt *maxits)
1103: {
1104:   PetscFunctionBegin;
1106:   PetscAssertPointer(maxits, 2);
1107:   *maxits = tao->max_it;
1108:   PetscFunctionReturn(PETSC_SUCCESS);
1109: }

1111: /*@
1112:   TaoSetInitialTrustRegionRadius - Sets the initial trust region radius.

1114:   Logically Collective

1116:   Input Parameters:
1117: + tao    - a `Tao` optimization solver
1118: - radius - the trust region radius

1120:   Options Database Key:
1121: . -tao_trust0 <t0> - sets initial trust region radius

1123:   Level: intermediate

1125: .seealso: [](ch_tao), `Tao`, `TaoGetTrustRegionRadius()`, `TaoSetTrustRegionTolerance()`, `TAONTR`
1126: @*/
1127: PetscErrorCode TaoSetInitialTrustRegionRadius(Tao tao, PetscReal radius)
1128: {
1129:   PetscFunctionBegin;
1132:   tao->trust0         = PetscMax(0.0, radius);
1133:   tao->trust0_changed = PETSC_TRUE;
1134:   PetscFunctionReturn(PETSC_SUCCESS);
1135: }

1137: /*@
1138:   TaoGetInitialTrustRegionRadius - Gets the initial trust region radius.

1140:   Not Collective

1142:   Input Parameter:
1143: . tao - a `Tao` optimization solver

1145:   Output Parameter:
1146: . radius - the trust region radius

1148:   Level: intermediate

1150: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetCurrentTrustRegionRadius()`, `TAONTR`
1151: @*/
1152: PetscErrorCode TaoGetInitialTrustRegionRadius(Tao tao, PetscReal *radius)
1153: {
1154:   PetscFunctionBegin;
1156:   PetscAssertPointer(radius, 2);
1157:   *radius = tao->trust0;
1158:   PetscFunctionReturn(PETSC_SUCCESS);
1159: }

1161: /*@
1162:   TaoGetCurrentTrustRegionRadius - Gets the current trust region radius.

1164:   Not Collective

1166:   Input Parameter:
1167: . tao - a `Tao` optimization solver

1169:   Output Parameter:
1170: . radius - the trust region radius

1172:   Level: intermediate

1174: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetInitialTrustRegionRadius()`, `TAONTR`
1175: @*/
1176: PetscErrorCode TaoGetCurrentTrustRegionRadius(Tao tao, PetscReal *radius)
1177: {
1178:   PetscFunctionBegin;
1180:   PetscAssertPointer(radius, 2);
1181:   *radius = tao->trust;
1182:   PetscFunctionReturn(PETSC_SUCCESS);
1183: }

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

1188:   Not Collective

1190:   Input Parameter:
1191: . tao - the `Tao` context

1193:   Output Parameters:
1194: + gatol - stop if norm of gradient is less than this
1195: . grtol - stop if relative norm of gradient is less than this
1196: - gttol - stop if norm of gradient is reduced by a this factor

1198:   Level: intermediate

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

1203: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`
1204: @*/
1205: PetscErrorCode TaoGetTolerances(Tao tao, PetscReal *gatol, PetscReal *grtol, PetscReal *gttol)
1206: {
1207:   PetscFunctionBegin;
1209:   if (gatol) *gatol = tao->gatol;
1210:   if (grtol) *grtol = tao->grtol;
1211:   if (gttol) *gttol = tao->gttol;
1212:   PetscFunctionReturn(PETSC_SUCCESS);
1213: }

1215: /*@
1216:   TaoGetKSP - Gets the linear solver used by the optimization solver.

1218:   Not Collective

1220:   Input Parameter:
1221: . tao - the `Tao` solver

1223:   Output Parameter:
1224: . ksp - the `KSP` linear solver used in the optimization solver

1226:   Level: intermediate

1228: .seealso: [](ch_tao), `Tao`, `KSP`
1229: @*/
1230: PetscErrorCode TaoGetKSP(Tao tao, KSP *ksp)
1231: {
1232:   PetscFunctionBegin;
1234:   PetscAssertPointer(ksp, 2);
1235:   *ksp = tao->ksp;
1236:   PetscFunctionReturn(PETSC_SUCCESS);
1237: }

1239: /*@
1240:   TaoGetLinearSolveIterations - Gets the total number of linear iterations
1241:   used by the `Tao` solver

1243:   Not Collective

1245:   Input Parameter:
1246: . tao - the `Tao` context

1248:   Output Parameter:
1249: . lits - number of linear iterations

1251:   Level: intermediate

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

1256: .seealso: [](ch_tao), `Tao`, `TaoGetKSP()`
1257: @*/
1258: PetscErrorCode TaoGetLinearSolveIterations(Tao tao, PetscInt *lits)
1259: {
1260:   PetscFunctionBegin;
1262:   PetscAssertPointer(lits, 2);
1263:   *lits = tao->ksp_tot_its;
1264:   PetscFunctionReturn(PETSC_SUCCESS);
1265: }

1267: /*@
1268:   TaoGetLineSearch - Gets the line search used by the optimization solver.

1270:   Not Collective

1272:   Input Parameter:
1273: . tao - the `Tao` solver

1275:   Output Parameter:
1276: . ls - the line search used in the optimization solver

1278:   Level: intermediate

1280: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`
1281: @*/
1282: PetscErrorCode TaoGetLineSearch(Tao tao, TaoLineSearch *ls)
1283: {
1284:   PetscFunctionBegin;
1286:   PetscAssertPointer(ls, 2);
1287:   *ls = tao->linesearch;
1288:   PetscFunctionReturn(PETSC_SUCCESS);
1289: }

1291: /*@
1292:   TaoAddLineSearchCounts - Adds the number of function evaluations spent
1293:   in the line search to the running total.

1295:   Input Parameters:
1296: . tao - the `Tao` solver

1298:   Level: developer

1300: .seealso: [](ch_tao), `Tao`, `TaoGetLineSearch()`, `TaoLineSearchApply()`
1301: @*/
1302: PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1303: {
1304:   PetscBool flg;
1305:   PetscInt  nfeval, ngeval, nfgeval;

1307:   PetscFunctionBegin;
1309:   if (tao->linesearch) {
1310:     PetscCall(TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg));
1311:     if (!flg) {
1312:       PetscCall(TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval));
1313:       tao->nfuncs += nfeval;
1314:       tao->ngrads += ngeval;
1315:       tao->nfuncgrads += nfgeval;
1316:     }
1317:   }
1318:   PetscFunctionReturn(PETSC_SUCCESS);
1319: }

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

1324:   Not Collective

1326:   Input Parameter:
1327: . tao - the `Tao` context

1329:   Output Parameter:
1330: . X - the current solution

1332:   Level: intermediate

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

1337: .seealso: [](ch_tao), `Tao`, `TaoSetSolution()`, `TaoSolve()`
1338: @*/
1339: PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1340: {
1341:   PetscFunctionBegin;
1343:   PetscAssertPointer(X, 2);
1344:   *X = tao->solution;
1345:   PetscFunctionReturn(PETSC_SUCCESS);
1346: }

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

1353:   Collective

1355:   Input Parameter:
1356: . tao - the `Tao` context

1358:   Level: developer

1360: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
1361: @*/
1362: PetscErrorCode TaoResetStatistics(Tao tao)
1363: {
1364:   PetscFunctionBegin;
1366:   tao->niter        = 0;
1367:   tao->nfuncs       = 0;
1368:   tao->nfuncgrads   = 0;
1369:   tao->ngrads       = 0;
1370:   tao->nhess        = 0;
1371:   tao->njac         = 0;
1372:   tao->nconstraints = 0;
1373:   tao->ksp_its      = 0;
1374:   tao->ksp_tot_its  = 0;
1375:   tao->reason       = TAO_CONTINUE_ITERATING;
1376:   tao->residual     = 0.0;
1377:   tao->cnorm        = 0.0;
1378:   tao->step         = 0.0;
1379:   tao->lsflag       = PETSC_FALSE;
1380:   if (tao->hist_reset) tao->hist_len = 0;
1381:   PetscFunctionReturn(PETSC_SUCCESS);
1382: }

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

1389:   Logically Collective

1391:   Input Parameters:
1392: + tao  - The `Tao` solver
1393: . func - The function
1394: - ctx  - The update function context

1396:   Calling sequence of `func`:
1397: + tao - The optimizer context
1398: . it  - The current iteration index
1399: - ctx - The update context

1401:   Level: advanced

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

1407: .seealso: [](ch_tao), `Tao`, `TaoSolve()`
1408: @*/
1409: PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao tao, PetscInt it, void *ctx), void *ctx)
1410: {
1411:   PetscFunctionBegin;
1413:   tao->ops->update = func;
1414:   tao->user_update = ctx;
1415:   PetscFunctionReturn(PETSC_SUCCESS);
1416: }

1418: /*@C
1419:   TaoSetConvergenceTest - Sets the function that is to be used to test
1420:   for convergence o fthe iterative minimization solution.  The new convergence
1421:   testing routine will replace Tao's default convergence test.

1423:   Logically Collective

1425:   Input Parameters:
1426: + tao  - the `Tao` object
1427: . conv - the routine to test for convergence
1428: - ctx  - [optional] context for private data for the convergence routine
1429:         (may be `NULL`)

1431:   Calling sequence of `conv`:
1432: + tao - the `Tao` object
1433: - ctx - [optional] convergence context

1435:   Level: advanced

1437:   Note:
1438:   The new convergence testing routine should call `TaoSetConvergedReason()`.

1440: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoMonitorSet()`
1441: @*/
1442: PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao, void *), void *ctx)
1443: {
1444:   PetscFunctionBegin;
1446:   tao->ops->convergencetest = conv;
1447:   tao->cnvP                 = ctx;
1448:   PetscFunctionReturn(PETSC_SUCCESS);
1449: }

1451: /*@C
1452:   TaoMonitorSet - Sets an additional function that is to be used at every
1453:   iteration of the solver to display the iteration's
1454:   progress.

1456:   Logically Collective

1458:   Input Parameters:
1459: + tao  - the `Tao` solver context
1460: . func - monitoring routine
1461: . ctx  - [optional] user-defined context for private data for the monitor routine (may be `NULL`)
1462: - dest - [optional] function to destroy the context when the `Tao` is destroyed

1464:   Calling sequence of `func`:
1465: + tao - the `Tao` solver context
1466: - ctx - [optional] monitoring context

1468:   Calling sequence of `dest`:
1469: . ctx - monitoring context

1471:   Level: intermediate

1473:   Notes:
1474:   See `TaoSetFromOptions()` for a monitoring options.

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

1480:   Fortran Notes:
1481:   Only one monitor function may be set

1483: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoMonitorDefault()`, `TaoMonitorCancel()`, `TaoSetDestroyRoutine()`, `TaoView()`
1484: @*/
1485: PetscErrorCode TaoMonitorSet(Tao tao, PetscErrorCode (*func)(Tao, void *), void *ctx, PetscErrorCode (*dest)(void **))
1486: {
1487:   PetscInt  i;
1488:   PetscBool identical;

1490:   PetscFunctionBegin;
1492:   PetscCheck(tao->numbermonitors < MAXTAOMONITORS, PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Cannot attach another monitor -- max=%d", MAXTAOMONITORS);

1494:   for (i = 0; i < tao->numbermonitors; i++) {
1495:     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))func, ctx, dest, (PetscErrorCode(*)(void))tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical));
1496:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1497:   }
1498:   tao->monitor[tao->numbermonitors]        = func;
1499:   tao->monitorcontext[tao->numbermonitors] = (void *)ctx;
1500:   tao->monitordestroy[tao->numbermonitors] = dest;
1501:   ++tao->numbermonitors;
1502:   PetscFunctionReturn(PETSC_SUCCESS);
1503: }

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

1508:   Logically Collective

1510:   Input Parameter:
1511: . tao - the `Tao` solver context

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

1518:   Level: advanced

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

1523: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1524: @*/
1525: PetscErrorCode TaoMonitorCancel(Tao tao)
1526: {
1527:   PetscInt i;

1529:   PetscFunctionBegin;
1531:   for (i = 0; i < tao->numbermonitors; i++) {
1532:     if (tao->monitordestroy[i]) PetscCall((*tao->monitordestroy[i])(&tao->monitorcontext[i]));
1533:   }
1534:   tao->numbermonitors = 0;
1535:   PetscFunctionReturn(PETSC_SUCCESS);
1536: }

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

1541:   Collective

1543:   Input Parameters:
1544: + tao - the `Tao` context
1545: - ctx - `PetscViewer` context or `NULL`

1547:   Options Database Key:
1548: . -tao_monitor - turn on default monitoring

1550:   Level: advanced

1552:   Note:
1553:   This monitor prints the function value and gradient
1554:   norm at each iteration.

1556: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1557: @*/
1558: PetscErrorCode TaoMonitorDefault(Tao tao, void *ctx)
1559: {
1560:   PetscInt    its, tabs;
1561:   PetscReal   fct, gnorm;
1562:   PetscViewer viewer = (PetscViewer)ctx;

1564:   PetscFunctionBegin;
1567:   its   = tao->niter;
1568:   fct   = tao->fc;
1569:   gnorm = tao->residual;
1570:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1571:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1572:   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1573:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1574:     tao->header_printed = PETSC_TRUE;
1575:   }
1576:   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1577:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1578:   if (gnorm >= PETSC_INFINITY) {
1579:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf \n"));
1580:   } else {
1581:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g \n", (double)gnorm));
1582:   }
1583:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1584:   PetscFunctionReturn(PETSC_SUCCESS);
1585: }

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

1590:   Collective

1592:   Input Parameters:
1593: + tao - the `Tao` context
1594: - ctx - `PetscViewer` context or `NULL`

1596:   Options Database Key:
1597: . -tao_monitor_globalization - turn on monitoring with globalization information

1599:   Level: advanced

1601:   Note:
1602:   This monitor prints the function value and gradient norm at each
1603:   iteration, as well as the step size and trust radius. Note that the
1604:   step size and trust radius may be the same for some algorithms.

1606: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1607: @*/
1608: PetscErrorCode TaoMonitorGlobalization(Tao tao, void *ctx)
1609: {
1610:   PetscInt    its, tabs;
1611:   PetscReal   fct, gnorm, stp, tr;
1612:   PetscViewer viewer = (PetscViewer)ctx;

1614:   PetscFunctionBegin;
1617:   its   = tao->niter;
1618:   fct   = tao->fc;
1619:   gnorm = tao->residual;
1620:   stp   = tao->step;
1621:   tr    = tao->trust;
1622:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1623:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1624:   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1625:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1626:     tao->header_printed = PETSC_TRUE;
1627:   }
1628:   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1629:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1630:   if (gnorm >= PETSC_INFINITY) {
1631:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf,"));
1632:   } else {
1633:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g,", (double)gnorm));
1634:   }
1635:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Step: %g,  Trust: %g\n", (double)stp, (double)tr));
1636:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1637:   PetscFunctionReturn(PETSC_SUCCESS);
1638: }

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

1643:   Collective

1645:   Input Parameters:
1646: + tao - the `Tao` context
1647: - ctx - `PetscViewer` context of type `PETSCVIEWERASCII`

1649:   Options Database Key:
1650: . -tao_monitor_short - turn on default short monitoring

1652:   Level: advanced

1654:   Note:
1655:   Same as `TaoMonitorDefault()` except
1656:   it prints fewer digits of the residual as the residual gets smaller.
1657:   This is because the later digits are meaningless and are often
1658:   different on different machines; by using this routine different
1659:   machines will usually generate the same output.

1661: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1662: @*/
1663: PetscErrorCode TaoMonitorDefaultShort(Tao tao, void *ctx)
1664: {
1665:   PetscInt    its, tabs;
1666:   PetscReal   fct, gnorm;
1667:   PetscViewer viewer = (PetscViewer)ctx;

1669:   PetscFunctionBegin;
1672:   its   = tao->niter;
1673:   fct   = tao->fc;
1674:   gnorm = tao->residual;
1675:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1676:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1677:   PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %3" PetscInt_FMT ",", its));
1678:   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value %g,", (double)fct));
1679:   if (gnorm >= PETSC_INFINITY) {
1680:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf \n"));
1681:   } else if (gnorm > 1.e-6) {
1682:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm));
1683:   } else if (gnorm > 1.e-11) {
1684:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-6 \n"));
1685:   } else {
1686:     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-11 \n"));
1687:   }
1688:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1689:   PetscFunctionReturn(PETSC_SUCCESS);
1690: }

1692: /*@
1693:   TaoMonitorConstraintNorm - same as `TaoMonitorDefault()` except
1694:   it prints the norm of the constraint function.

1696:   Collective

1698:   Input Parameters:
1699: + tao - the `Tao` context
1700: - ctx - `PetscViewer` context or `NULL`

1702:   Options Database Key:
1703: . -tao_monitor_constraint_norm - monitor the constraints

1705:   Level: advanced

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

1715:   PetscFunctionBegin;
1718:   its   = tao->niter;
1719:   fct   = tao->fc;
1720:   gnorm = tao->residual;
1721:   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1722:   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1723:   PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", its));
1724:   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct));
1725:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g ", (double)gnorm));
1726:   PetscCall(PetscViewerASCIIPrintf(viewer, "  Constraint: %g \n", (double)tao->cnorm));
1727:   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1728:   PetscFunctionReturn(PETSC_SUCCESS);
1729: }

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

1734:   Collective

1736:   Input Parameters:
1737: + tao - the `Tao` context
1738: - ctx - `PetscViewer` context or `NULL`

1740:   Options Database Key:
1741: . -tao_monitor_solution - view the solution

1743:   Level: advanced

1745: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1746: @*/
1747: PetscErrorCode TaoMonitorSolution(Tao tao, void *ctx)
1748: {
1749:   PetscViewer viewer = (PetscViewer)ctx;

1751:   PetscFunctionBegin;
1754:   PetscCall(VecView(tao->solution, viewer));
1755:   PetscFunctionReturn(PETSC_SUCCESS);
1756: }

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

1761:   Collective

1763:   Input Parameters:
1764: + tao - the `Tao` context
1765: - ctx - `PetscViewer` context or `NULL`

1767:   Options Database Key:
1768: . -tao_monitor_gradient - view the gradient at each iteration

1770:   Level: advanced

1772: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1773: @*/
1774: PetscErrorCode TaoMonitorGradient(Tao tao, void *ctx)
1775: {
1776:   PetscViewer viewer = (PetscViewer)ctx;

1778:   PetscFunctionBegin;
1781:   PetscCall(VecView(tao->gradient, viewer));
1782:   PetscFunctionReturn(PETSC_SUCCESS);
1783: }

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

1788:   Collective

1790:   Input Parameters:
1791: + tao - the `Tao` context
1792: - ctx - `PetscViewer` context or `NULL`

1794:   Options Database Key:
1795: . -tao_monitor_step - view the step vector at each iteration

1797:   Level: advanced

1799: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1800: @*/
1801: PetscErrorCode TaoMonitorStep(Tao tao, void *ctx)
1802: {
1803:   PetscViewer viewer = (PetscViewer)ctx;

1805:   PetscFunctionBegin;
1808:   PetscCall(VecView(tao->stepdirection, viewer));
1809:   PetscFunctionReturn(PETSC_SUCCESS);
1810: }

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

1815:   Collective

1817:   Input Parameters:
1818: + tao - the `Tao` context
1819: - ctx - `TaoMonitorDraw` context

1821:   Options Database Key:
1822: . -tao_monitor_solution_draw - draw the solution at each iteration

1824:   Level: advanced

1826: .seealso: [](ch_tao), `Tao`, `TaoMonitorSolution()`, `TaoMonitorSet()`, `TaoMonitorGradientDraw()`
1827: @*/
1828: PetscErrorCode TaoMonitorSolutionDraw(Tao tao, void *ctx)
1829: {
1830:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

1832:   PetscFunctionBegin;
1834:   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1835:   PetscCall(VecView(tao->solution, ictx->viewer));
1836:   PetscFunctionReturn(PETSC_SUCCESS);
1837: }

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

1842:   Collective

1844:   Input Parameters:
1845: + tao - the `Tao` context
1846: - ctx - `PetscViewer` context

1848:   Options Database Key:
1849: . -tao_monitor_gradient_draw - draw the gradient at each iteration

1851:   Level: advanced

1853: .seealso: [](ch_tao), `Tao`, `TaoMonitorGradient()`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw()`
1854: @*/
1855: PetscErrorCode TaoMonitorGradientDraw(Tao tao, void *ctx)
1856: {
1857:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

1859:   PetscFunctionBegin;
1861:   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1862:   PetscCall(VecView(tao->gradient, ictx->viewer));
1863:   PetscFunctionReturn(PETSC_SUCCESS);
1864: }

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

1869:   Collective

1871:   Input Parameters:
1872: + tao - the `Tao` context
1873: - ctx - the `PetscViewer` context

1875:   Options Database Key:
1876: . -tao_monitor_step_draw - draw the step direction at each iteration

1878:   Level: advanced

1880: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw`
1881: @*/
1882: PetscErrorCode TaoMonitorStepDraw(Tao tao, void *ctx)
1883: {
1884:   PetscViewer viewer = (PetscViewer)ctx;

1886:   PetscFunctionBegin;
1889:   PetscCall(VecView(tao->stepdirection, viewer));
1890:   PetscFunctionReturn(PETSC_SUCCESS);
1891: }

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

1896:   Collective

1898:   Input Parameters:
1899: + tao - the `Tao` context
1900: - ctx - the `PetscViewer` context or `NULL`

1902:   Options Database Key:
1903: . -tao_monitor_ls_residual - view the residual at each iteration

1905:   Level: advanced

1907: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1908: @*/
1909: PetscErrorCode TaoMonitorResidual(Tao tao, void *ctx)
1910: {
1911:   PetscViewer viewer = (PetscViewer)ctx;

1913:   PetscFunctionBegin;
1916:   PetscCall(VecView(tao->ls_res, viewer));
1917:   PetscFunctionReturn(PETSC_SUCCESS);
1918: }

1920: /*@
1921:   TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
1922:   or terminate.

1924:   Collective

1926:   Input Parameters:
1927: + tao   - the `Tao` context
1928: - dummy - unused dummy context

1930:   Level: developer

1932:   Notes:
1933:   This routine checks the residual in the optimality conditions, the
1934:   relative residual in the optimity conditions, the number of function
1935:   evaluations, and the function value to test convergence.  Some
1936:   solvers may use different convergence routines.

1938: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
1939: @*/
1940: PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
1941: {
1942:   PetscInt           niter = tao->niter, nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1943:   PetscInt           max_funcs = tao->max_funcs;
1944:   PetscReal          gnorm = tao->residual, gnorm0 = tao->gnorm0;
1945:   PetscReal          f = tao->fc, steptol = tao->steptol, trradius = tao->step;
1946:   PetscReal          gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
1947:   PetscReal          catol = tao->catol, crtol = tao->crtol;
1948:   PetscReal          fmin = tao->fmin, cnorm = tao->cnorm;
1949:   TaoConvergedReason reason = tao->reason;

1951:   PetscFunctionBegin;
1953:   if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);

1955:   if (PetscIsInfOrNanReal(f)) {
1956:     PetscCall(PetscInfo(tao, "Failed to converged, function value is Inf or NaN\n"));
1957:     reason = TAO_DIVERGED_NAN;
1958:   } else if (f <= fmin && cnorm <= catol) {
1959:     PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
1960:     reason = TAO_CONVERGED_MINF;
1961:   } else if (gnorm <= gatol && cnorm <= catol) {
1962:     PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
1963:     reason = TAO_CONVERGED_GATOL;
1964:   } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
1965:     PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
1966:     reason = TAO_CONVERGED_GRTOL;
1967:   } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
1968:     PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
1969:     reason = TAO_CONVERGED_GTTOL;
1970:   } else if (max_funcs >= 0 && nfuncs > max_funcs) {
1971:     PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
1972:     reason = TAO_DIVERGED_MAXFCN;
1973:   } else if (tao->lsflag != 0) {
1974:     PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
1975:     reason = TAO_DIVERGED_LS_FAILURE;
1976:   } else if (trradius < steptol && niter > 0) {
1977:     PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
1978:     reason = TAO_CONVERGED_STEPTOL;
1979:   } else if (niter >= tao->max_it) {
1980:     PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
1981:     reason = TAO_DIVERGED_MAXITS;
1982:   } else {
1983:     reason = TAO_CONTINUE_ITERATING;
1984:   }
1985:   tao->reason = reason;
1986:   PetscFunctionReturn(PETSC_SUCCESS);
1987: }

1989: /*@
1990:   TaoSetOptionsPrefix - Sets the prefix used for searching for all
1991:   Tao options in the database.

1993:   Logically Collective

1995:   Input Parameters:
1996: + tao - the `Tao` context
1997: - p   - the prefix string to prepend to all Tao option requests

1999:   Level: advanced

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

2005:   For example, to distinguish between the runtime options for two
2006:   different Tao solvers, one could call
2007: .vb
2008:       TaoSetOptionsPrefix(tao1,"sys1_")
2009:       TaoSetOptionsPrefix(tao2,"sys2_")
2010: .ve

2012:   This would enable use of different options for each system, such as
2013: .vb
2014:       -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2015:       -sys2_tao_method lmvm  -sys2_tao_grtol 1.e-4
2016: .ve

2018: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2019: @*/
2020: PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2021: {
2022:   PetscFunctionBegin;
2024:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2025:   if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2026:   if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2027:   PetscFunctionReturn(PETSC_SUCCESS);
2028: }

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

2033:   Logically Collective

2035:   Input Parameters:
2036: + tao - the `Tao` solver context
2037: - p   - the prefix string to prepend to all `Tao` option requests

2039:   Level: advanced

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

2045: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2046: @*/
2047: PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2048: {
2049:   PetscFunctionBegin;
2051:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2052:   if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2053:   if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2054:   PetscFunctionReturn(PETSC_SUCCESS);
2055: }

2057: /*@
2058:   TaoGetOptionsPrefix - Gets the prefix used for searching for all
2059:   Tao options in the database

2061:   Not Collective

2063:   Input Parameter:
2064: . tao - the `Tao` context

2066:   Output Parameter:
2067: . p - pointer to the prefix string used is returned

2069:   Fortran Notes:
2070:   Pass in a string 'prefix' of sufficient length to hold the prefix.

2072:   Level: advanced

2074: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2075: @*/
2076: PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2077: {
2078:   PetscFunctionBegin;
2080:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2081:   PetscFunctionReturn(PETSC_SUCCESS);
2082: }

2084: /*@
2085:   TaoSetType - Sets the `TaoType` for the minimization solver.

2087:   Collective

2089:   Input Parameters:
2090: + tao  - the `Tao` solver context
2091: - type - a known method

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

2097:   Level: intermediate

2099: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2100: @*/
2101: PetscErrorCode TaoSetType(Tao tao, TaoType type)
2102: {
2103:   PetscErrorCode (*create_xxx)(Tao);
2104:   PetscBool issame;

2106:   PetscFunctionBegin;

2109:   PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2110:   if (issame) PetscFunctionReturn(PETSC_SUCCESS);

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

2115:   /* Destroy the existing solver information */
2116:   PetscTryTypeMethod(tao, destroy);
2117:   PetscCall(KSPDestroy(&tao->ksp));
2118:   PetscCall(TaoLineSearchDestroy(&tao->linesearch));
2119:   tao->ops->setup          = NULL;
2120:   tao->ops->solve          = NULL;
2121:   tao->ops->view           = NULL;
2122:   tao->ops->setfromoptions = NULL;
2123:   tao->ops->destroy        = NULL;

2125:   tao->setupcalled = PETSC_FALSE;

2127:   PetscCall((*create_xxx)(tao));
2128:   PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2129:   PetscFunctionReturn(PETSC_SUCCESS);
2130: }

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

2135:   Not Collective, No Fortran Support

2137:   Input Parameters:
2138: + sname - name of a new user-defined solver
2139: - func  - routine to Create method context

2141:   Example Usage:
2142: .vb
2143:    TaoRegister("my_solver", MySolverCreate);
2144: .ve

2146:   Then, your solver can be chosen with the procedural interface via
2147: $     TaoSetType(tao, "my_solver")
2148:   or at runtime via the option
2149: $     -tao_type my_solver

2151:   Level: advanced

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

2156: .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2157: @*/
2158: PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao))
2159: {
2160:   PetscFunctionBegin;
2161:   PetscCall(TaoInitializePackage());
2162:   PetscCall(PetscFunctionListAdd(&TaoList, sname, (void (*)(void))func));
2163:   PetscFunctionReturn(PETSC_SUCCESS);
2164: }

2166: /*@C
2167:   TaoRegisterDestroy - Frees the list of minimization solvers that were
2168:   registered by `TaoRegister()`.

2170:   Not Collective

2172:   Level: advanced

2174: .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2175: @*/
2176: PetscErrorCode TaoRegisterDestroy(void)
2177: {
2178:   PetscFunctionBegin;
2179:   PetscCall(PetscFunctionListDestroy(&TaoList));
2180:   TaoRegisterAllCalled = PETSC_FALSE;
2181:   PetscFunctionReturn(PETSC_SUCCESS);
2182: }

2184: /*@
2185:   TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2186:   at this time.

2188:   Not Collective

2190:   Input Parameter:
2191: . tao - the `Tao` context

2193:   Output Parameter:
2194: . iter - iteration number

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

2199:   Level: intermediate

2201: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2202: @*/
2203: PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2204: {
2205:   PetscFunctionBegin;
2207:   PetscAssertPointer(iter, 2);
2208:   *iter = tao->niter;
2209:   PetscFunctionReturn(PETSC_SUCCESS);
2210: }

2212: /*@
2213:   TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2214:   at this time.

2216:   Not Collective

2218:   Input Parameter:
2219: . tao - the `Tao` context

2221:   Output Parameter:
2222: . value - the current value

2224:   Level: intermediate

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

2230: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2231: @*/
2232: PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2233: {
2234:   PetscFunctionBegin;
2236:   PetscAssertPointer(value, 2);
2237:   *value = tao->residual;
2238:   PetscFunctionReturn(PETSC_SUCCESS);
2239: }

2241: /*@
2242:   TaoSetIterationNumber - Sets the current iteration number.

2244:   Logically Collective

2246:   Input Parameters:
2247: + tao  - the `Tao` context
2248: - iter - iteration number

2250:   Level: developer

2252: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2253: @*/
2254: PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2255: {
2256:   PetscFunctionBegin;
2259:   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2260:   tao->niter = iter;
2261:   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2262:   PetscFunctionReturn(PETSC_SUCCESS);
2263: }

2265: /*@
2266:   TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2267:   completed. This number keeps accumulating if multiple solves
2268:   are called with the `Tao` object.

2270:   Not Collective

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

2275:   Output Parameter:
2276: . iter - number of iterations

2278:   Level: intermediate

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

2284: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2285: @*/
2286: PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2287: {
2288:   PetscFunctionBegin;
2290:   PetscAssertPointer(iter, 2);
2291:   *iter = tao->ntotalits;
2292:   PetscFunctionReturn(PETSC_SUCCESS);
2293: }

2295: /*@
2296:   TaoSetTotalIterationNumber - Sets the current total iteration number.

2298:   Logically Collective

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

2304:   Level: developer

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

2319: /*@
2320:   TaoSetConvergedReason - Sets the termination flag on a `Tao` object

2322:   Logically Collective

2324:   Input Parameters:
2325: + tao    - the `Tao` context
2326: - reason - the `TaoConvergedReason`

2328:   Level: intermediate

2330: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2331: @*/
2332: PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2333: {
2334:   PetscFunctionBegin;
2337:   tao->reason = reason;
2338:   PetscFunctionReturn(PETSC_SUCCESS);
2339: }

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

2344:   Not Collective

2346:   Input Parameter:
2347: . tao - the `Tao` solver context

2349:   Output Parameter:
2350: . reason - value of `TaoConvergedReason`

2352:   Level: intermediate

2354: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`
2355: @*/
2356: PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2357: {
2358:   PetscFunctionBegin;
2360:   PetscAssertPointer(reason, 2);
2361:   *reason = tao->reason;
2362:   PetscFunctionReturn(PETSC_SUCCESS);
2363: }

2365: /*@
2366:   TaoGetSolutionStatus - Get the current iterate, objective value,
2367:   residual, infeasibility, and termination from a `Tao` object

2369:   Not Collective

2371:   Input Parameter:
2372: . tao - the `Tao` context

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

2382:   Level: intermediate

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

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

2389: .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2390: @*/
2391: PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2392: {
2393:   PetscFunctionBegin;
2395:   if (its) *its = tao->niter;
2396:   if (f) *f = tao->fc;
2397:   if (gnorm) *gnorm = tao->residual;
2398:   if (cnorm) *cnorm = tao->cnorm;
2399:   if (reason) *reason = tao->reason;
2400:   if (xdiff) *xdiff = tao->step;
2401:   PetscFunctionReturn(PETSC_SUCCESS);
2402: }

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

2407:   Not Collective

2409:   Input Parameter:
2410: . tao - the `Tao` solver context

2412:   Output Parameter:
2413: . type - the `TaoType`

2415:   Level: intermediate

2417: .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`
2418: @*/
2419: PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2420: {
2421:   PetscFunctionBegin;
2423:   PetscAssertPointer(type, 2);
2424:   *type = ((PetscObject)tao)->type_name;
2425:   PetscFunctionReturn(PETSC_SUCCESS);
2426: }

2428: /*@C
2429:   TaoMonitor - Monitor the solver and the current solution.  This
2430:   routine will record the iteration number and residual statistics,
2431:   and call any monitors specified by the user.

2433:   Input Parameters:
2434: + tao        - the `Tao` context
2435: . its        - the current iterate number (>=0)
2436: . f          - the current objective function value
2437: . res        - the gradient norm, square root of the duality gap, or other measure indicating distance from optimality.  This measure will be recorded and
2438:           used for some termination tests.
2439: . cnorm      - the infeasibility of the current solution with regard to the constraints.
2440: - steplength - multiple of the step direction added to the previous iterate.

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

2445:   Level: developer

2447: .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoMonitorSet()`
2448: @*/
2449: PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2450: {
2451:   PetscInt i;

2453:   PetscFunctionBegin;
2455:   tao->fc       = f;
2456:   tao->residual = res;
2457:   tao->cnorm    = cnorm;
2458:   tao->step     = steplength;
2459:   if (!its) {
2460:     tao->cnorm0 = cnorm;
2461:     tao->gnorm0 = res;
2462:   }
2463:   PetscCall(VecLockReadPush(tao->solution));
2464:   for (i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2465:   PetscCall(VecLockReadPop(tao->solution));
2466:   PetscFunctionReturn(PETSC_SUCCESS);
2467: }

2469: /*@
2470:   TaoSetConvergenceHistory - Sets the array used to hold the convergence history.

2472:   Logically Collective

2474:   Input Parameters:
2475: + tao   - the `Tao` solver context
2476: . obj   - array to hold objective value history
2477: . resid - array to hold residual history
2478: . cnorm - array to hold constraint violation history
2479: . lits  - integer array holds the number of linear iterations for each Tao iteration
2480: . na    - size of `obj`, `resid`, and `cnorm`
2481: - reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2482:            else it continues storing new values for new minimizations after the old ones

2484:   Level: intermediate

2486:   Notes:
2487:   If set, `Tao` will fill the given arrays with the indicated
2488:   information at each iteration.  If 'obj','resid','cnorm','lits' are
2489:   *all* `NULL` then space (using size `na`, or 1000 if na is `PETSC_DECIDE` or
2490:   `PETSC_DEFAULT`) is allocated for the history.
2491:   If not all are `NULL`, then only the non-`NULL` information categories
2492:   will be stored, the others will be ignored.

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

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

2500: .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2501: @*/
2502: PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2503: {
2504:   PetscFunctionBegin;
2506:   if (obj) PetscAssertPointer(obj, 2);
2507:   if (resid) PetscAssertPointer(resid, 3);
2508:   if (cnorm) PetscAssertPointer(cnorm, 4);
2509:   if (lits) PetscAssertPointer(lits, 5);

2511:   if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
2512:   if (!obj && !resid && !cnorm && !lits) {
2513:     PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2514:     tao->hist_malloc = PETSC_TRUE;
2515:   }

2517:   tao->hist_obj   = obj;
2518:   tao->hist_resid = resid;
2519:   tao->hist_cnorm = cnorm;
2520:   tao->hist_lits  = lits;
2521:   tao->hist_max   = na;
2522:   tao->hist_reset = reset;
2523:   tao->hist_len   = 0;
2524:   PetscFunctionReturn(PETSC_SUCCESS);
2525: }

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

2530:   Collective

2532:   Input Parameter:
2533: . tao - the `Tao` context

2535:   Output Parameters:
2536: + obj   - array used to hold objective value history
2537: . resid - array used to hold residual history
2538: . cnorm - array used to hold constraint violation history
2539: . lits  - integer array used to hold linear solver iteration count
2540: - nhist - size of `obj`, `resid`, `cnorm`, and `lits`

2542:   Level: advanced

2544:   Notes:
2545:   This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2546:   and `TaoSolve()`, otherwise it returns useless information.

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:   Fortran Notes:
2553:   The calling sequence is
2554: .vb
2555:    call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2556: .ve
2557:   In other words this gets the current number of entries in the history. Access the history through the array you passed to `TaoSetConvergenceHistory()`

2559: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2560: @*/
2561: PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2562: {
2563:   PetscFunctionBegin;
2565:   if (obj) *obj = tao->hist_obj;
2566:   if (cnorm) *cnorm = tao->hist_cnorm;
2567:   if (resid) *resid = tao->hist_resid;
2568:   if (lits) *lits = tao->hist_lits;
2569:   if (nhist) *nhist = tao->hist_len;
2570:   PetscFunctionReturn(PETSC_SUCCESS);
2571: }

2573: /*@
2574:   TaoSetApplicationContext - Sets the optional user-defined context for a `Tao` solver.

2576:   Logically Collective

2578:   Input Parameters:
2579: + tao  - the `Tao` context
2580: - usrP - optional user context

2582:   Level: intermediate

2584: .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`
2585: @*/
2586: PetscErrorCode TaoSetApplicationContext(Tao tao, void *usrP)
2587: {
2588:   PetscFunctionBegin;
2590:   tao->user = usrP;
2591:   PetscFunctionReturn(PETSC_SUCCESS);
2592: }

2594: /*@
2595:   TaoGetApplicationContext - Gets the user-defined context for a `Tao` solver

2597:   Not Collective

2599:   Input Parameter:
2600: . tao - the `Tao` context

2602:   Output Parameter:
2603: . usrP - user context

2605:   Level: intermediate

2607: .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2608: @*/
2609: PetscErrorCode TaoGetApplicationContext(Tao tao, void *usrP)
2610: {
2611:   PetscFunctionBegin;
2613:   PetscAssertPointer(usrP, 2);
2614:   *(void **)usrP = tao->user;
2615:   PetscFunctionReturn(PETSC_SUCCESS);
2616: }

2618: /*@
2619:   TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient.

2621:   Collective

2623:   Input Parameters:
2624: + tao - the `Tao` context
2625: - M   - matrix that defines the norm

2627:   Level: beginner

2629: .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2630: @*/
2631: PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2632: {
2633:   PetscFunctionBegin;
2636:   PetscCall(PetscObjectReference((PetscObject)M));
2637:   PetscCall(MatDestroy(&tao->gradient_norm));
2638:   PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2639:   tao->gradient_norm = M;
2640:   PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2641:   PetscFunctionReturn(PETSC_SUCCESS);
2642: }

2644: /*@
2645:   TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient.

2647:   Not Collective

2649:   Input Parameter:
2650: . tao - the `Tao` context

2652:   Output Parameter:
2653: . M - gradient norm

2655:   Level: beginner

2657: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2658: @*/
2659: PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2660: {
2661:   PetscFunctionBegin;
2663:   PetscAssertPointer(M, 2);
2664:   *M = tao->gradient_norm;
2665:   PetscFunctionReturn(PETSC_SUCCESS);
2666: }

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

2671:   Collective

2673:   Input Parameters:
2674: + tao      - the `Tao` context
2675: . gradient - the gradient to be computed
2676: - type     - the norm type

2678:   Output Parameter:
2679: . gnorm - the gradient norm

2681:   Level: advanced

2683: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2684: @*/
2685: PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2686: {
2687:   PetscFunctionBegin;
2691:   PetscAssertPointer(gnorm, 4);
2692:   if (tao->gradient_norm) {
2693:     PetscScalar gnorms;

2695:     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.");
2696:     PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2697:     PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2698:     *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2699:   } else {
2700:     PetscCall(VecNorm(gradient, type, gnorm));
2701:   }
2702:   PetscFunctionReturn(PETSC_SUCCESS);
2703: }

2705: /*@C
2706:   TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorDrawSolution()`

2708:   Collective

2710:   Input Parameters:
2711: + comm     - the communicator to share the context
2712: . host     - the name of the X Windows host that will display the monitor
2713: . label    - the label to put at the top of the display window
2714: . x        - the horizontal coordinate of the lower left corner of the window to open
2715: . y        - the vertical coordinate of the lower left corner of the window to open
2716: . m        - the width of the window
2717: . n        - the height of the window
2718: - howoften - how many `Tao` iterations between displaying the monitor information

2720:   Output Parameter:
2721: . ctx - the monitor context

2723:   Options Database Key:
2724: . -tao_draw_solution_initial - show initial guess as well as current solution

2726:   Level: intermediate

2728: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2729: @*/
2730: PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2731: {
2732:   PetscFunctionBegin;
2733:   PetscCall(PetscNew(ctx));
2734:   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
2735:   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
2736:   (*ctx)->howoften = howoften;
2737:   PetscFunctionReturn(PETSC_SUCCESS);
2738: }

2740: /*@C
2741:   TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorDrawSolution()`

2743:   Collective

2745:   Input Parameter:
2746: . ictx - the monitor context

2748:   Level: intermediate

2750: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawSolution()`
2751: @*/
2752: PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2753: {
2754:   PetscFunctionBegin;
2755:   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
2756:   PetscCall(PetscFree(*ictx));
2757:   PetscFunctionReturn(PETSC_SUCCESS);
2758: }