xref: /petsc/src/tao/interface/taosolver.c (revision f8b9f887efa5534f423807e37a1fe2e87d779bac)
1 #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/
2 #include <petsc/private/snesimpl.h>
3 
4 PetscBool         TaoRegisterAllCalled = PETSC_FALSE;
5 PetscFunctionList TaoList              = NULL;
6 
7 PetscClassId TAO_CLASSID;
8 
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;
16 
17 const char *TaoSubSetTypes[] = {"subvec", "mask", "matrixfree", "TaoSubSetType", "TAO_SUBSET_", NULL};
18 
19 struct _n_TaoMonitorDrawCtx {
20   PetscViewer viewer;
21   PetscInt    howoften; /* when > 0 uses iteration % howoften, when negative only final solution plotted */
22 };
23 
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;
28 
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 }
40 
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;
45 
46   PetscFunctionBegin;
47   if (!snes_ewdummy) PetscFunctionReturn(PETSC_SUCCESS);
48   PetscCall(KSPPostSolve_SNESEW(ksp, b, x, snes_ewdummy));
49   PetscFunctionReturn(PETSC_SUCCESS);
50 }
51 
52 static PetscErrorCode TaoSetUpEW_Private(Tao tao)
53 {
54   SNESKSPEW  *kctx;
55   const char *ewprefix;
56 
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));
64 
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 }
71 
72 /*@
73   TaoParametersInitialize - Sets all the parameters in `tao` to their default value (when `TaoCreate()` was called) if they
74   currently contain default values. Default values are the parameter values when the object's type is set.
75 
76   Collective
77 
78   Input Parameter:
79 . tao - the `Tao` object
80 
81   Level: developer
82 
83   Developer Note:
84   This is called by all the `TaoCreate_XXX()` routines.
85 
86 .seealso: [](ch_snes), `Tao`, `TaoSolve()`, `TaoDestroy()`,
87           `PetscObjectParameterSetDefault()`
88 @*/
89 PetscErrorCode TaoParametersInitialize(Tao tao)
90 {
91   PetscObjectParameterSetDefault(tao, max_it, 10000);
92   PetscObjectParameterSetDefault(tao, max_funcs, PETSC_UNLIMITED);
93   PetscObjectParameterSetDefault(tao, gatol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
94   PetscObjectParameterSetDefault(tao, grtol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
95   PetscObjectParameterSetDefault(tao, crtol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
96   PetscObjectParameterSetDefault(tao, catol, PetscDefined(USE_REAL_SINGLE) ? 1e-5 : 1e-8);
97   PetscObjectParameterSetDefault(tao, gttol, 0.0);
98   PetscObjectParameterSetDefault(tao, steptol, 0.0);
99   PetscObjectParameterSetDefault(tao, fmin, PETSC_NINFINITY);
100   PetscObjectParameterSetDefault(tao, trust0, PETSC_INFINITY);
101   return PETSC_SUCCESS;
102 }
103 
104 /*@
105   TaoCreate - Creates a Tao solver
106 
107   Collective
108 
109   Input Parameter:
110 . comm - MPI communicator
111 
112   Output Parameter:
113 . newtao - the new `Tao` context
114 
115   Options Database Key:
116 . -tao_type - select which method Tao should use
117 
118   Level: beginner
119 
120 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoDestroy()`, `TaoSetFromOptions()`, `TaoSetType()`
121 @*/
122 PetscErrorCode TaoCreate(MPI_Comm comm, Tao *newtao)
123 {
124   Tao tao;
125 
126   PetscFunctionBegin;
127   PetscAssertPointer(newtao, 2);
128   PetscCall(TaoInitializePackage());
129   PetscCall(TaoLineSearchInitializePackage());
130 
131   PetscCall(PetscHeaderCreate(tao, TAO_CLASSID, "Tao", "Optimization solver", "Tao", comm, TaoDestroy, TaoView));
132   tao->ops->convergencetest = TaoDefaultConvergenceTest;
133 
134   tao->hist_reset = PETSC_TRUE;
135   PetscCall(TaoResetStatistics(tao));
136   *newtao = tao;
137   PetscFunctionReturn(PETSC_SUCCESS);
138 }
139 
140 /*@
141   TaoSolve - Solves an optimization problem min F(x) s.t. l <= x <= u
142 
143   Collective
144 
145   Input Parameter:
146 . tao - the `Tao` context
147 
148   Level: beginner
149 
150   Notes:
151   The user must set up the `Tao` object  with calls to `TaoSetSolution()`, `TaoSetObjective()`, `TaoSetGradient()`, and (if using 2nd order method) `TaoSetHessian()`.
152 
153   You should call `TaoGetConvergedReason()` or run with `-tao_converged_reason` to determine if the optimization algorithm actually succeeded or
154   why it failed.
155 
156 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoGetConvergedReason()`, `TaoSetUp()`
157  @*/
158 PetscErrorCode TaoSolve(Tao tao)
159 {
160   static PetscBool set = PETSC_FALSE;
161 
162   PetscFunctionBegin;
163   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
164   PetscCall(PetscCitationsRegister("@TechReport{tao-user-ref,\n"
165                                    "title   = {Toolkit for Advanced Optimization (TAO) Users Manual},\n"
166                                    "author  = {Todd Munson and Jason Sarich and Stefan Wild and Steve Benson and Lois Curfman McInnes},\n"
167                                    "Institution = {Argonne National Laboratory},\n"
168                                    "Year   = 2014,\n"
169                                    "Number = {ANL/MCS-TM-322 - Revision 3.5},\n"
170                                    "url    = {https://www.mcs.anl.gov/research/projects/tao/}\n}\n",
171                                    &set));
172   tao->header_printed = PETSC_FALSE;
173   PetscCall(TaoSetUp(tao));
174   PetscCall(TaoResetStatistics(tao));
175   if (tao->linesearch) PetscCall(TaoLineSearchReset(tao->linesearch));
176 
177   PetscCall(PetscLogEventBegin(TAO_Solve, tao, 0, 0, 0));
178   PetscTryTypeMethod(tao, solve);
179   PetscCall(PetscLogEventEnd(TAO_Solve, tao, 0, 0, 0));
180 
181   PetscCall(VecViewFromOptions(tao->solution, (PetscObject)tao, "-tao_view_solution"));
182 
183   tao->ntotalits += tao->niter;
184 
185   if (tao->printreason) {
186     PetscViewer viewer = PETSC_VIEWER_STDOUT_(((PetscObject)tao)->comm);
187 
188     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)tao)->tablevel));
189     if (tao->reason > 0) {
190       if (((PetscObject)tao)->prefix) {
191         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix, TaoConvergedReasons[tao->reason], tao->niter));
192       } else {
193         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO solve converged due to %s iterations %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter));
194       }
195     } else {
196       if (((PetscObject)tao)->prefix) {
197         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO %s solve did not converge due to %s iteration %" PetscInt_FMT "\n", ((PetscObject)tao)->prefix, TaoConvergedReasons[tao->reason], tao->niter));
198       } else {
199         PetscCall(PetscViewerASCIIPrintf(viewer, "  TAO solve did not converge due to %s iteration %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter));
200       }
201     }
202     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)tao)->tablevel));
203   }
204   PetscCall(TaoViewFromOptions(tao, NULL, "-tao_view"));
205   PetscFunctionReturn(PETSC_SUCCESS);
206 }
207 
208 /*@
209   TaoSetUp - Sets up the internal data structures for the later use
210   of a Tao solver
211 
212   Collective
213 
214   Input Parameter:
215 . tao - the `Tao` context
216 
217   Level: advanced
218 
219   Note:
220   The user will not need to explicitly call `TaoSetUp()`, as it will
221   automatically be called in `TaoSolve()`.  However, if the user
222   desires to call it explicitly, it should come after `TaoCreate()`
223   and any TaoSetSomething() routines, but before `TaoSolve()`.
224 
225 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
226 @*/
227 PetscErrorCode TaoSetUp(Tao tao)
228 {
229   PetscFunctionBegin;
230   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
231   if (tao->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
232   PetscCall(TaoSetUpEW_Private(tao));
233   PetscCheck(tao->solution, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Must call TaoSetSolution");
234   PetscTryTypeMethod(tao, setup);
235   tao->setupcalled = PETSC_TRUE;
236   PetscFunctionReturn(PETSC_SUCCESS);
237 }
238 
239 /*@
240   TaoDestroy - Destroys the `Tao` context that was created with `TaoCreate()`
241 
242   Collective
243 
244   Input Parameter:
245 . tao - the `Tao` context
246 
247   Level: beginner
248 
249 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
250 @*/
251 PetscErrorCode TaoDestroy(Tao *tao)
252 {
253   PetscFunctionBegin;
254   if (!*tao) PetscFunctionReturn(PETSC_SUCCESS);
255   PetscValidHeaderSpecific(*tao, TAO_CLASSID, 1);
256   if (--((PetscObject)*tao)->refct > 0) {
257     *tao = NULL;
258     PetscFunctionReturn(PETSC_SUCCESS);
259   }
260 
261   PetscTryTypeMethod(*tao, destroy);
262   PetscCall(KSPDestroy(&(*tao)->ksp));
263   PetscCall(SNESDestroy(&(*tao)->snes_ewdummy));
264   PetscCall(TaoLineSearchDestroy(&(*tao)->linesearch));
265 
266   if ((*tao)->ops->convergencedestroy) {
267     PetscCall((*(*tao)->ops->convergencedestroy)((*tao)->cnvP));
268     if ((*tao)->jacobian_state_inv) PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
269   }
270   PetscCall(VecDestroy(&(*tao)->solution));
271   PetscCall(VecDestroy(&(*tao)->gradient));
272   PetscCall(VecDestroy(&(*tao)->ls_res));
273 
274   if ((*tao)->gradient_norm) {
275     PetscCall(PetscObjectDereference((PetscObject)(*tao)->gradient_norm));
276     PetscCall(VecDestroy(&(*tao)->gradient_norm_tmp));
277   }
278 
279   PetscCall(VecDestroy(&(*tao)->XL));
280   PetscCall(VecDestroy(&(*tao)->XU));
281   PetscCall(VecDestroy(&(*tao)->IL));
282   PetscCall(VecDestroy(&(*tao)->IU));
283   PetscCall(VecDestroy(&(*tao)->DE));
284   PetscCall(VecDestroy(&(*tao)->DI));
285   PetscCall(VecDestroy(&(*tao)->constraints));
286   PetscCall(VecDestroy(&(*tao)->constraints_equality));
287   PetscCall(VecDestroy(&(*tao)->constraints_inequality));
288   PetscCall(VecDestroy(&(*tao)->stepdirection));
289   PetscCall(MatDestroy(&(*tao)->hessian_pre));
290   PetscCall(MatDestroy(&(*tao)->hessian));
291   PetscCall(MatDestroy(&(*tao)->ls_jac));
292   PetscCall(MatDestroy(&(*tao)->ls_jac_pre));
293   PetscCall(MatDestroy(&(*tao)->jacobian_pre));
294   PetscCall(MatDestroy(&(*tao)->jacobian));
295   PetscCall(MatDestroy(&(*tao)->jacobian_state_pre));
296   PetscCall(MatDestroy(&(*tao)->jacobian_state));
297   PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
298   PetscCall(MatDestroy(&(*tao)->jacobian_design));
299   PetscCall(MatDestroy(&(*tao)->jacobian_equality));
300   PetscCall(MatDestroy(&(*tao)->jacobian_equality_pre));
301   PetscCall(MatDestroy(&(*tao)->jacobian_inequality));
302   PetscCall(MatDestroy(&(*tao)->jacobian_inequality_pre));
303   PetscCall(ISDestroy(&(*tao)->state_is));
304   PetscCall(ISDestroy(&(*tao)->design_is));
305   PetscCall(VecDestroy(&(*tao)->res_weights_v));
306   PetscCall(TaoMonitorCancel(*tao));
307   if ((*tao)->hist_malloc) PetscCall(PetscFree4((*tao)->hist_obj, (*tao)->hist_resid, (*tao)->hist_cnorm, (*tao)->hist_lits));
308   if ((*tao)->res_weights_n) {
309     PetscCall(PetscFree((*tao)->res_weights_rows));
310     PetscCall(PetscFree((*tao)->res_weights_cols));
311     PetscCall(PetscFree((*tao)->res_weights_w));
312   }
313   PetscCall(PetscHeaderDestroy(tao));
314   PetscFunctionReturn(PETSC_SUCCESS);
315 }
316 
317 /*@
318   TaoKSPSetUseEW - Sets `SNES` to use Eisenstat-Walker method {cite}`ew96`for computing relative tolerance for linear solvers.
319 
320   Logically Collective
321 
322   Input Parameters:
323 + tao  - Tao context
324 - flag - `PETSC_TRUE` or `PETSC_FALSE`
325 
326   Level: advanced
327 
328   Note:
329   See `SNESKSPSetUseEW()` for customization details.
330 
331 .seealso: [](ch_tao), `Tao`, `SNESKSPSetUseEW()`
332 @*/
333 PetscErrorCode TaoKSPSetUseEW(Tao tao, PetscBool flag)
334 {
335   PetscFunctionBegin;
336   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
337   PetscValidLogicalCollectiveBool(tao, flag, 2);
338   tao->ksp_ewconv = flag;
339   PetscFunctionReturn(PETSC_SUCCESS);
340 }
341 
342 /*@
343   TaoSetFromOptions - Sets various Tao parameters from the options database
344 
345   Collective
346 
347   Input Parameter:
348 . tao - the `Tao` solver context
349 
350   Options Database Keys:
351 + -tao_type <type>             - The algorithm that Tao uses (lmvm, nls, etc.)
352 . -tao_gatol <gatol>           - absolute error tolerance for ||gradient||
353 . -tao_grtol <grtol>           - relative error tolerance for ||gradient||
354 . -tao_gttol <gttol>           - reduction of ||gradient|| relative to initial gradient
355 . -tao_max_it <max>            - sets maximum number of iterations
356 . -tao_max_funcs <max>         - sets maximum number of function evaluations
357 . -tao_fmin <fmin>             - stop if function value reaches fmin
358 . -tao_steptol <tol>           - stop if trust region radius less than <tol>
359 . -tao_trust0 <t>              - initial trust region radius
360 . -tao_view_solution           - view the solution at the end of the optimization process
361 . -tao_monitor                 - prints function value and residual norm at each iteration
362 . -tao_monitor_short           - same as `-tao_monitor`, but truncates very small values
363 . -tao_monitor_constraint_norm - prints objective value, gradient, and constraint norm at each iteration
364 . -tao_monitor_globalization   - prints information about the globalization at each iteration
365 . -tao_monitor_solution        - prints solution vector at each iteration
366 . -tao_monitor_ls_residual     - prints least-squares residual vector at each iteration
367 . -tao_monitor_step            - prints step vector at each iteration
368 . -tao_monitor_gradient        - prints gradient vector at each iteration
369 . -tao_monitor_solution_draw   - graphically view solution vector at each iteration
370 . -tao_monitor_step_draw       - graphically view step vector at each iteration
371 . -tao_monitor_gradient_draw   - graphically view gradient at each iteration
372 . -tao_monitor_cancel          - cancels all monitors (except those set with command line)
373 . -tao_fd_gradient             - use gradient computed with finite differences
374 . -tao_fd_hessian              - use hessian computed with finite differences
375 . -tao_mf_hessian              - use matrix-free Hessian computed with finite differences
376 . -tao_view                    - prints information about the Tao after solving
377 - -tao_converged_reason        - prints the reason Tao stopped iterating
378 
379   Level: beginner
380 
381   Note:
382   To see all options, run your program with the `-help` option or consult the
383   user's manual. Should be called after `TaoCreate()` but before `TaoSolve()`
384 
385 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
386 @*/
387 PetscErrorCode TaoSetFromOptions(Tao tao)
388 {
389   TaoType     default_type = TAOLMVM;
390   char        type[256], monfilename[PETSC_MAX_PATH_LEN];
391   PetscViewer monviewer;
392   PetscBool   flg, found;
393   MPI_Comm    comm;
394   PetscReal   catol, crtol, gatol, grtol, gttol;
395 
396   PetscFunctionBegin;
397   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
398   PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
399 
400   if (((PetscObject)tao)->type_name) default_type = ((PetscObject)tao)->type_name;
401 
402   PetscObjectOptionsBegin((PetscObject)tao);
403   /* Check for type from options */
404   PetscCall(PetscOptionsFList("-tao_type", "Tao Solver type", "TaoSetType", TaoList, default_type, type, 256, &flg));
405   if (flg) {
406     PetscCall(TaoSetType(tao, type));
407   } else if (!((PetscObject)tao)->type_name) {
408     PetscCall(TaoSetType(tao, default_type));
409   }
410 
411   /* Tao solvers do not set the prefix, set it here if not yet done
412      We do it after SetType since solver may have been changed */
413   if (tao->linesearch) {
414     const char *prefix;
415     PetscCall(TaoLineSearchGetOptionsPrefix(tao->linesearch, &prefix));
416     if (!prefix) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, ((PetscObject)tao)->prefix));
417   }
418 
419   catol = tao->catol;
420   crtol = tao->crtol;
421   PetscCall(PetscOptionsReal("-tao_catol", "Stop if constraints violations within", "TaoSetConstraintTolerances", tao->catol, &catol, NULL));
422   PetscCall(PetscOptionsReal("-tao_crtol", "Stop if relative constraint violations within", "TaoSetConstraintTolerances", tao->crtol, &crtol, NULL));
423   PetscCall(TaoSetConstraintTolerances(tao, catol, crtol));
424 
425   gatol = tao->gatol;
426   grtol = tao->grtol;
427   gttol = tao->gttol;
428   PetscCall(PetscOptionsReal("-tao_gatol", "Stop if norm of gradient less than", "TaoSetTolerances", tao->gatol, &gatol, NULL));
429   PetscCall(PetscOptionsReal("-tao_grtol", "Stop if norm of gradient divided by the function value is less than", "TaoSetTolerances", tao->grtol, &grtol, NULL));
430   PetscCall(PetscOptionsReal("-tao_gttol", "Stop if the norm of the gradient is less than the norm of the initial gradient times tol", "TaoSetTolerances", tao->gttol, &gttol, NULL));
431   PetscCall(TaoSetTolerances(tao, gatol, grtol, gttol));
432 
433   PetscCall(PetscOptionsInt("-tao_max_it", "Stop if iteration number exceeds", "TaoSetMaximumIterations", tao->max_it, &tao->max_it, &flg));
434   if (flg) PetscCall(TaoSetMaximumIterations(tao, tao->max_it));
435 
436   PetscCall(PetscOptionsInt("-tao_max_funcs", "Stop if number of function evaluations exceeds", "TaoSetMaximumFunctionEvaluations", tao->max_funcs, &tao->max_funcs, &flg));
437   if (flg) PetscCall(TaoSetMaximumFunctionEvaluations(tao, tao->max_funcs));
438 
439   PetscCall(PetscOptionsReal("-tao_fmin", "Stop if function less than", "TaoSetFunctionLowerBound", tao->fmin, &tao->fmin, NULL));
440   PetscCall(PetscOptionsBoundedReal("-tao_steptol", "Stop if step size or trust region radius less than", "", tao->steptol, &tao->steptol, NULL, 0));
441   PetscCall(PetscOptionsReal("-tao_trust0", "Initial trust region radius", "TaoSetInitialTrustRegionRadius", tao->trust0, &tao->trust0, &flg));
442   if (flg) PetscCall(TaoSetInitialTrustRegionRadius(tao, tao->trust0));
443 
444   PetscCall(PetscOptionsDeprecated("-tao_solution_monitor", "-tao_monitor_solution", "3.21", NULL));
445   PetscCall(PetscOptionsDeprecated("-tao_gradient_monitor", "-tao_monitor_gradient", "3.21", NULL));
446   PetscCall(PetscOptionsDeprecated("-tao_stepdirection_monitor", "-tao_monitor_step", "3.21", NULL));
447   PetscCall(PetscOptionsDeprecated("-tao_residual_monitor", "-tao_monitor_residual", "3.21", NULL));
448   PetscCall(PetscOptionsDeprecated("-tao_smonitor", "-tao_monitor_short", "3.21", NULL));
449   PetscCall(PetscOptionsDeprecated("-tao_cmonitor", "-tao_monitor_constraint_norm", "3.21", NULL));
450   PetscCall(PetscOptionsDeprecated("-tao_gmonitor", "-tao_monitor_globalization", "3.21", NULL));
451   PetscCall(PetscOptionsDeprecated("-tao_draw_solution", "-tao_monitor_solution_draw", "3.21", NULL));
452   PetscCall(PetscOptionsDeprecated("-tao_draw_gradient", "-tao_monitor_gradient_draw", "3.21", NULL));
453   PetscCall(PetscOptionsDeprecated("-tao_draw_step", "-tao_monitor_step_draw", "3.21", NULL));
454 
455   PetscCall(PetscOptionsString("-tao_monitor_solution", "View solution vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
456   if (flg) {
457     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
458     PetscCall(TaoMonitorSet(tao, TaoMonitorSolution, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
459   }
460 
461   PetscCall(PetscOptionsBool("-tao_converged_reason", "Print reason for Tao converged", "TaoSolve", tao->printreason, &tao->printreason, NULL));
462   PetscCall(PetscOptionsString("-tao_monitor_gradient", "View gradient vector for each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
463   if (flg) {
464     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
465     PetscCall(TaoMonitorSet(tao, TaoMonitorGradient, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
466   }
467 
468   PetscCall(PetscOptionsString("-tao_monitor_step", "View step vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
469   if (flg) {
470     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
471     PetscCall(TaoMonitorSet(tao, TaoMonitorStep, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
472   }
473 
474   PetscCall(PetscOptionsString("-tao_monitor_residual", "View least-squares residual vector after each iteration", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
475   if (flg) {
476     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
477     PetscCall(TaoMonitorSet(tao, TaoMonitorResidual, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
478   }
479 
480   PetscCall(PetscOptionsString("-tao_monitor", "Use the default convergence monitor", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
481   if (flg) {
482     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
483     PetscCall(TaoMonitorSet(tao, TaoMonitorDefault, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
484   }
485 
486   PetscCall(PetscOptionsString("-tao_monitor_globalization", "Use the convergence monitor with extra globalization info", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
487   if (flg) {
488     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
489     PetscCall(TaoMonitorSet(tao, TaoMonitorGlobalization, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
490   }
491 
492   PetscCall(PetscOptionsString("-tao_monitor_short", "Use the short convergence monitor", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
493   if (flg) {
494     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
495     PetscCall(TaoMonitorSet(tao, TaoMonitorDefaultShort, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
496   }
497 
498   PetscCall(PetscOptionsString("-tao_monitor_constraint_norm", "Use the default convergence monitor with constraint norm", "TaoMonitorSet", "stdout", monfilename, sizeof(monfilename), &flg));
499   if (flg) {
500     PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
501     PetscCall(TaoMonitorSet(tao, TaoMonitorConstraintNorm, monviewer, (PetscCtxDestroyFn *)PetscViewerDestroy));
502   }
503 
504   flg = PETSC_FALSE;
505   PetscCall(PetscOptionsDeprecated("-tao_cancelmonitors", "-tao_monitor_cancel", "3.21", NULL));
506   PetscCall(PetscOptionsBool("-tao_monitor_cancel", "cancel all monitors and call any registered destroy routines", "TaoMonitorCancel", flg, &flg, NULL));
507   if (flg) PetscCall(TaoMonitorCancel(tao));
508 
509   flg = PETSC_FALSE;
510   PetscCall(PetscOptionsBool("-tao_monitor_solution_draw", "Plot solution vector at each iteration", "TaoMonitorSet", flg, &flg, NULL));
511   if (flg) {
512     TaoMonitorDrawCtx drawctx;
513     PetscInt          howoften = 1;
514     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
515     PetscCall(TaoMonitorSet(tao, TaoMonitorSolutionDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
516   }
517 
518   flg = PETSC_FALSE;
519   PetscCall(PetscOptionsBool("-tao_monitor_step_draw", "Plots step at each iteration", "TaoMonitorSet", flg, &flg, NULL));
520   if (flg) PetscCall(TaoMonitorSet(tao, TaoMonitorStepDraw, NULL, NULL));
521 
522   flg = PETSC_FALSE;
523   PetscCall(PetscOptionsBool("-tao_monitor_gradient_draw", "plots gradient at each iteration", "TaoMonitorSet", flg, &flg, NULL));
524   if (flg) {
525     TaoMonitorDrawCtx drawctx;
526     PetscInt          howoften = 1;
527     PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
528     PetscCall(TaoMonitorSet(tao, TaoMonitorGradientDraw, drawctx, (PetscCtxDestroyFn *)TaoMonitorDrawCtxDestroy));
529   }
530   flg = PETSC_FALSE;
531   PetscCall(PetscOptionsBool("-tao_fd_gradient", "compute gradient using finite differences", "TaoDefaultComputeGradient", flg, &flg, NULL));
532   if (flg) PetscCall(TaoSetGradient(tao, NULL, TaoDefaultComputeGradient, NULL));
533   flg = PETSC_FALSE;
534   PetscCall(PetscOptionsBool("-tao_fd_hessian", "compute Hessian using finite differences", "TaoDefaultComputeHessian", flg, &flg, NULL));
535   if (flg) {
536     Mat H;
537 
538     PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
539     PetscCall(MatSetType(H, MATAIJ));
540     PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessian, NULL));
541     PetscCall(MatDestroy(&H));
542   }
543   flg = PETSC_FALSE;
544   PetscCall(PetscOptionsBool("-tao_mf_hessian", "compute matrix-free Hessian using finite differences", "TaoDefaultComputeHessianMFFD", flg, &flg, NULL));
545   if (flg) {
546     Mat H;
547 
548     PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
549     PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessianMFFD, NULL));
550     PetscCall(MatDestroy(&H));
551   }
552   PetscCall(PetscOptionsBool("-tao_recycle_history", "enable recycling/re-using information from the previous TaoSolve() call for some algorithms", "TaoSetRecycleHistory", flg, &flg, &found));
553   if (found) PetscCall(TaoSetRecycleHistory(tao, flg));
554   PetscCall(PetscOptionsEnum("-tao_subset_type", "subset type", "", TaoSubSetTypes, (PetscEnum)tao->subset_type, (PetscEnum *)&tao->subset_type, NULL));
555 
556   if (tao->ksp) {
557     PetscCall(PetscOptionsBool("-tao_ksp_ew", "Use Eisentat-Walker linear system convergence test", "TaoKSPSetUseEW", tao->ksp_ewconv, &tao->ksp_ewconv, NULL));
558     PetscCall(TaoKSPSetUseEW(tao, tao->ksp_ewconv));
559   }
560 
561   PetscTryTypeMethod(tao, setfromoptions, PetscOptionsObject);
562 
563   /* process any options handlers added with PetscObjectAddOptionsHandler() */
564   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)tao, PetscOptionsObject));
565   PetscOptionsEnd();
566 
567   if (tao->linesearch) PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
568   PetscFunctionReturn(PETSC_SUCCESS);
569 }
570 
571 /*@
572   TaoViewFromOptions - View a `Tao` object based on values in the options database
573 
574   Collective
575 
576   Input Parameters:
577 + A    - the  `Tao` context
578 . obj  - Optional object that provides the prefix for the options database
579 - name - command line option
580 
581   Level: intermediate
582 
583 .seealso: [](ch_tao), `Tao`, `TaoView`, `PetscObjectViewFromOptions()`, `TaoCreate()`
584 @*/
585 PetscErrorCode TaoViewFromOptions(Tao A, PetscObject obj, const char name[])
586 {
587   PetscFunctionBegin;
588   PetscValidHeaderSpecific(A, TAO_CLASSID, 1);
589   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
590   PetscFunctionReturn(PETSC_SUCCESS);
591 }
592 
593 /*@
594   TaoView - Prints information about the `Tao` object
595 
596   Collective
597 
598   Input Parameters:
599 + tao    - the `Tao` context
600 - viewer - visualization context
601 
602   Options Database Key:
603 . -tao_view - Calls `TaoView()` at the end of `TaoSolve()`
604 
605   Level: beginner
606 
607   Notes:
608   The available visualization contexts include
609 +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
610 -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
611   output where only the first processor opens
612   the file.  All other processors send their
613   data to the first processor to print.
614 
615 .seealso: [](ch_tao), `Tao`, `PetscViewerASCIIOpen()`
616 @*/
617 PetscErrorCode TaoView(Tao tao, PetscViewer viewer)
618 {
619   PetscBool isascii, isstring;
620   TaoType   type;
621 
622   PetscFunctionBegin;
623   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
624   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)tao)->comm, &viewer));
625   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
626   PetscCheckSameComm(tao, 1, viewer, 2);
627 
628   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
629   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
630   if (isascii) {
631     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)tao, viewer));
632 
633     PetscCall(PetscViewerASCIIPushTab(viewer));
634     PetscTryTypeMethod(tao, view, viewer);
635     if (tao->linesearch) PetscCall(TaoLineSearchView(tao->linesearch, viewer));
636     if (tao->ksp) {
637       PetscCall(KSPView(tao->ksp, viewer));
638       PetscCall(PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", tao->ksp_tot_its));
639     }
640 
641     if (tao->XL || tao->XU) PetscCall(PetscViewerASCIIPrintf(viewer, "Active Set subset type: %s\n", TaoSubSetTypes[tao->subset_type]));
642 
643     PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: gatol=%g,", (double)tao->gatol));
644     PetscCall(PetscViewerASCIIPrintf(viewer, " grtol=%g,", (double)tao->grtol));
645     PetscCall(PetscViewerASCIIPrintf(viewer, " steptol=%g,", (double)tao->steptol));
646     PetscCall(PetscViewerASCIIPrintf(viewer, " gttol=%g\n", (double)tao->gttol));
647     PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Function/Gradient:=%g\n", (double)tao->residual));
648 
649     if (tao->constrained) {
650       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances:"));
651       PetscCall(PetscViewerASCIIPrintf(viewer, " catol=%g,", (double)tao->catol));
652       PetscCall(PetscViewerASCIIPrintf(viewer, " crtol=%g\n", (double)tao->crtol));
653       PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Constraints:=%g\n", (double)tao->cnorm));
654     }
655 
656     if (tao->trust < tao->steptol) {
657       PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: steptol=%g\n", (double)tao->steptol));
658       PetscCall(PetscViewerASCIIPrintf(viewer, "Final trust region radius:=%g\n", (double)tao->trust));
659     }
660 
661     if (tao->fmin > -1.e25) PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: function minimum=%g\n", (double)tao->fmin));
662     PetscCall(PetscViewerASCIIPrintf(viewer, "Objective value=%g\n", (double)tao->fc));
663 
664     PetscCall(PetscViewerASCIIPrintf(viewer, "total number of iterations=%" PetscInt_FMT ",          ", tao->niter));
665     PetscCall(PetscViewerASCIIPrintf(viewer, "              (max: %" PetscInt_FMT ")\n", tao->max_it));
666 
667     if (tao->nfuncs > 0) {
668       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT ",", tao->nfuncs));
669       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: unlimited)\n"));
670       else PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: %" PetscInt_FMT ")\n", tao->max_funcs));
671     }
672     if (tao->ngrads > 0) {
673       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT ",", tao->ngrads));
674       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: unlimited)\n"));
675       else PetscCall(PetscViewerASCIIPrintf(viewer, "                (max: %" PetscInt_FMT ")\n", tao->max_funcs));
676     }
677     if (tao->nfuncgrads > 0) {
678       PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT ",", tao->nfuncgrads));
679       if (tao->max_funcs == PETSC_UNLIMITED) PetscCall(PetscViewerASCIIPrintf(viewer, "    (max: unlimited)\n"));
680       else PetscCall(PetscViewerASCIIPrintf(viewer, "    (max: %" PetscInt_FMT ")\n", tao->max_funcs));
681     }
682     if (tao->nhess > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", tao->nhess));
683     if (tao->nconstraints > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of constraint function evaluations=%" PetscInt_FMT "\n", tao->nconstraints));
684     if (tao->njac > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Jacobian evaluations=%" PetscInt_FMT "\n", tao->njac));
685 
686     if (tao->reason > 0) {
687       PetscCall(PetscViewerASCIIPrintf(viewer, "Solution converged: "));
688       switch (tao->reason) {
689       case TAO_CONVERGED_GATOL:
690         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)|| <= gatol\n"));
691         break;
692       case TAO_CONVERGED_GRTOL:
693         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/|f(X)| <= grtol\n"));
694         break;
695       case TAO_CONVERGED_GTTOL:
696         PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/||g(X0)|| <= gttol\n"));
697         break;
698       case TAO_CONVERGED_STEPTOL:
699         PetscCall(PetscViewerASCIIPrintf(viewer, " Steptol -- step size small\n"));
700         break;
701       case TAO_CONVERGED_MINF:
702         PetscCall(PetscViewerASCIIPrintf(viewer, " Minf --  f < fmin\n"));
703         break;
704       case TAO_CONVERGED_USER:
705         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
706         break;
707       default:
708         PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
709         break;
710       }
711     } else if (tao->reason == TAO_CONTINUE_ITERATING) {
712       PetscCall(PetscViewerASCIIPrintf(viewer, "Solver never run\n"));
713     } else {
714       PetscCall(PetscViewerASCIIPrintf(viewer, "Solver failed: "));
715       switch (tao->reason) {
716       case TAO_DIVERGED_MAXITS:
717         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Iterations\n"));
718         break;
719       case TAO_DIVERGED_NAN:
720         PetscCall(PetscViewerASCIIPrintf(viewer, " NAN or Inf encountered\n"));
721         break;
722       case TAO_DIVERGED_MAXFCN:
723         PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Function Evaluations\n"));
724         break;
725       case TAO_DIVERGED_LS_FAILURE:
726         PetscCall(PetscViewerASCIIPrintf(viewer, " Line Search Failure\n"));
727         break;
728       case TAO_DIVERGED_TR_REDUCTION:
729         PetscCall(PetscViewerASCIIPrintf(viewer, " Trust Region too small\n"));
730         break;
731       case TAO_DIVERGED_USER:
732         PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
733         break;
734       default:
735         PetscCall(PetscViewerASCIIPrintf(viewer, " %d\n", tao->reason));
736         break;
737       }
738     }
739     PetscCall(PetscViewerASCIIPopTab(viewer));
740   } else if (isstring) {
741     PetscCall(TaoGetType(tao, &type));
742     PetscCall(PetscViewerStringSPrintf(viewer, " %-3.3s", type));
743   }
744   PetscFunctionReturn(PETSC_SUCCESS);
745 }
746 
747 /*@
748   TaoSetRecycleHistory - Sets the boolean flag to enable/disable re-using
749   iterate information from the previous `TaoSolve()`. This feature is disabled by
750   default.
751 
752   Logically Collective
753 
754   Input Parameters:
755 + tao     - the `Tao` context
756 - recycle - boolean flag
757 
758   Options Database Key:
759 . -tao_recycle_history <true,false> - reuse the history
760 
761   Level: intermediate
762 
763   Notes:
764   For conjugate gradient methods (`TAOBNCG`), this re-uses the latest search direction
765   from the previous `TaoSolve()` call when computing the first search direction in a
766   new solution. By default, CG methods set the first search direction to the
767   negative gradient.
768 
769   For quasi-Newton family of methods (`TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`), this re-uses
770   the accumulated quasi-Newton Hessian approximation from the previous `TaoSolve()`
771   call. By default, QN family of methods reset the initial Hessian approximation to
772   the identity matrix.
773 
774   For any other algorithm, this setting has no effect.
775 
776 .seealso: [](ch_tao), `Tao`, `TaoGetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
777 @*/
778 PetscErrorCode TaoSetRecycleHistory(Tao tao, PetscBool recycle)
779 {
780   PetscFunctionBegin;
781   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
782   PetscValidLogicalCollectiveBool(tao, recycle, 2);
783   tao->recycle = recycle;
784   PetscFunctionReturn(PETSC_SUCCESS);
785 }
786 
787 /*@
788   TaoGetRecycleHistory - Retrieve the boolean flag for re-using iterate information
789   from the previous `TaoSolve()`. This feature is disabled by default.
790 
791   Logically Collective
792 
793   Input Parameter:
794 . tao - the `Tao` context
795 
796   Output Parameter:
797 . recycle - boolean flag
798 
799   Level: intermediate
800 
801 .seealso: [](ch_tao), `Tao`, `TaoSetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
802 @*/
803 PetscErrorCode TaoGetRecycleHistory(Tao tao, PetscBool *recycle)
804 {
805   PetscFunctionBegin;
806   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
807   PetscAssertPointer(recycle, 2);
808   *recycle = tao->recycle;
809   PetscFunctionReturn(PETSC_SUCCESS);
810 }
811 
812 /*@
813   TaoSetTolerances - Sets parameters used in `TaoSolve()` convergence tests
814 
815   Logically Collective
816 
817   Input Parameters:
818 + tao   - the `Tao` context
819 . gatol - stop if norm of gradient is less than this
820 . grtol - stop if relative norm of gradient is less than this
821 - gttol - stop if norm of gradient is reduced by this factor
822 
823   Options Database Keys:
824 + -tao_gatol <gatol> - Sets gatol
825 . -tao_grtol <grtol> - Sets grtol
826 - -tao_gttol <gttol> - Sets gttol
827 
828   Stopping Criteria\:
829 .vb
830   ||g(X)||                            <= gatol
831   ||g(X)|| / |f(X)|                   <= grtol
832   ||g(X)|| / ||g(X0)||                <= gttol
833 .ve
834 
835   Level: beginner
836 
837   Notes:
838   Use `PETSC_CURRENT` to leave one or more tolerances unchanged.
839 
840   Use `PETSC_DETERMINE` to set one or more tolerances to their values when the `tao`object's type was set
841 
842   Fortran Note:
843   Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`
844 
845 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`
846 @*/
847 PetscErrorCode TaoSetTolerances(Tao tao, PetscReal gatol, PetscReal grtol, PetscReal gttol)
848 {
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
851   PetscValidLogicalCollectiveReal(tao, gatol, 2);
852   PetscValidLogicalCollectiveReal(tao, grtol, 3);
853   PetscValidLogicalCollectiveReal(tao, gttol, 4);
854 
855   if (gatol == (PetscReal)PETSC_DETERMINE) {
856     tao->gatol = tao->default_gatol;
857   } else if (gatol != (PetscReal)PETSC_CURRENT) {
858     PetscCheck(gatol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gatol not allowed");
859     tao->gatol = gatol;
860   }
861 
862   if (grtol == (PetscReal)PETSC_DETERMINE) {
863     tao->grtol = tao->default_grtol;
864   } else if (grtol != (PetscReal)PETSC_CURRENT) {
865     PetscCheck(grtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative grtol not allowed");
866     tao->grtol = grtol;
867   }
868 
869   if (gttol == (PetscReal)PETSC_DETERMINE) {
870     tao->gttol = tao->default_gttol;
871   } else if (gttol != (PetscReal)PETSC_CURRENT) {
872     PetscCheck(gttol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative gttol not allowed");
873     tao->gttol = gttol;
874   }
875   PetscFunctionReturn(PETSC_SUCCESS);
876 }
877 
878 /*@
879   TaoSetConstraintTolerances - Sets constraint tolerance parameters used in `TaoSolve()` convergence tests
880 
881   Logically Collective
882 
883   Input Parameters:
884 + tao   - the `Tao` context
885 . catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for `gatol` convergence criteria
886 - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for `gatol`, `gttol` convergence criteria
887 
888   Options Database Keys:
889 + -tao_catol <catol> - Sets catol
890 - -tao_crtol <crtol> - Sets crtol
891 
892   Level: intermediate
893 
894   Notes:
895   Use `PETSC_CURRENT` to leave one or tolerance unchanged.
896 
897   Use `PETSC_DETERMINE` to set one or more tolerances to their values when the `tao` object's type was set
898 
899   Fortran Note:
900   Use `PETSC_CURRENT_REAL` or `PETSC_DETERMINE_REAL`
901 
902 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoGetConstraintTolerances()`, `TaoSetTolerances()`
903 @*/
904 PetscErrorCode TaoSetConstraintTolerances(Tao tao, PetscReal catol, PetscReal crtol)
905 {
906   PetscFunctionBegin;
907   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
908   PetscValidLogicalCollectiveReal(tao, catol, 2);
909   PetscValidLogicalCollectiveReal(tao, crtol, 3);
910 
911   if (catol == (PetscReal)PETSC_DETERMINE) {
912     tao->catol = tao->default_catol;
913   } else if (catol != (PetscReal)PETSC_CURRENT) {
914     PetscCheck(catol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative catol not allowed");
915     tao->catol = catol;
916   }
917 
918   if (crtol == (PetscReal)PETSC_DETERMINE) {
919     tao->crtol = tao->default_crtol;
920   } else if (crtol != (PetscReal)PETSC_CURRENT) {
921     PetscCheck(crtol >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Negative crtol not allowed");
922     tao->crtol = crtol;
923   }
924   PetscFunctionReturn(PETSC_SUCCESS);
925 }
926 
927 /*@
928   TaoGetConstraintTolerances - Gets constraint tolerance parameters used in `TaoSolve()` convergence tests
929 
930   Not Collective
931 
932   Input Parameter:
933 . tao - the `Tao` context
934 
935   Output Parameters:
936 + catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for `gatol` convergence criteria
937 - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for `gatol`, `gttol` convergence criteria
938 
939   Level: intermediate
940 
941 .seealso: [](ch_tao), `Tao`, `TaoConvergedReasons`,`TaoGetTolerances()`, `TaoSetTolerances()`, `TaoSetConstraintTolerances()`
942 @*/
943 PetscErrorCode TaoGetConstraintTolerances(Tao tao, PetscReal *catol, PetscReal *crtol)
944 {
945   PetscFunctionBegin;
946   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
947   if (catol) *catol = tao->catol;
948   if (crtol) *crtol = tao->crtol;
949   PetscFunctionReturn(PETSC_SUCCESS);
950 }
951 
952 /*@
953   TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
954   When an approximate solution with an objective value below this number
955   has been found, the solver will terminate.
956 
957   Logically Collective
958 
959   Input Parameters:
960 + tao  - the Tao solver context
961 - fmin - the tolerance
962 
963   Options Database Key:
964 . -tao_fmin <fmin> - sets the minimum function value
965 
966   Level: intermediate
967 
968 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetTolerances()`
969 @*/
970 PetscErrorCode TaoSetFunctionLowerBound(Tao tao, PetscReal fmin)
971 {
972   PetscFunctionBegin;
973   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
974   PetscValidLogicalCollectiveReal(tao, fmin, 2);
975   tao->fmin = fmin;
976   PetscFunctionReturn(PETSC_SUCCESS);
977 }
978 
979 /*@
980   TaoGetFunctionLowerBound - Gets the bound on the solution objective value.
981   When an approximate solution with an objective value below this number
982   has been found, the solver will terminate.
983 
984   Not Collective
985 
986   Input Parameter:
987 . tao - the `Tao` solver context
988 
989   Output Parameter:
990 . fmin - the minimum function value
991 
992   Level: intermediate
993 
994 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetFunctionLowerBound()`
995 @*/
996 PetscErrorCode TaoGetFunctionLowerBound(Tao tao, PetscReal *fmin)
997 {
998   PetscFunctionBegin;
999   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1000   PetscAssertPointer(fmin, 2);
1001   *fmin = tao->fmin;
1002   PetscFunctionReturn(PETSC_SUCCESS);
1003 }
1004 
1005 /*@
1006   TaoSetMaximumFunctionEvaluations - Sets a maximum number of function evaluations allowed for a `TaoSolve()`.
1007 
1008   Logically Collective
1009 
1010   Input Parameters:
1011 + tao  - the `Tao` solver context
1012 - nfcn - the maximum number of function evaluations (>=0), use `PETSC_UNLIMITED` to have no bound
1013 
1014   Options Database Key:
1015 . -tao_max_funcs <nfcn> - sets the maximum number of function evaluations
1016 
1017   Level: intermediate
1018 
1019   Note:
1020   Use `PETSC_DETERMINE` to use the default maximum number of function evaluations that was set when the object type was set.
1021 
1022   Developer Note:
1023   Deprecated support for an unlimited number of function evaluations by passing a negative value.
1024 
1025 .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumIterations()`
1026 @*/
1027 PetscErrorCode TaoSetMaximumFunctionEvaluations(Tao tao, PetscInt nfcn)
1028 {
1029   PetscFunctionBegin;
1030   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1031   PetscValidLogicalCollectiveInt(tao, nfcn, 2);
1032   if (nfcn == PETSC_DETERMINE) {
1033     tao->max_funcs = tao->default_max_funcs;
1034   } else if (nfcn == PETSC_UNLIMITED || nfcn < 0) {
1035     tao->max_funcs = PETSC_UNLIMITED;
1036   } else {
1037     PetscCheck(nfcn >= 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations  must be positive");
1038     tao->max_funcs = nfcn;
1039   }
1040   PetscFunctionReturn(PETSC_SUCCESS);
1041 }
1042 
1043 /*@
1044   TaoGetMaximumFunctionEvaluations - Gets a maximum number of function evaluations allowed for a `TaoSolve()`
1045 
1046   Logically Collective
1047 
1048   Input Parameter:
1049 . tao - the `Tao` solver context
1050 
1051   Output Parameter:
1052 . nfcn - the maximum number of function evaluations
1053 
1054   Level: intermediate
1055 
1056 .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1057 @*/
1058 PetscErrorCode TaoGetMaximumFunctionEvaluations(Tao tao, PetscInt *nfcn)
1059 {
1060   PetscFunctionBegin;
1061   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1062   PetscAssertPointer(nfcn, 2);
1063   *nfcn = tao->max_funcs;
1064   PetscFunctionReturn(PETSC_SUCCESS);
1065 }
1066 
1067 /*@
1068   TaoGetCurrentFunctionEvaluations - Get current number of function evaluations used by a `Tao` object
1069 
1070   Not Collective
1071 
1072   Input Parameter:
1073 . tao - the `Tao` solver context
1074 
1075   Output Parameter:
1076 . nfuncs - the current number of function evaluations (maximum between gradient and function evaluations)
1077 
1078   Level: intermediate
1079 
1080 .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1081 @*/
1082 PetscErrorCode TaoGetCurrentFunctionEvaluations(Tao tao, PetscInt *nfuncs)
1083 {
1084   PetscFunctionBegin;
1085   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1086   PetscAssertPointer(nfuncs, 2);
1087   *nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1088   PetscFunctionReturn(PETSC_SUCCESS);
1089 }
1090 
1091 /*@
1092   TaoSetMaximumIterations - Sets a maximum number of iterates to be used in `TaoSolve()`
1093 
1094   Logically Collective
1095 
1096   Input Parameters:
1097 + tao    - the `Tao` solver context
1098 - maxits - the maximum number of iterates (>=0), use `PETSC_UNLIMITED` to have no bound
1099 
1100   Options Database Key:
1101 . -tao_max_it <its> - sets the maximum number of iterations
1102 
1103   Level: intermediate
1104 
1105   Note:
1106   Use `PETSC_DETERMINE` to use the default maximum number of iterations that was set when the object's type was set.
1107 
1108   Developer Note:
1109   DeprAlso accepts the deprecated negative values to indicate no limit
1110 
1111 .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumFunctionEvaluations()`
1112 @*/
1113 PetscErrorCode TaoSetMaximumIterations(Tao tao, PetscInt maxits)
1114 {
1115   PetscFunctionBegin;
1116   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1117   PetscValidLogicalCollectiveInt(tao, maxits, 2);
1118   if (maxits == PETSC_DETERMINE) {
1119     tao->max_it = tao->default_max_it;
1120   } else if (maxits == PETSC_UNLIMITED) {
1121     tao->max_it = PETSC_INT_MAX;
1122   } else {
1123     PetscCheck(maxits > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations must be positive");
1124     tao->max_it = maxits;
1125   }
1126   PetscFunctionReturn(PETSC_SUCCESS);
1127 }
1128 
1129 /*@
1130   TaoGetMaximumIterations - Gets a maximum number of iterates that will be used
1131 
1132   Not Collective
1133 
1134   Input Parameter:
1135 . tao - the `Tao` solver context
1136 
1137   Output Parameter:
1138 . maxits - the maximum number of iterates
1139 
1140   Level: intermediate
1141 
1142 .seealso: [](ch_tao), `Tao`, `TaoSetMaximumIterations()`, `TaoGetMaximumFunctionEvaluations()`
1143 @*/
1144 PetscErrorCode TaoGetMaximumIterations(Tao tao, PetscInt *maxits)
1145 {
1146   PetscFunctionBegin;
1147   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1148   PetscAssertPointer(maxits, 2);
1149   *maxits = tao->max_it;
1150   PetscFunctionReturn(PETSC_SUCCESS);
1151 }
1152 
1153 /*@
1154   TaoSetInitialTrustRegionRadius - Sets the initial trust region radius.
1155 
1156   Logically Collective
1157 
1158   Input Parameters:
1159 + tao    - a `Tao` optimization solver
1160 - radius - the trust region radius
1161 
1162   Options Database Key:
1163 . -tao_trust0 <t0> - sets initial trust region radius
1164 
1165   Level: intermediate
1166 
1167   Note:
1168   Use `PETSC_DETERMINE` to use the default radius that was set when the object's type was set.
1169 
1170 .seealso: [](ch_tao), `Tao`, `TaoGetTrustRegionRadius()`, `TaoSetTrustRegionTolerance()`, `TAONTR`
1171 @*/
1172 PetscErrorCode TaoSetInitialTrustRegionRadius(Tao tao, PetscReal radius)
1173 {
1174   PetscFunctionBegin;
1175   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1176   PetscValidLogicalCollectiveReal(tao, radius, 2);
1177   if (radius == PETSC_DETERMINE) {
1178     tao->trust0 = tao->default_trust0;
1179   } else {
1180     PetscCheck(radius > 0, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_OUTOFRANGE, "Radius must be positive");
1181     tao->trust0 = radius;
1182   }
1183   PetscFunctionReturn(PETSC_SUCCESS);
1184 }
1185 
1186 /*@
1187   TaoGetInitialTrustRegionRadius - Gets the initial trust region radius.
1188 
1189   Not Collective
1190 
1191   Input Parameter:
1192 . tao - a `Tao` optimization solver
1193 
1194   Output Parameter:
1195 . radius - the trust region radius
1196 
1197   Level: intermediate
1198 
1199 .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetCurrentTrustRegionRadius()`, `TAONTR`
1200 @*/
1201 PetscErrorCode TaoGetInitialTrustRegionRadius(Tao tao, PetscReal *radius)
1202 {
1203   PetscFunctionBegin;
1204   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1205   PetscAssertPointer(radius, 2);
1206   *radius = tao->trust0;
1207   PetscFunctionReturn(PETSC_SUCCESS);
1208 }
1209 
1210 /*@
1211   TaoGetCurrentTrustRegionRadius - Gets the current trust region radius.
1212 
1213   Not Collective
1214 
1215   Input Parameter:
1216 . tao - a `Tao` optimization solver
1217 
1218   Output Parameter:
1219 . radius - the trust region radius
1220 
1221   Level: intermediate
1222 
1223 .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetInitialTrustRegionRadius()`, `TAONTR`
1224 @*/
1225 PetscErrorCode TaoGetCurrentTrustRegionRadius(Tao tao, PetscReal *radius)
1226 {
1227   PetscFunctionBegin;
1228   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1229   PetscAssertPointer(radius, 2);
1230   *radius = tao->trust;
1231   PetscFunctionReturn(PETSC_SUCCESS);
1232 }
1233 
1234 /*@
1235   TaoGetTolerances - gets the current values of some tolerances used for the convergence testing of `TaoSolve()`
1236 
1237   Not Collective
1238 
1239   Input Parameter:
1240 . tao - the `Tao` context
1241 
1242   Output Parameters:
1243 + gatol - stop if norm of gradient is less than this
1244 . grtol - stop if relative norm of gradient is less than this
1245 - gttol - stop if norm of gradient is reduced by a this factor
1246 
1247   Level: intermediate
1248 
1249   Note:
1250   `NULL` can be used as an argument if not all tolerances values are needed
1251 
1252 .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`
1253 @*/
1254 PetscErrorCode TaoGetTolerances(Tao tao, PetscReal *gatol, PetscReal *grtol, PetscReal *gttol)
1255 {
1256   PetscFunctionBegin;
1257   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1258   if (gatol) *gatol = tao->gatol;
1259   if (grtol) *grtol = tao->grtol;
1260   if (gttol) *gttol = tao->gttol;
1261   PetscFunctionReturn(PETSC_SUCCESS);
1262 }
1263 
1264 /*@
1265   TaoGetKSP - Gets the linear solver used by the optimization solver.
1266 
1267   Not Collective
1268 
1269   Input Parameter:
1270 . tao - the `Tao` solver
1271 
1272   Output Parameter:
1273 . ksp - the `KSP` linear solver used in the optimization solver
1274 
1275   Level: intermediate
1276 
1277 .seealso: [](ch_tao), `Tao`, `KSP`
1278 @*/
1279 PetscErrorCode TaoGetKSP(Tao tao, KSP *ksp)
1280 {
1281   PetscFunctionBegin;
1282   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1283   PetscAssertPointer(ksp, 2);
1284   *ksp = tao->ksp;
1285   PetscFunctionReturn(PETSC_SUCCESS);
1286 }
1287 
1288 /*@
1289   TaoGetLinearSolveIterations - Gets the total number of linear iterations
1290   used by the `Tao` solver
1291 
1292   Not Collective
1293 
1294   Input Parameter:
1295 . tao - the `Tao` context
1296 
1297   Output Parameter:
1298 . lits - number of linear iterations
1299 
1300   Level: intermediate
1301 
1302   Note:
1303   This counter is reset to zero for each successive call to `TaoSolve()`
1304 
1305 .seealso: [](ch_tao), `Tao`, `TaoGetKSP()`
1306 @*/
1307 PetscErrorCode TaoGetLinearSolveIterations(Tao tao, PetscInt *lits)
1308 {
1309   PetscFunctionBegin;
1310   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1311   PetscAssertPointer(lits, 2);
1312   *lits = tao->ksp_tot_its;
1313   PetscFunctionReturn(PETSC_SUCCESS);
1314 }
1315 
1316 /*@
1317   TaoGetLineSearch - Gets the line search used by the optimization solver.
1318 
1319   Not Collective
1320 
1321   Input Parameter:
1322 . tao - the `Tao` solver
1323 
1324   Output Parameter:
1325 . ls - the line search used in the optimization solver
1326 
1327   Level: intermediate
1328 
1329 .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`
1330 @*/
1331 PetscErrorCode TaoGetLineSearch(Tao tao, TaoLineSearch *ls)
1332 {
1333   PetscFunctionBegin;
1334   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1335   PetscAssertPointer(ls, 2);
1336   *ls = tao->linesearch;
1337   PetscFunctionReturn(PETSC_SUCCESS);
1338 }
1339 
1340 /*@
1341   TaoAddLineSearchCounts - Adds the number of function evaluations spent
1342   in the line search to the running total.
1343 
1344   Input Parameters:
1345 . tao - the `Tao` solver
1346 
1347   Level: developer
1348 
1349 .seealso: [](ch_tao), `Tao`, `TaoGetLineSearch()`, `TaoLineSearchApply()`
1350 @*/
1351 PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1352 {
1353   PetscBool flg;
1354   PetscInt  nfeval, ngeval, nfgeval;
1355 
1356   PetscFunctionBegin;
1357   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1358   if (tao->linesearch) {
1359     PetscCall(TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg));
1360     if (!flg) {
1361       PetscCall(TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval));
1362       tao->nfuncs += nfeval;
1363       tao->ngrads += ngeval;
1364       tao->nfuncgrads += nfgeval;
1365     }
1366   }
1367   PetscFunctionReturn(PETSC_SUCCESS);
1368 }
1369 
1370 /*@
1371   TaoGetSolution - Returns the vector with the current solution from the `Tao` object
1372 
1373   Not Collective
1374 
1375   Input Parameter:
1376 . tao - the `Tao` context
1377 
1378   Output Parameter:
1379 . X - the current solution
1380 
1381   Level: intermediate
1382 
1383   Note:
1384   The returned vector will be the same object that was passed into `TaoSetSolution()`
1385 
1386 .seealso: [](ch_tao), `Tao`, `TaoSetSolution()`, `TaoSolve()`
1387 @*/
1388 PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1389 {
1390   PetscFunctionBegin;
1391   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1392   PetscAssertPointer(X, 2);
1393   *X = tao->solution;
1394   PetscFunctionReturn(PETSC_SUCCESS);
1395 }
1396 
1397 /*@
1398   TaoResetStatistics - Initialize the statistics collected by the `Tao` object.
1399   These statistics include the iteration number, residual norms, and convergence status.
1400   This routine gets called before solving each optimization problem.
1401 
1402   Collective
1403 
1404   Input Parameter:
1405 . tao - the `Tao` context
1406 
1407   Level: developer
1408 
1409 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
1410 @*/
1411 PetscErrorCode TaoResetStatistics(Tao tao)
1412 {
1413   PetscFunctionBegin;
1414   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1415   tao->niter        = 0;
1416   tao->nfuncs       = 0;
1417   tao->nfuncgrads   = 0;
1418   tao->ngrads       = 0;
1419   tao->nhess        = 0;
1420   tao->njac         = 0;
1421   tao->nconstraints = 0;
1422   tao->ksp_its      = 0;
1423   tao->ksp_tot_its  = 0;
1424   tao->reason       = TAO_CONTINUE_ITERATING;
1425   tao->residual     = 0.0;
1426   tao->cnorm        = 0.0;
1427   tao->step         = 0.0;
1428   tao->lsflag       = PETSC_FALSE;
1429   if (tao->hist_reset) tao->hist_len = 0;
1430   PetscFunctionReturn(PETSC_SUCCESS);
1431 }
1432 
1433 /*@C
1434   TaoSetUpdate - Sets the general-purpose update function called
1435   at the beginning of every iteration of the optimization algorithm. Called after the new solution and the gradient
1436   is determined, but before the Hessian is computed (if applicable).
1437 
1438   Logically Collective
1439 
1440   Input Parameters:
1441 + tao  - The `Tao` solver
1442 . func - The function
1443 - ctx  - The update function context
1444 
1445   Calling sequence of `func`:
1446 + tao - The optimizer context
1447 . it  - The current iteration index
1448 - ctx - The update context
1449 
1450   Level: advanced
1451 
1452   Notes:
1453   Users can modify the gradient direction or any other vector associated to the specific solver used.
1454   The objective function value is always recomputed after a call to the update hook.
1455 
1456 .seealso: [](ch_tao), `Tao`, `TaoSolve()`
1457 @*/
1458 PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao tao, PetscInt it, void *ctx), void *ctx)
1459 {
1460   PetscFunctionBegin;
1461   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1462   tao->ops->update = func;
1463   tao->user_update = ctx;
1464   PetscFunctionReturn(PETSC_SUCCESS);
1465 }
1466 
1467 /*@C
1468   TaoSetConvergenceTest - Sets the function that is to be used to test
1469   for convergence of the iterative minimization solution.  The new convergence
1470   testing routine will replace Tao's default convergence test.
1471 
1472   Logically Collective
1473 
1474   Input Parameters:
1475 + tao  - the `Tao` object
1476 . conv - the routine to test for convergence
1477 - ctx  - [optional] context for private data for the convergence routine
1478         (may be `NULL`)
1479 
1480   Calling sequence of `conv`:
1481 + tao - the `Tao` object
1482 - ctx - [optional] convergence context
1483 
1484   Level: advanced
1485 
1486   Note:
1487   The new convergence testing routine should call `TaoSetConvergedReason()`.
1488 
1489 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoMonitorSet()`
1490 @*/
1491 PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao, void *), void *ctx)
1492 {
1493   PetscFunctionBegin;
1494   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1495   tao->ops->convergencetest = conv;
1496   tao->cnvP                 = ctx;
1497   PetscFunctionReturn(PETSC_SUCCESS);
1498 }
1499 
1500 /*@C
1501   TaoMonitorSet - Sets an additional function that is to be used at every
1502   iteration of the solver to display the iteration's
1503   progress.
1504 
1505   Logically Collective
1506 
1507   Input Parameters:
1508 + tao  - the `Tao` solver context
1509 . func - monitoring routine
1510 . ctx  - [optional] user-defined context for private data for the monitor routine (may be `NULL`)
1511 - dest - [optional] function to destroy the context when the `Tao` is destroyed, see `PetscCtxDestroyFn` for the calling sequence
1512 
1513   Calling sequence of `func`:
1514 + tao - the `Tao` solver context
1515 - ctx - [optional] monitoring context
1516 
1517   Level: intermediate
1518 
1519   Notes:
1520   See `TaoSetFromOptions()` for a monitoring options.
1521 
1522   Several different monitoring routines may be set by calling
1523   `TaoMonitorSet()` multiple times; all will be called in the
1524   order in which they were set.
1525 
1526   Fortran Notes:
1527   Only one monitor function may be set
1528 
1529 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoMonitorDefault()`, `TaoMonitorCancel()`, `TaoSetDestroyRoutine()`, `TaoView()`, `PetscCtxDestroyFn`
1530 @*/
1531 PetscErrorCode TaoMonitorSet(Tao tao, PetscErrorCode (*func)(Tao, void *), void *ctx, PetscCtxDestroyFn *dest)
1532 {
1533   PetscInt  i;
1534   PetscBool identical;
1535 
1536   PetscFunctionBegin;
1537   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1538   PetscCheck(tao->numbermonitors < MAXTAOMONITORS, PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Cannot attach another monitor -- max=%d", MAXTAOMONITORS);
1539 
1540   for (i = 0; i < tao->numbermonitors; i++) {
1541     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))func, ctx, dest, (PetscErrorCode (*)(void))tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical));
1542     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1543   }
1544   tao->monitor[tao->numbermonitors]        = func;
1545   tao->monitorcontext[tao->numbermonitors] = ctx;
1546   tao->monitordestroy[tao->numbermonitors] = dest;
1547   ++tao->numbermonitors;
1548   PetscFunctionReturn(PETSC_SUCCESS);
1549 }
1550 
1551 /*@
1552   TaoMonitorCancel - Clears all the monitor functions for a `Tao` object.
1553 
1554   Logically Collective
1555 
1556   Input Parameter:
1557 . tao - the `Tao` solver context
1558 
1559   Options Database Key:
1560 . -tao_monitor_cancel - cancels all monitors that have been hardwired
1561     into a code by calls to `TaoMonitorSet()`, but does not cancel those
1562     set via the options database
1563 
1564   Level: advanced
1565 
1566   Note:
1567   There is no way to clear one specific monitor from a `Tao` object.
1568 
1569 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1570 @*/
1571 PetscErrorCode TaoMonitorCancel(Tao tao)
1572 {
1573   PetscInt i;
1574 
1575   PetscFunctionBegin;
1576   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1577   for (i = 0; i < tao->numbermonitors; i++) {
1578     if (tao->monitordestroy[i]) PetscCall((*tao->monitordestroy[i])(&tao->monitorcontext[i]));
1579   }
1580   tao->numbermonitors = 0;
1581   PetscFunctionReturn(PETSC_SUCCESS);
1582 }
1583 
1584 /*@
1585   TaoMonitorDefault - Default routine for monitoring progress of `TaoSolve()`
1586 
1587   Collective
1588 
1589   Input Parameters:
1590 + tao - the `Tao` context
1591 - ctx - `PetscViewer` context or `NULL`
1592 
1593   Options Database Key:
1594 . -tao_monitor - turn on default monitoring
1595 
1596   Level: advanced
1597 
1598   Note:
1599   This monitor prints the function value and gradient
1600   norm at each iteration.
1601 
1602 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1603 @*/
1604 PetscErrorCode TaoMonitorDefault(Tao tao, void *ctx)
1605 {
1606   PetscInt    its, tabs;
1607   PetscReal   fct, gnorm;
1608   PetscViewer viewer = (PetscViewer)ctx;
1609 
1610   PetscFunctionBegin;
1611   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1612   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1613   its   = tao->niter;
1614   fct   = tao->fc;
1615   gnorm = tao->residual;
1616   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1617   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1618   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1619     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1620     tao->header_printed = PETSC_TRUE;
1621   }
1622   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1623   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1624   if (gnorm >= PETSC_INFINITY) {
1625     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf \n"));
1626   } else {
1627     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g \n", (double)gnorm));
1628   }
1629   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1630   PetscFunctionReturn(PETSC_SUCCESS);
1631 }
1632 
1633 /*@
1634   TaoMonitorGlobalization - Default routine for monitoring progress of `TaoSolve()` with extra detail on the globalization method.
1635 
1636   Collective
1637 
1638   Input Parameters:
1639 + tao - the `Tao` context
1640 - ctx - `PetscViewer` context or `NULL`
1641 
1642   Options Database Key:
1643 . -tao_monitor_globalization - turn on monitoring with globalization information
1644 
1645   Level: advanced
1646 
1647   Note:
1648   This monitor prints the function value and gradient norm at each
1649   iteration, as well as the step size and trust radius. Note that the
1650   step size and trust radius may be the same for some algorithms.
1651 
1652 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1653 @*/
1654 PetscErrorCode TaoMonitorGlobalization(Tao tao, void *ctx)
1655 {
1656   PetscInt    its, tabs;
1657   PetscReal   fct, gnorm, stp, tr;
1658   PetscViewer viewer = (PetscViewer)ctx;
1659 
1660   PetscFunctionBegin;
1661   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1662   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1663   its   = tao->niter;
1664   fct   = tao->fc;
1665   gnorm = tao->residual;
1666   stp   = tao->step;
1667   tr    = tao->trust;
1668   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1669   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1670   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1671     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1672     tao->header_printed = PETSC_TRUE;
1673   }
1674   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1675   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1676   if (gnorm >= PETSC_INFINITY) {
1677     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf,"));
1678   } else {
1679     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g,", (double)gnorm));
1680   }
1681   PetscCall(PetscViewerASCIIPrintf(viewer, "  Step: %g,  Trust: %g\n", (double)stp, (double)tr));
1682   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1683   PetscFunctionReturn(PETSC_SUCCESS);
1684 }
1685 
1686 /*@
1687   TaoMonitorDefaultShort - Routine for monitoring progress of `TaoSolve()` that displays fewer digits than `TaoMonitorDefault()`
1688 
1689   Collective
1690 
1691   Input Parameters:
1692 + tao - the `Tao` context
1693 - ctx - `PetscViewer` context of type `PETSCVIEWERASCII`
1694 
1695   Options Database Key:
1696 . -tao_monitor_short - turn on default short monitoring
1697 
1698   Level: advanced
1699 
1700   Note:
1701   Same as `TaoMonitorDefault()` except
1702   it prints fewer digits of the residual as the residual gets smaller.
1703   This is because the later digits are meaningless and are often
1704   different on different machines; by using this routine different
1705   machines will usually generate the same output.
1706 
1707 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1708 @*/
1709 PetscErrorCode TaoMonitorDefaultShort(Tao tao, void *ctx)
1710 {
1711   PetscInt    its, tabs;
1712   PetscReal   fct, gnorm;
1713   PetscViewer viewer = (PetscViewer)ctx;
1714 
1715   PetscFunctionBegin;
1716   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1717   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
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 = %3" PetscInt_FMT ",", its));
1724   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value %g,", (double)fct));
1725   if (gnorm >= PETSC_INFINITY) {
1726     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf \n"));
1727   } else if (gnorm > 1.e-6) {
1728     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm));
1729   } else if (gnorm > 1.e-11) {
1730     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-6 \n"));
1731   } else {
1732     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-11 \n"));
1733   }
1734   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1735   PetscFunctionReturn(PETSC_SUCCESS);
1736 }
1737 
1738 /*@
1739   TaoMonitorConstraintNorm - same as `TaoMonitorDefault()` except
1740   it prints the norm of the constraint function.
1741 
1742   Collective
1743 
1744   Input Parameters:
1745 + tao - the `Tao` context
1746 - ctx - `PetscViewer` context or `NULL`
1747 
1748   Options Database Key:
1749 . -tao_monitor_constraint_norm - monitor the constraints
1750 
1751   Level: advanced
1752 
1753 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1754 @*/
1755 PetscErrorCode TaoMonitorConstraintNorm(Tao tao, void *ctx)
1756 {
1757   PetscInt    its, tabs;
1758   PetscReal   fct, gnorm;
1759   PetscViewer viewer = (PetscViewer)ctx;
1760 
1761   PetscFunctionBegin;
1762   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1763   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1764   its   = tao->niter;
1765   fct   = tao->fc;
1766   gnorm = tao->residual;
1767   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1768   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1769   PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", its));
1770   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct));
1771   PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g ", (double)gnorm));
1772   PetscCall(PetscViewerASCIIPrintf(viewer, "  Constraint: %g \n", (double)tao->cnorm));
1773   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1774   PetscFunctionReturn(PETSC_SUCCESS);
1775 }
1776 
1777 /*@C
1778   TaoMonitorSolution - Views the solution at each iteration of `TaoSolve()`
1779 
1780   Collective
1781 
1782   Input Parameters:
1783 + tao - the `Tao` context
1784 - ctx - `PetscViewer` context or `NULL`
1785 
1786   Options Database Key:
1787 . -tao_monitor_solution - view the solution
1788 
1789   Level: advanced
1790 
1791 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1792 @*/
1793 PetscErrorCode TaoMonitorSolution(Tao tao, void *ctx)
1794 {
1795   PetscViewer viewer = (PetscViewer)ctx;
1796 
1797   PetscFunctionBegin;
1798   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1799   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1800   PetscCall(VecView(tao->solution, viewer));
1801   PetscFunctionReturn(PETSC_SUCCESS);
1802 }
1803 
1804 /*@C
1805   TaoMonitorGradient - Views the gradient at each iteration of `TaoSolve()`
1806 
1807   Collective
1808 
1809   Input Parameters:
1810 + tao - the `Tao` context
1811 - ctx - `PetscViewer` context or `NULL`
1812 
1813   Options Database Key:
1814 . -tao_monitor_gradient - view the gradient at each iteration
1815 
1816   Level: advanced
1817 
1818 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1819 @*/
1820 PetscErrorCode TaoMonitorGradient(Tao tao, void *ctx)
1821 {
1822   PetscViewer viewer = (PetscViewer)ctx;
1823 
1824   PetscFunctionBegin;
1825   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1826   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1827   PetscCall(VecView(tao->gradient, viewer));
1828   PetscFunctionReturn(PETSC_SUCCESS);
1829 }
1830 
1831 /*@C
1832   TaoMonitorStep - Views the step-direction at each iteration of `TaoSolve()`
1833 
1834   Collective
1835 
1836   Input Parameters:
1837 + tao - the `Tao` context
1838 - ctx - `PetscViewer` context or `NULL`
1839 
1840   Options Database Key:
1841 . -tao_monitor_step - view the step vector at each iteration
1842 
1843   Level: advanced
1844 
1845 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1846 @*/
1847 PetscErrorCode TaoMonitorStep(Tao tao, void *ctx)
1848 {
1849   PetscViewer viewer = (PetscViewer)ctx;
1850 
1851   PetscFunctionBegin;
1852   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1853   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1854   PetscCall(VecView(tao->stepdirection, viewer));
1855   PetscFunctionReturn(PETSC_SUCCESS);
1856 }
1857 
1858 /*@C
1859   TaoMonitorSolutionDraw - Plots the solution at each iteration of `TaoSolve()`
1860 
1861   Collective
1862 
1863   Input Parameters:
1864 + tao - the `Tao` context
1865 - ctx - `TaoMonitorDraw` context
1866 
1867   Options Database Key:
1868 . -tao_monitor_solution_draw - draw the solution at each iteration
1869 
1870   Level: advanced
1871 
1872   Note:
1873   The context created by `TaoMonitorDrawCtxCreate()`, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
1874   are passed to `TaoMonitorSet()` to monitor the solution graphically.
1875 
1876 .seealso: [](ch_tao), `Tao`, `TaoMonitorSolution()`, `TaoMonitorSet()`, `TaoMonitorGradientDraw()`, `TaoMonitorDrawCtxCreate()`,
1877           `TaoMonitorDrawCtxDestroy()`
1878 @*/
1879 PetscErrorCode TaoMonitorSolutionDraw(Tao tao, void *ctx)
1880 {
1881   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
1882 
1883   PetscFunctionBegin;
1884   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1885   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1886   PetscCall(VecView(tao->solution, ictx->viewer));
1887   PetscFunctionReturn(PETSC_SUCCESS);
1888 }
1889 
1890 /*@C
1891   TaoMonitorGradientDraw - Plots the gradient at each iteration of `TaoSolve()`
1892 
1893   Collective
1894 
1895   Input Parameters:
1896 + tao - the `Tao` context
1897 - ctx - `PetscViewer` context
1898 
1899   Options Database Key:
1900 . -tao_monitor_gradient_draw - draw the gradient at each iteration
1901 
1902   Level: advanced
1903 
1904 .seealso: [](ch_tao), `Tao`, `TaoMonitorGradient()`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw()`
1905 @*/
1906 PetscErrorCode TaoMonitorGradientDraw(Tao tao, void *ctx)
1907 {
1908   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
1909 
1910   PetscFunctionBegin;
1911   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1912   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1913   PetscCall(VecView(tao->gradient, ictx->viewer));
1914   PetscFunctionReturn(PETSC_SUCCESS);
1915 }
1916 
1917 /*@C
1918   TaoMonitorStepDraw - Plots the step direction at each iteration of `TaoSolve()`
1919 
1920   Collective
1921 
1922   Input Parameters:
1923 + tao - the `Tao` context
1924 - ctx - the `PetscViewer` context
1925 
1926   Options Database Key:
1927 . -tao_monitor_step_draw - draw the step direction at each iteration
1928 
1929   Level: advanced
1930 
1931 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw`
1932 @*/
1933 PetscErrorCode TaoMonitorStepDraw(Tao tao, void *ctx)
1934 {
1935   PetscViewer viewer = (PetscViewer)ctx;
1936 
1937   PetscFunctionBegin;
1938   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1939   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1940   PetscCall(VecView(tao->stepdirection, viewer));
1941   PetscFunctionReturn(PETSC_SUCCESS);
1942 }
1943 
1944 /*@C
1945   TaoMonitorResidual - Views the least-squares residual at each iteration of `TaoSolve()`
1946 
1947   Collective
1948 
1949   Input Parameters:
1950 + tao - the `Tao` context
1951 - ctx - the `PetscViewer` context or `NULL`
1952 
1953   Options Database Key:
1954 . -tao_monitor_ls_residual - view the residual at each iteration
1955 
1956   Level: advanced
1957 
1958 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1959 @*/
1960 PetscErrorCode TaoMonitorResidual(Tao tao, void *ctx)
1961 {
1962   PetscViewer viewer = (PetscViewer)ctx;
1963 
1964   PetscFunctionBegin;
1965   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1966   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1967   PetscCall(VecView(tao->ls_res, viewer));
1968   PetscFunctionReturn(PETSC_SUCCESS);
1969 }
1970 
1971 /*@
1972   TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
1973   or terminate.
1974 
1975   Collective
1976 
1977   Input Parameters:
1978 + tao   - the `Tao` context
1979 - dummy - unused dummy context
1980 
1981   Level: developer
1982 
1983   Notes:
1984   This routine checks the residual in the optimality conditions, the
1985   relative residual in the optimity conditions, the number of function
1986   evaluations, and the function value to test convergence.  Some
1987   solvers may use different convergence routines.
1988 
1989 .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
1990 @*/
1991 PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
1992 {
1993   PetscInt           niter = tao->niter, nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1994   PetscInt           max_funcs = tao->max_funcs;
1995   PetscReal          gnorm = tao->residual, gnorm0 = tao->gnorm0;
1996   PetscReal          f = tao->fc, steptol = tao->steptol, trradius = tao->step;
1997   PetscReal          gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
1998   PetscReal          catol = tao->catol, crtol = tao->crtol;
1999   PetscReal          fmin = tao->fmin, cnorm = tao->cnorm;
2000   TaoConvergedReason reason = tao->reason;
2001 
2002   PetscFunctionBegin;
2003   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2004   if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);
2005 
2006   if (PetscIsInfOrNanReal(f)) {
2007     PetscCall(PetscInfo(tao, "Failed to converged, function value is Inf or NaN\n"));
2008     reason = TAO_DIVERGED_NAN;
2009   } else if (f <= fmin && cnorm <= catol) {
2010     PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
2011     reason = TAO_CONVERGED_MINF;
2012   } else if (gnorm <= gatol && cnorm <= catol) {
2013     PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
2014     reason = TAO_CONVERGED_GATOL;
2015   } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
2016     PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
2017     reason = TAO_CONVERGED_GRTOL;
2018   } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
2019     PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
2020     reason = TAO_CONVERGED_GTTOL;
2021   } else if (max_funcs != PETSC_UNLIMITED && nfuncs > max_funcs) {
2022     PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
2023     reason = TAO_DIVERGED_MAXFCN;
2024   } else if (tao->lsflag != 0) {
2025     PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
2026     reason = TAO_DIVERGED_LS_FAILURE;
2027   } else if (trradius < steptol && niter > 0) {
2028     PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
2029     reason = TAO_CONVERGED_STEPTOL;
2030   } else if (niter >= tao->max_it) {
2031     PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
2032     reason = TAO_DIVERGED_MAXITS;
2033   } else {
2034     reason = TAO_CONTINUE_ITERATING;
2035   }
2036   tao->reason = reason;
2037   PetscFunctionReturn(PETSC_SUCCESS);
2038 }
2039 
2040 /*@
2041   TaoSetOptionsPrefix - Sets the prefix used for searching for all
2042   Tao options in the database.
2043 
2044   Logically Collective
2045 
2046   Input Parameters:
2047 + tao - the `Tao` context
2048 - p   - the prefix string to prepend to all Tao option requests
2049 
2050   Level: advanced
2051 
2052   Notes:
2053   A hyphen (-) must NOT be given at the beginning of the prefix name.
2054   The first character of all runtime options is AUTOMATICALLY the hyphen.
2055 
2056   For example, to distinguish between the runtime options for two
2057   different Tao solvers, one could call
2058 .vb
2059       TaoSetOptionsPrefix(tao1,"sys1_")
2060       TaoSetOptionsPrefix(tao2,"sys2_")
2061 .ve
2062 
2063   This would enable use of different options for each system, such as
2064 .vb
2065       -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2066       -sys2_tao_method lmvm  -sys2_tao_grtol 1.e-4
2067 .ve
2068 
2069 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2070 @*/
2071 PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2072 {
2073   PetscFunctionBegin;
2074   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2075   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2076   if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2077   if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2078   PetscFunctionReturn(PETSC_SUCCESS);
2079 }
2080 
2081 /*@
2082   TaoAppendOptionsPrefix - Appends to the prefix used for searching for all Tao options in the database.
2083 
2084   Logically Collective
2085 
2086   Input Parameters:
2087 + tao - the `Tao` solver context
2088 - p   - the prefix string to prepend to all `Tao` option requests
2089 
2090   Level: advanced
2091 
2092   Note:
2093   A hyphen (-) must NOT be given at the beginning of the prefix name.
2094   The first character of all runtime options is automatically the hyphen.
2095 
2096 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2097 @*/
2098 PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2099 {
2100   PetscFunctionBegin;
2101   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2102   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2103   if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2104   if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2105   PetscFunctionReturn(PETSC_SUCCESS);
2106 }
2107 
2108 /*@
2109   TaoGetOptionsPrefix - Gets the prefix used for searching for all
2110   Tao options in the database
2111 
2112   Not Collective
2113 
2114   Input Parameter:
2115 . tao - the `Tao` context
2116 
2117   Output Parameter:
2118 . p - pointer to the prefix string used is returned
2119 
2120   Level: advanced
2121 
2122 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2123 @*/
2124 PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2125 {
2126   PetscFunctionBegin;
2127   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2128   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2129   PetscFunctionReturn(PETSC_SUCCESS);
2130 }
2131 
2132 /*@
2133   TaoSetType - Sets the `TaoType` for the minimization solver.
2134 
2135   Collective
2136 
2137   Input Parameters:
2138 + tao  - the `Tao` solver context
2139 - type - a known method
2140 
2141   Options Database Key:
2142 . -tao_type <type> - Sets the method; use -help for a list
2143    of available methods (for instance, "-tao_type lmvm" or "-tao_type tron")
2144 
2145   Level: intermediate
2146 
2147 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2148 @*/
2149 PetscErrorCode TaoSetType(Tao tao, TaoType type)
2150 {
2151   PetscErrorCode (*create_xxx)(Tao);
2152   PetscBool issame;
2153 
2154   PetscFunctionBegin;
2155   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2156 
2157   PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2158   if (issame) PetscFunctionReturn(PETSC_SUCCESS);
2159 
2160   PetscCall(PetscFunctionListFind(TaoList, type, &create_xxx));
2161   PetscCheck(create_xxx, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Tao type %s", type);
2162 
2163   /* Destroy the existing solver information */
2164   PetscTryTypeMethod(tao, destroy);
2165   PetscCall(KSPDestroy(&tao->ksp));
2166   PetscCall(TaoLineSearchDestroy(&tao->linesearch));
2167 
2168   /* Reinitialize type-specific function pointers in TaoOps structure */
2169   tao->ops->setup          = NULL;
2170   tao->ops->computedual    = NULL;
2171   tao->ops->solve          = NULL;
2172   tao->ops->view           = NULL;
2173   tao->ops->setfromoptions = NULL;
2174   tao->ops->destroy        = NULL;
2175 
2176   tao->setupcalled = PETSC_FALSE;
2177 
2178   PetscCall((*create_xxx)(tao));
2179   PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2180   PetscFunctionReturn(PETSC_SUCCESS);
2181 }
2182 
2183 /*@C
2184   TaoRegister - Adds a method to the Tao package for minimization.
2185 
2186   Not Collective, No Fortran Support
2187 
2188   Input Parameters:
2189 + sname - name of a new user-defined solver
2190 - func  - routine to Create method context
2191 
2192   Example Usage:
2193 .vb
2194    TaoRegister("my_solver", MySolverCreate);
2195 .ve
2196 
2197   Then, your solver can be chosen with the procedural interface via
2198 $     TaoSetType(tao, "my_solver")
2199   or at runtime via the option
2200 $     -tao_type my_solver
2201 
2202   Level: advanced
2203 
2204   Note:
2205   `TaoRegister()` may be called multiple times to add several user-defined solvers.
2206 
2207 .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2208 @*/
2209 PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao))
2210 {
2211   PetscFunctionBegin;
2212   PetscCall(TaoInitializePackage());
2213   PetscCall(PetscFunctionListAdd(&TaoList, sname, func));
2214   PetscFunctionReturn(PETSC_SUCCESS);
2215 }
2216 
2217 /*@C
2218   TaoRegisterDestroy - Frees the list of minimization solvers that were
2219   registered by `TaoRegister()`.
2220 
2221   Not Collective
2222 
2223   Level: advanced
2224 
2225 .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2226 @*/
2227 PetscErrorCode TaoRegisterDestroy(void)
2228 {
2229   PetscFunctionBegin;
2230   PetscCall(PetscFunctionListDestroy(&TaoList));
2231   TaoRegisterAllCalled = PETSC_FALSE;
2232   PetscFunctionReturn(PETSC_SUCCESS);
2233 }
2234 
2235 /*@
2236   TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2237   at this time.
2238 
2239   Not Collective
2240 
2241   Input Parameter:
2242 . tao - the `Tao` context
2243 
2244   Output Parameter:
2245 . iter - iteration number
2246 
2247   Notes:
2248   For example, during the computation of iteration 2 this would return 1.
2249 
2250   Level: intermediate
2251 
2252 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2253 @*/
2254 PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2255 {
2256   PetscFunctionBegin;
2257   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2258   PetscAssertPointer(iter, 2);
2259   *iter = tao->niter;
2260   PetscFunctionReturn(PETSC_SUCCESS);
2261 }
2262 
2263 /*@
2264   TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2265   at this time.
2266 
2267   Not Collective
2268 
2269   Input Parameter:
2270 . tao - the `Tao` context
2271 
2272   Output Parameter:
2273 . value - the current value
2274 
2275   Level: intermediate
2276 
2277   Developer Notes:
2278   This is the 2-norm of the residual, we cannot use `TaoGetGradientNorm()` because that has
2279   a different meaning. For some reason `Tao` sometimes calls the gradient the residual.
2280 
2281 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2282 @*/
2283 PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2284 {
2285   PetscFunctionBegin;
2286   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2287   PetscAssertPointer(value, 2);
2288   *value = tao->residual;
2289   PetscFunctionReturn(PETSC_SUCCESS);
2290 }
2291 
2292 /*@
2293   TaoSetIterationNumber - Sets the current iteration number.
2294 
2295   Logically Collective
2296 
2297   Input Parameters:
2298 + tao  - the `Tao` context
2299 - iter - iteration number
2300 
2301   Level: developer
2302 
2303 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2304 @*/
2305 PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2306 {
2307   PetscFunctionBegin;
2308   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2309   PetscValidLogicalCollectiveInt(tao, iter, 2);
2310   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2311   tao->niter = iter;
2312   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2313   PetscFunctionReturn(PETSC_SUCCESS);
2314 }
2315 
2316 /*@
2317   TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2318   completed. This number keeps accumulating if multiple solves
2319   are called with the `Tao` object.
2320 
2321   Not Collective
2322 
2323   Input Parameter:
2324 . tao - the `Tao` context
2325 
2326   Output Parameter:
2327 . iter - number of iterations
2328 
2329   Level: intermediate
2330 
2331   Note:
2332   The total iteration count is updated after each solve, if there is a current
2333   `TaoSolve()` in progress then those iterations are not included in the count
2334 
2335 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2336 @*/
2337 PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2338 {
2339   PetscFunctionBegin;
2340   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2341   PetscAssertPointer(iter, 2);
2342   *iter = tao->ntotalits;
2343   PetscFunctionReturn(PETSC_SUCCESS);
2344 }
2345 
2346 /*@
2347   TaoSetTotalIterationNumber - Sets the current total iteration number.
2348 
2349   Logically Collective
2350 
2351   Input Parameters:
2352 + tao  - the `Tao` context
2353 - iter - the iteration number
2354 
2355   Level: developer
2356 
2357 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2358 @*/
2359 PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2360 {
2361   PetscFunctionBegin;
2362   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2363   PetscValidLogicalCollectiveInt(tao, iter, 2);
2364   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2365   tao->ntotalits = iter;
2366   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2367   PetscFunctionReturn(PETSC_SUCCESS);
2368 }
2369 
2370 /*@
2371   TaoSetConvergedReason - Sets the termination flag on a `Tao` object
2372 
2373   Logically Collective
2374 
2375   Input Parameters:
2376 + tao    - the `Tao` context
2377 - reason - the `TaoConvergedReason`
2378 
2379   Level: intermediate
2380 
2381 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2382 @*/
2383 PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2384 {
2385   PetscFunctionBegin;
2386   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2387   PetscValidLogicalCollectiveEnum(tao, reason, 2);
2388   tao->reason = reason;
2389   PetscFunctionReturn(PETSC_SUCCESS);
2390 }
2391 
2392 /*@
2393   TaoGetConvergedReason - Gets the reason the `TaoSolve()` was stopped.
2394 
2395   Not Collective
2396 
2397   Input Parameter:
2398 . tao - the `Tao` solver context
2399 
2400   Output Parameter:
2401 . reason - value of `TaoConvergedReason`
2402 
2403   Level: intermediate
2404 
2405 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`
2406 @*/
2407 PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2408 {
2409   PetscFunctionBegin;
2410   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2411   PetscAssertPointer(reason, 2);
2412   *reason = tao->reason;
2413   PetscFunctionReturn(PETSC_SUCCESS);
2414 }
2415 
2416 /*@
2417   TaoGetSolutionStatus - Get the current iterate, objective value,
2418   residual, infeasibility, and termination from a `Tao` object
2419 
2420   Not Collective
2421 
2422   Input Parameter:
2423 . tao - the `Tao` context
2424 
2425   Output Parameters:
2426 + its    - the current iterate number (>=0)
2427 . f      - the current function value
2428 . gnorm  - the square of the gradient norm, duality gap, or other measure indicating distance from optimality.
2429 . cnorm  - the infeasibility of the current solution with regard to the constraints.
2430 . xdiff  - the step length or trust region radius of the most recent iterate.
2431 - reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`
2432 
2433   Level: intermediate
2434 
2435   Notes:
2436   Tao returns the values set by the solvers in the routine `TaoMonitor()`.
2437 
2438   If any of the output arguments are set to `NULL`, no corresponding value will be returned.
2439 
2440 .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2441 @*/
2442 PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2443 {
2444   PetscFunctionBegin;
2445   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2446   if (its) *its = tao->niter;
2447   if (f) *f = tao->fc;
2448   if (gnorm) *gnorm = tao->residual;
2449   if (cnorm) *cnorm = tao->cnorm;
2450   if (reason) *reason = tao->reason;
2451   if (xdiff) *xdiff = tao->step;
2452   PetscFunctionReturn(PETSC_SUCCESS);
2453 }
2454 
2455 /*@
2456   TaoGetType - Gets the current `TaoType` being used in the `Tao` object
2457 
2458   Not Collective
2459 
2460   Input Parameter:
2461 . tao - the `Tao` solver context
2462 
2463   Output Parameter:
2464 . type - the `TaoType`
2465 
2466   Level: intermediate
2467 
2468 .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`
2469 @*/
2470 PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2471 {
2472   PetscFunctionBegin;
2473   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2474   PetscAssertPointer(type, 2);
2475   *type = ((PetscObject)tao)->type_name;
2476   PetscFunctionReturn(PETSC_SUCCESS);
2477 }
2478 
2479 /*@C
2480   TaoMonitor - Monitor the solver and the current solution.  This
2481   routine will record the iteration number and residual statistics,
2482   and call any monitors specified by the user.
2483 
2484   Input Parameters:
2485 + tao        - the `Tao` context
2486 . its        - the current iterate number (>=0)
2487 . f          - the current objective function value
2488 . res        - the gradient norm, square root of the duality gap, or other measure indicating distance from optimality.  This measure will be recorded and
2489           used for some termination tests.
2490 . cnorm      - the infeasibility of the current solution with regard to the constraints.
2491 - steplength - multiple of the step direction added to the previous iterate.
2492 
2493   Options Database Key:
2494 . -tao_monitor - Use the default monitor, which prints statistics to standard output
2495 
2496   Level: developer
2497 
2498 .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoMonitorSet()`
2499 @*/
2500 PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2501 {
2502   PetscInt i;
2503 
2504   PetscFunctionBegin;
2505   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2506   tao->fc       = f;
2507   tao->residual = res;
2508   tao->cnorm    = cnorm;
2509   tao->step     = steplength;
2510   if (!its) {
2511     tao->cnorm0 = cnorm;
2512     tao->gnorm0 = res;
2513   }
2514   PetscCall(VecLockReadPush(tao->solution));
2515   for (i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2516   PetscCall(VecLockReadPop(tao->solution));
2517   PetscFunctionReturn(PETSC_SUCCESS);
2518 }
2519 
2520 /*@
2521   TaoSetConvergenceHistory - Sets the array used to hold the convergence history.
2522 
2523   Logically Collective
2524 
2525   Input Parameters:
2526 + tao   - the `Tao` solver context
2527 . obj   - array to hold objective value history
2528 . resid - array to hold residual history
2529 . cnorm - array to hold constraint violation history
2530 . lits  - integer array holds the number of linear iterations for each Tao iteration
2531 . na    - size of `obj`, `resid`, and `cnorm`
2532 - reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2533            else it continues storing new values for new minimizations after the old ones
2534 
2535   Level: intermediate
2536 
2537   Notes:
2538   If set, `Tao` will fill the given arrays with the indicated
2539   information at each iteration.  If 'obj','resid','cnorm','lits' are
2540   *all* `NULL` then space (using size `na`, or 1000 if `na` is `PETSC_DECIDE`) is allocated for the history.
2541   If not all are `NULL`, then only the non-`NULL` information categories
2542   will be stored, the others will be ignored.
2543 
2544   Any convergence information after iteration number 'na' will not be stored.
2545 
2546   This routine is useful, e.g., when running a code for purposes
2547   of accurate performance monitoring, when no I/O should be done
2548   during the section of code that is being timed.
2549 
2550 .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2551 @*/
2552 PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2553 {
2554   PetscFunctionBegin;
2555   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2556   if (obj) PetscAssertPointer(obj, 2);
2557   if (resid) PetscAssertPointer(resid, 3);
2558   if (cnorm) PetscAssertPointer(cnorm, 4);
2559   if (lits) PetscAssertPointer(lits, 5);
2560 
2561   if (na == PETSC_DECIDE || na == PETSC_CURRENT) na = 1000;
2562   if (!obj && !resid && !cnorm && !lits) {
2563     PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2564     tao->hist_malloc = PETSC_TRUE;
2565   }
2566 
2567   tao->hist_obj   = obj;
2568   tao->hist_resid = resid;
2569   tao->hist_cnorm = cnorm;
2570   tao->hist_lits  = lits;
2571   tao->hist_max   = na;
2572   tao->hist_reset = reset;
2573   tao->hist_len   = 0;
2574   PetscFunctionReturn(PETSC_SUCCESS);
2575 }
2576 
2577 /*@C
2578   TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.
2579 
2580   Collective
2581 
2582   Input Parameter:
2583 . tao - the `Tao` context
2584 
2585   Output Parameters:
2586 + obj   - array used to hold objective value history
2587 . resid - array used to hold residual history
2588 . cnorm - array used to hold constraint violation history
2589 . lits  - integer array used to hold linear solver iteration count
2590 - nhist - size of `obj`, `resid`, `cnorm`, and `lits`
2591 
2592   Level: advanced
2593 
2594   Notes:
2595   This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2596   and `TaoSolve()`, otherwise it returns useless information.
2597 
2598   This routine is useful, e.g., when running a code for purposes
2599   of accurate performance monitoring, when no I/O should be done
2600   during the section of code that is being timed.
2601 
2602   Fortran Notes:
2603   The calling sequence is
2604 .vb
2605    call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2606 .ve
2607   In other words this gets the current number of entries in the history. Access the history through the array you passed to `TaoSetConvergenceHistory()`
2608 
2609 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2610 @*/
2611 PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2612 {
2613   PetscFunctionBegin;
2614   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2615   if (obj) *obj = tao->hist_obj;
2616   if (cnorm) *cnorm = tao->hist_cnorm;
2617   if (resid) *resid = tao->hist_resid;
2618   if (lits) *lits = tao->hist_lits;
2619   if (nhist) *nhist = tao->hist_len;
2620   PetscFunctionReturn(PETSC_SUCCESS);
2621 }
2622 
2623 /*@
2624   TaoSetApplicationContext - Sets the optional user-defined context for a `Tao` solver that can be accessed later, for example in the
2625   `Tao` callback functions with `TaoGetApplicationContext()`
2626 
2627   Logically Collective
2628 
2629   Input Parameters:
2630 + tao - the `Tao` context
2631 - ctx - the user context
2632 
2633   Level: intermediate
2634 
2635   Fortran Note:
2636   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
2637   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `TaoGetApplicationContext()` for
2638   an example.
2639 
2640 .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`
2641 @*/
2642 PetscErrorCode TaoSetApplicationContext(Tao tao, void *ctx)
2643 {
2644   PetscFunctionBegin;
2645   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2646   tao->ctx = ctx;
2647   PetscFunctionReturn(PETSC_SUCCESS);
2648 }
2649 
2650 /*@
2651   TaoGetApplicationContext - Gets the user-defined context for a `Tao` solver provided with `TaoSetApplicationContext()`
2652 
2653   Not Collective
2654 
2655   Input Parameter:
2656 . tao - the `Tao` context
2657 
2658   Output Parameter:
2659 . ctx - a pointer to the user context
2660 
2661   Level: intermediate
2662 
2663   Fortran Notes:
2664   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
2665   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
2666 .vb
2667   Interface TaoGetApplicationContext
2668     Subroutine TaoGetApplicationContext(tao,ctx,ierr)
2669   #include <petsc/finclude/petsctao.h>
2670       use petsctao
2671       Tao tao
2672       type(tUsertype), pointer :: ctx
2673       PetscErrorCode ierr
2674     End Subroutine
2675   End Interface TaoGetApplicationContext
2676 .ve
2677 
2678   The prototype for `ctx` must be
2679 .vb
2680   type(tUsertype), pointer :: ctx
2681 .ve
2682 
2683 .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2684 @*/
2685 PetscErrorCode TaoGetApplicationContext(Tao tao, PeCtx ctx)
2686 {
2687   PetscFunctionBegin;
2688   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2689   PetscAssertPointer(ctx, 2);
2690   *(void **)ctx = tao->ctx;
2691   PetscFunctionReturn(PETSC_SUCCESS);
2692 }
2693 
2694 /*@
2695   TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient in some of the `Tao` algorithms
2696 
2697   Collective
2698 
2699   Input Parameters:
2700 + tao - the `Tao` context
2701 - M   - matrix that defines the norm
2702 
2703   Level: beginner
2704 
2705 .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2706 @*/
2707 PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2708 {
2709   PetscFunctionBegin;
2710   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2711   PetscValidHeaderSpecific(M, MAT_CLASSID, 2);
2712   PetscCall(PetscObjectReference((PetscObject)M));
2713   PetscCall(MatDestroy(&tao->gradient_norm));
2714   PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2715   tao->gradient_norm = M;
2716   PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2717   PetscFunctionReturn(PETSC_SUCCESS);
2718 }
2719 
2720 /*@
2721   TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient in some of the `Tao` algorithms
2722 
2723   Not Collective
2724 
2725   Input Parameter:
2726 . tao - the `Tao` context
2727 
2728   Output Parameter:
2729 . M - gradient norm
2730 
2731   Level: beginner
2732 
2733 .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2734 @*/
2735 PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2736 {
2737   PetscFunctionBegin;
2738   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2739   PetscAssertPointer(M, 2);
2740   *M = tao->gradient_norm;
2741   PetscFunctionReturn(PETSC_SUCCESS);
2742 }
2743 
2744 /*@
2745   TaoGradientNorm - Compute the norm using the `NormType`, the user has selected
2746 
2747   Collective
2748 
2749   Input Parameters:
2750 + tao      - the `Tao` context
2751 . gradient - the gradient
2752 - type     - the norm type
2753 
2754   Output Parameter:
2755 . gnorm - the gradient norm
2756 
2757   Level: advanced
2758 
2759   Note:
2760   If `TaoSetGradientNorm()` has been set and `type` is `NORM_2` then the norm provided with `TaoSetGradientNorm()` is used.
2761 
2762   Developer Notes:
2763   Should be named `TaoComputeGradientNorm()`.
2764 
2765   The usage is a bit confusing, with `TaoSetGradientNorm()` plus `NORM_2` resulting in the computation of the user provided
2766   norm, perhaps a refactorization is in order.
2767 
2768 .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2769 @*/
2770 PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2771 {
2772   PetscFunctionBegin;
2773   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2774   PetscValidHeaderSpecific(gradient, VEC_CLASSID, 2);
2775   PetscValidLogicalCollectiveEnum(tao, type, 3);
2776   PetscAssertPointer(gnorm, 4);
2777   if (tao->gradient_norm) {
2778     PetscScalar gnorms;
2779 
2780     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.");
2781     PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2782     PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2783     *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2784   } else {
2785     PetscCall(VecNorm(gradient, type, gnorm));
2786   }
2787   PetscFunctionReturn(PETSC_SUCCESS);
2788 }
2789 
2790 /*@C
2791   TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorSolutionDraw()`
2792 
2793   Collective
2794 
2795   Input Parameters:
2796 + comm     - the communicator to share the context
2797 . host     - the name of the X Windows host that will display the monitor
2798 . label    - the label to put at the top of the display window
2799 . x        - the horizontal coordinate of the lower left corner of the window to open
2800 . y        - the vertical coordinate of the lower left corner of the window to open
2801 . m        - the width of the window
2802 . n        - the height of the window
2803 - howoften - how many `Tao` iterations between displaying the monitor information
2804 
2805   Output Parameter:
2806 . ctx - the monitor context
2807 
2808   Options Database Keys:
2809 + -tao_monitor_solution_draw - use `TaoMonitorSolutionDraw()` to monitor the solution
2810 - -tao_draw_solution_initial - show initial guess as well as current solution
2811 
2812   Level: intermediate
2813 
2814   Note:
2815   The context this creates, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
2816   are passed to `TaoMonitorSet()`.
2817 
2818 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2819 @*/
2820 PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2821 {
2822   PetscFunctionBegin;
2823   PetscCall(PetscNew(ctx));
2824   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
2825   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
2826   (*ctx)->howoften = howoften;
2827   PetscFunctionReturn(PETSC_SUCCESS);
2828 }
2829 
2830 /*@C
2831   TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorSolutionDraw()`
2832 
2833   Collective
2834 
2835   Input Parameter:
2836 . ictx - the monitor context
2837 
2838   Level: intermediate
2839 
2840   Note:
2841   This is passed to `TaoMonitorSet()` as the final argument, along with `TaoMonitorSolutionDraw()`, and the context
2842   obtained with `TaoMonitorDrawCtxCreate()`.
2843 
2844 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorSolutionDraw()`
2845 @*/
2846 PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2847 {
2848   PetscFunctionBegin;
2849   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
2850   PetscCall(PetscFree(*ictx));
2851   PetscFunctionReturn(PETSC_SUCCESS);
2852 }
2853