xref: /petsc/src/tao/interface/taosolver.c (revision badd099fb2ece77d080fc02aefe95d4a02e75697)
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   PetscFunctionBegin;
1534   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1535   PetscCheck(tao->numbermonitors < MAXTAOMONITORS, PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Cannot attach another monitor -- max=%d", MAXTAOMONITORS);
1536   for (PetscInt i = 0; i < tao->numbermonitors; i++) {
1537     PetscBool identical;
1538 
1539     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)func, ctx, dest, (PetscErrorCode (*)(void))(PetscVoidFn *)tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical));
1540     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1541   }
1542   tao->monitor[tao->numbermonitors]        = func;
1543   tao->monitorcontext[tao->numbermonitors] = ctx;
1544   tao->monitordestroy[tao->numbermonitors] = dest;
1545   ++tao->numbermonitors;
1546   PetscFunctionReturn(PETSC_SUCCESS);
1547 }
1548 
1549 /*@
1550   TaoMonitorCancel - Clears all the monitor functions for a `Tao` object.
1551 
1552   Logically Collective
1553 
1554   Input Parameter:
1555 . tao - the `Tao` solver context
1556 
1557   Options Database Key:
1558 . -tao_monitor_cancel - cancels all monitors that have been hardwired
1559     into a code by calls to `TaoMonitorSet()`, but does not cancel those
1560     set via the options database
1561 
1562   Level: advanced
1563 
1564   Note:
1565   There is no way to clear one specific monitor from a `Tao` object.
1566 
1567 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1568 @*/
1569 PetscErrorCode TaoMonitorCancel(Tao tao)
1570 {
1571   PetscInt i;
1572 
1573   PetscFunctionBegin;
1574   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1575   for (i = 0; i < tao->numbermonitors; i++) {
1576     if (tao->monitordestroy[i]) PetscCall((*tao->monitordestroy[i])(&tao->monitorcontext[i]));
1577   }
1578   tao->numbermonitors = 0;
1579   PetscFunctionReturn(PETSC_SUCCESS);
1580 }
1581 
1582 /*@
1583   TaoMonitorDefault - Default routine for monitoring progress of `TaoSolve()`
1584 
1585   Collective
1586 
1587   Input Parameters:
1588 + tao - the `Tao` context
1589 - ctx - `PetscViewer` context or `NULL`
1590 
1591   Options Database Key:
1592 . -tao_monitor - turn on default monitoring
1593 
1594   Level: advanced
1595 
1596   Note:
1597   This monitor prints the function value and gradient
1598   norm at each iteration.
1599 
1600 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1601 @*/
1602 PetscErrorCode TaoMonitorDefault(Tao tao, void *ctx)
1603 {
1604   PetscInt    its, tabs;
1605   PetscReal   fct, gnorm;
1606   PetscViewer viewer = (PetscViewer)ctx;
1607 
1608   PetscFunctionBegin;
1609   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1610   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1611   its   = tao->niter;
1612   fct   = tao->fc;
1613   gnorm = tao->residual;
1614   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1615   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1616   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1617     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1618     tao->header_printed = PETSC_TRUE;
1619   }
1620   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1621   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1622   if (gnorm >= PETSC_INFINITY) {
1623     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf \n"));
1624   } else {
1625     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g \n", (double)gnorm));
1626   }
1627   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1628   PetscFunctionReturn(PETSC_SUCCESS);
1629 }
1630 
1631 /*@
1632   TaoMonitorGlobalization - Default routine for monitoring progress of `TaoSolve()` with extra detail on the globalization method.
1633 
1634   Collective
1635 
1636   Input Parameters:
1637 + tao - the `Tao` context
1638 - ctx - `PetscViewer` context or `NULL`
1639 
1640   Options Database Key:
1641 . -tao_monitor_globalization - turn on monitoring with globalization information
1642 
1643   Level: advanced
1644 
1645   Note:
1646   This monitor prints the function value and gradient norm at each
1647   iteration, as well as the step size and trust radius. Note that the
1648   step size and trust radius may be the same for some algorithms.
1649 
1650 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1651 @*/
1652 PetscErrorCode TaoMonitorGlobalization(Tao tao, void *ctx)
1653 {
1654   PetscInt    its, tabs;
1655   PetscReal   fct, gnorm, stp, tr;
1656   PetscViewer viewer = (PetscViewer)ctx;
1657 
1658   PetscFunctionBegin;
1659   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1660   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1661   its   = tao->niter;
1662   fct   = tao->fc;
1663   gnorm = tao->residual;
1664   stp   = tao->step;
1665   tr    = tao->trust;
1666   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1667   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1668   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1669     PetscCall(PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1670     tao->header_printed = PETSC_TRUE;
1671   }
1672   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1673   PetscCall(PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct));
1674   if (gnorm >= PETSC_INFINITY) {
1675     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: Inf,"));
1676   } else {
1677     PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g,", (double)gnorm));
1678   }
1679   PetscCall(PetscViewerASCIIPrintf(viewer, "  Step: %g,  Trust: %g\n", (double)stp, (double)tr));
1680   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1681   PetscFunctionReturn(PETSC_SUCCESS);
1682 }
1683 
1684 /*@
1685   TaoMonitorDefaultShort - Routine for monitoring progress of `TaoSolve()` that displays fewer digits than `TaoMonitorDefault()`
1686 
1687   Collective
1688 
1689   Input Parameters:
1690 + tao - the `Tao` context
1691 - ctx - `PetscViewer` context of type `PETSCVIEWERASCII`
1692 
1693   Options Database Key:
1694 . -tao_monitor_short - turn on default short monitoring
1695 
1696   Level: advanced
1697 
1698   Note:
1699   Same as `TaoMonitorDefault()` except
1700   it prints fewer digits of the residual as the residual gets smaller.
1701   This is because the later digits are meaningless and are often
1702   different on different machines; by using this routine different
1703   machines will usually generate the same output.
1704 
1705 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1706 @*/
1707 PetscErrorCode TaoMonitorDefaultShort(Tao tao, void *ctx)
1708 {
1709   PetscInt    its, tabs;
1710   PetscReal   fct, gnorm;
1711   PetscViewer viewer = (PetscViewer)ctx;
1712 
1713   PetscFunctionBegin;
1714   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1715   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1716   its   = tao->niter;
1717   fct   = tao->fc;
1718   gnorm = tao->residual;
1719   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1720   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1721   PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %3" PetscInt_FMT ",", its));
1722   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value %g,", (double)fct));
1723   if (gnorm >= PETSC_INFINITY) {
1724     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf \n"));
1725   } else if (gnorm > 1.e-6) {
1726     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm));
1727   } else if (gnorm > 1.e-11) {
1728     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-6 \n"));
1729   } else {
1730     PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-11 \n"));
1731   }
1732   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1733   PetscFunctionReturn(PETSC_SUCCESS);
1734 }
1735 
1736 /*@
1737   TaoMonitorConstraintNorm - same as `TaoMonitorDefault()` except
1738   it prints the norm of the constraint function.
1739 
1740   Collective
1741 
1742   Input Parameters:
1743 + tao - the `Tao` context
1744 - ctx - `PetscViewer` context or `NULL`
1745 
1746   Options Database Key:
1747 . -tao_monitor_constraint_norm - monitor the constraints
1748 
1749   Level: advanced
1750 
1751 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoMonitorSet()`
1752 @*/
1753 PetscErrorCode TaoMonitorConstraintNorm(Tao tao, void *ctx)
1754 {
1755   PetscInt    its, tabs;
1756   PetscReal   fct, gnorm;
1757   PetscViewer viewer = (PetscViewer)ctx;
1758 
1759   PetscFunctionBegin;
1760   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1761   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1762   its   = tao->niter;
1763   fct   = tao->fc;
1764   gnorm = tao->residual;
1765   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1766   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1767   PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", its));
1768   PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct));
1769   PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual: %g ", (double)gnorm));
1770   PetscCall(PetscViewerASCIIPrintf(viewer, "  Constraint: %g \n", (double)tao->cnorm));
1771   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1772   PetscFunctionReturn(PETSC_SUCCESS);
1773 }
1774 
1775 /*@C
1776   TaoMonitorSolution - Views the solution at each iteration of `TaoSolve()`
1777 
1778   Collective
1779 
1780   Input Parameters:
1781 + tao - the `Tao` context
1782 - ctx - `PetscViewer` context or `NULL`
1783 
1784   Options Database Key:
1785 . -tao_monitor_solution - view the solution
1786 
1787   Level: advanced
1788 
1789 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1790 @*/
1791 PetscErrorCode TaoMonitorSolution(Tao tao, void *ctx)
1792 {
1793   PetscViewer viewer = (PetscViewer)ctx;
1794 
1795   PetscFunctionBegin;
1796   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1797   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1798   PetscCall(VecView(tao->solution, viewer));
1799   PetscFunctionReturn(PETSC_SUCCESS);
1800 }
1801 
1802 /*@C
1803   TaoMonitorGradient - Views the gradient at each iteration of `TaoSolve()`
1804 
1805   Collective
1806 
1807   Input Parameters:
1808 + tao - the `Tao` context
1809 - ctx - `PetscViewer` context or `NULL`
1810 
1811   Options Database Key:
1812 . -tao_monitor_gradient - view the gradient at each iteration
1813 
1814   Level: advanced
1815 
1816 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1817 @*/
1818 PetscErrorCode TaoMonitorGradient(Tao tao, void *ctx)
1819 {
1820   PetscViewer viewer = (PetscViewer)ctx;
1821 
1822   PetscFunctionBegin;
1823   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1824   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1825   PetscCall(VecView(tao->gradient, viewer));
1826   PetscFunctionReturn(PETSC_SUCCESS);
1827 }
1828 
1829 /*@C
1830   TaoMonitorStep - Views the step-direction at each iteration of `TaoSolve()`
1831 
1832   Collective
1833 
1834   Input Parameters:
1835 + tao - the `Tao` context
1836 - ctx - `PetscViewer` context or `NULL`
1837 
1838   Options Database Key:
1839 . -tao_monitor_step - view the step vector at each iteration
1840 
1841   Level: advanced
1842 
1843 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1844 @*/
1845 PetscErrorCode TaoMonitorStep(Tao tao, void *ctx)
1846 {
1847   PetscViewer viewer = (PetscViewer)ctx;
1848 
1849   PetscFunctionBegin;
1850   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1851   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1852   PetscCall(VecView(tao->stepdirection, viewer));
1853   PetscFunctionReturn(PETSC_SUCCESS);
1854 }
1855 
1856 /*@C
1857   TaoMonitorSolutionDraw - Plots the solution at each iteration of `TaoSolve()`
1858 
1859   Collective
1860 
1861   Input Parameters:
1862 + tao - the `Tao` context
1863 - ctx - `TaoMonitorDraw` context
1864 
1865   Options Database Key:
1866 . -tao_monitor_solution_draw - draw the solution at each iteration
1867 
1868   Level: advanced
1869 
1870   Note:
1871   The context created by `TaoMonitorDrawCtxCreate()`, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
1872   are passed to `TaoMonitorSet()` to monitor the solution graphically.
1873 
1874 .seealso: [](ch_tao), `Tao`, `TaoMonitorSolution()`, `TaoMonitorSet()`, `TaoMonitorGradientDraw()`, `TaoMonitorDrawCtxCreate()`,
1875           `TaoMonitorDrawCtxDestroy()`
1876 @*/
1877 PetscErrorCode TaoMonitorSolutionDraw(Tao tao, void *ctx)
1878 {
1879   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
1880 
1881   PetscFunctionBegin;
1882   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1883   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1884   PetscCall(VecView(tao->solution, ictx->viewer));
1885   PetscFunctionReturn(PETSC_SUCCESS);
1886 }
1887 
1888 /*@C
1889   TaoMonitorGradientDraw - Plots the gradient at each iteration of `TaoSolve()`
1890 
1891   Collective
1892 
1893   Input Parameters:
1894 + tao - the `Tao` context
1895 - ctx - `PetscViewer` context
1896 
1897   Options Database Key:
1898 . -tao_monitor_gradient_draw - draw the gradient at each iteration
1899 
1900   Level: advanced
1901 
1902 .seealso: [](ch_tao), `Tao`, `TaoMonitorGradient()`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw()`
1903 @*/
1904 PetscErrorCode TaoMonitorGradientDraw(Tao tao, void *ctx)
1905 {
1906   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
1907 
1908   PetscFunctionBegin;
1909   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1910   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1911   PetscCall(VecView(tao->gradient, ictx->viewer));
1912   PetscFunctionReturn(PETSC_SUCCESS);
1913 }
1914 
1915 /*@C
1916   TaoMonitorStepDraw - Plots the step direction at each iteration of `TaoSolve()`
1917 
1918   Collective
1919 
1920   Input Parameters:
1921 + tao - the `Tao` context
1922 - ctx - the `PetscViewer` context
1923 
1924   Options Database Key:
1925 . -tao_monitor_step_draw - draw the step direction at each iteration
1926 
1927   Level: advanced
1928 
1929 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorSolutionDraw`
1930 @*/
1931 PetscErrorCode TaoMonitorStepDraw(Tao tao, void *ctx)
1932 {
1933   PetscViewer viewer = (PetscViewer)ctx;
1934 
1935   PetscFunctionBegin;
1936   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1937   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1938   PetscCall(VecView(tao->stepdirection, viewer));
1939   PetscFunctionReturn(PETSC_SUCCESS);
1940 }
1941 
1942 /*@C
1943   TaoMonitorResidual - Views the least-squares residual at each iteration of `TaoSolve()`
1944 
1945   Collective
1946 
1947   Input Parameters:
1948 + tao - the `Tao` context
1949 - ctx - the `PetscViewer` context or `NULL`
1950 
1951   Options Database Key:
1952 . -tao_monitor_ls_residual - view the residual at each iteration
1953 
1954   Level: advanced
1955 
1956 .seealso: [](ch_tao), `Tao`, `TaoMonitorDefaultShort()`, `TaoMonitorSet()`
1957 @*/
1958 PetscErrorCode TaoMonitorResidual(Tao tao, void *ctx)
1959 {
1960   PetscViewer viewer = (PetscViewer)ctx;
1961 
1962   PetscFunctionBegin;
1963   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1964   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1965   PetscCall(VecView(tao->ls_res, viewer));
1966   PetscFunctionReturn(PETSC_SUCCESS);
1967 }
1968 
1969 /*@
1970   TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
1971   or terminate.
1972 
1973   Collective
1974 
1975   Input Parameters:
1976 + tao   - the `Tao` context
1977 - dummy - unused dummy context
1978 
1979   Level: developer
1980 
1981   Notes:
1982   This routine checks the residual in the optimality conditions, the
1983   relative residual in the optimity conditions, the number of function
1984   evaluations, and the function value to test convergence.  Some
1985   solvers may use different convergence routines.
1986 
1987 .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
1988 @*/
1989 PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
1990 {
1991   PetscInt           niter = tao->niter, nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1992   PetscInt           max_funcs = tao->max_funcs;
1993   PetscReal          gnorm = tao->residual, gnorm0 = tao->gnorm0;
1994   PetscReal          f = tao->fc, steptol = tao->steptol, trradius = tao->step;
1995   PetscReal          gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
1996   PetscReal          catol = tao->catol, crtol = tao->crtol;
1997   PetscReal          fmin = tao->fmin, cnorm = tao->cnorm;
1998   TaoConvergedReason reason = tao->reason;
1999 
2000   PetscFunctionBegin;
2001   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2002   if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);
2003 
2004   if (PetscIsInfOrNanReal(f)) {
2005     PetscCall(PetscInfo(tao, "Failed to converged, function value is Inf or NaN\n"));
2006     reason = TAO_DIVERGED_NAN;
2007   } else if (f <= fmin && cnorm <= catol) {
2008     PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
2009     reason = TAO_CONVERGED_MINF;
2010   } else if (gnorm <= gatol && cnorm <= catol) {
2011     PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
2012     reason = TAO_CONVERGED_GATOL;
2013   } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
2014     PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
2015     reason = TAO_CONVERGED_GRTOL;
2016   } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
2017     PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
2018     reason = TAO_CONVERGED_GTTOL;
2019   } else if (max_funcs != PETSC_UNLIMITED && nfuncs > max_funcs) {
2020     PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
2021     reason = TAO_DIVERGED_MAXFCN;
2022   } else if (tao->lsflag != 0) {
2023     PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
2024     reason = TAO_DIVERGED_LS_FAILURE;
2025   } else if (trradius < steptol && niter > 0) {
2026     PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
2027     reason = TAO_CONVERGED_STEPTOL;
2028   } else if (niter >= tao->max_it) {
2029     PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
2030     reason = TAO_DIVERGED_MAXITS;
2031   } else {
2032     reason = TAO_CONTINUE_ITERATING;
2033   }
2034   tao->reason = reason;
2035   PetscFunctionReturn(PETSC_SUCCESS);
2036 }
2037 
2038 /*@
2039   TaoSetOptionsPrefix - Sets the prefix used for searching for all
2040   Tao options in the database.
2041 
2042   Logically Collective
2043 
2044   Input Parameters:
2045 + tao - the `Tao` context
2046 - p   - the prefix string to prepend to all Tao option requests
2047 
2048   Level: advanced
2049 
2050   Notes:
2051   A hyphen (-) must NOT be given at the beginning of the prefix name.
2052   The first character of all runtime options is AUTOMATICALLY the hyphen.
2053 
2054   For example, to distinguish between the runtime options for two
2055   different Tao solvers, one could call
2056 .vb
2057       TaoSetOptionsPrefix(tao1,"sys1_")
2058       TaoSetOptionsPrefix(tao2,"sys2_")
2059 .ve
2060 
2061   This would enable use of different options for each system, such as
2062 .vb
2063       -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2064       -sys2_tao_method lmvm  -sys2_tao_grtol 1.e-4
2065 .ve
2066 
2067 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2068 @*/
2069 PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2070 {
2071   PetscFunctionBegin;
2072   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2073   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2074   if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2075   if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2076   PetscFunctionReturn(PETSC_SUCCESS);
2077 }
2078 
2079 /*@
2080   TaoAppendOptionsPrefix - Appends to the prefix used for searching for all Tao options in the database.
2081 
2082   Logically Collective
2083 
2084   Input Parameters:
2085 + tao - the `Tao` solver context
2086 - p   - the prefix string to prepend to all `Tao` option requests
2087 
2088   Level: advanced
2089 
2090   Note:
2091   A hyphen (-) must NOT be given at the beginning of the prefix name.
2092   The first character of all runtime options is automatically the hyphen.
2093 
2094 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2095 @*/
2096 PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2097 {
2098   PetscFunctionBegin;
2099   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2100   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2101   if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2102   if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2103   PetscFunctionReturn(PETSC_SUCCESS);
2104 }
2105 
2106 /*@
2107   TaoGetOptionsPrefix - Gets the prefix used for searching for all
2108   Tao options in the database
2109 
2110   Not Collective
2111 
2112   Input Parameter:
2113 . tao - the `Tao` context
2114 
2115   Output Parameter:
2116 . p - pointer to the prefix string used is returned
2117 
2118   Level: advanced
2119 
2120 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2121 @*/
2122 PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2123 {
2124   PetscFunctionBegin;
2125   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2126   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2127   PetscFunctionReturn(PETSC_SUCCESS);
2128 }
2129 
2130 /*@
2131   TaoSetType - Sets the `TaoType` for the minimization solver.
2132 
2133   Collective
2134 
2135   Input Parameters:
2136 + tao  - the `Tao` solver context
2137 - type - a known method
2138 
2139   Options Database Key:
2140 . -tao_type <type> - Sets the method; use -help for a list
2141    of available methods (for instance, "-tao_type lmvm" or "-tao_type tron")
2142 
2143   Level: intermediate
2144 
2145 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2146 @*/
2147 PetscErrorCode TaoSetType(Tao tao, TaoType type)
2148 {
2149   PetscErrorCode (*create_xxx)(Tao);
2150   PetscBool issame;
2151 
2152   PetscFunctionBegin;
2153   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2154 
2155   PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2156   if (issame) PetscFunctionReturn(PETSC_SUCCESS);
2157 
2158   PetscCall(PetscFunctionListFind(TaoList, type, &create_xxx));
2159   PetscCheck(create_xxx, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Tao type %s", type);
2160 
2161   /* Destroy the existing solver information */
2162   PetscTryTypeMethod(tao, destroy);
2163   PetscCall(KSPDestroy(&tao->ksp));
2164   PetscCall(TaoLineSearchDestroy(&tao->linesearch));
2165 
2166   /* Reinitialize type-specific function pointers in TaoOps structure */
2167   tao->ops->setup          = NULL;
2168   tao->ops->computedual    = NULL;
2169   tao->ops->solve          = NULL;
2170   tao->ops->view           = NULL;
2171   tao->ops->setfromoptions = NULL;
2172   tao->ops->destroy        = NULL;
2173 
2174   tao->setupcalled = PETSC_FALSE;
2175 
2176   PetscCall((*create_xxx)(tao));
2177   PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2178   PetscFunctionReturn(PETSC_SUCCESS);
2179 }
2180 
2181 /*@C
2182   TaoRegister - Adds a method to the Tao package for minimization.
2183 
2184   Not Collective, No Fortran Support
2185 
2186   Input Parameters:
2187 + sname - name of a new user-defined solver
2188 - func  - routine to Create method context
2189 
2190   Example Usage:
2191 .vb
2192    TaoRegister("my_solver", MySolverCreate);
2193 .ve
2194 
2195   Then, your solver can be chosen with the procedural interface via
2196 .vb
2197   TaoSetType(tao, "my_solver")
2198 .ve
2199   or at runtime via the option
2200 .vb
2201   -tao_type my_solver
2202 .ve
2203 
2204   Level: advanced
2205 
2206   Note:
2207   `TaoRegister()` may be called multiple times to add several user-defined solvers.
2208 
2209 .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2210 @*/
2211 PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao))
2212 {
2213   PetscFunctionBegin;
2214   PetscCall(TaoInitializePackage());
2215   PetscCall(PetscFunctionListAdd(&TaoList, sname, func));
2216   PetscFunctionReturn(PETSC_SUCCESS);
2217 }
2218 
2219 /*@C
2220   TaoRegisterDestroy - Frees the list of minimization solvers that were
2221   registered by `TaoRegister()`.
2222 
2223   Not Collective
2224 
2225   Level: advanced
2226 
2227 .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2228 @*/
2229 PetscErrorCode TaoRegisterDestroy(void)
2230 {
2231   PetscFunctionBegin;
2232   PetscCall(PetscFunctionListDestroy(&TaoList));
2233   TaoRegisterAllCalled = PETSC_FALSE;
2234   PetscFunctionReturn(PETSC_SUCCESS);
2235 }
2236 
2237 /*@
2238   TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2239   at this time.
2240 
2241   Not Collective
2242 
2243   Input Parameter:
2244 . tao - the `Tao` context
2245 
2246   Output Parameter:
2247 . iter - iteration number
2248 
2249   Notes:
2250   For example, during the computation of iteration 2 this would return 1.
2251 
2252   Level: intermediate
2253 
2254 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2255 @*/
2256 PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2257 {
2258   PetscFunctionBegin;
2259   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2260   PetscAssertPointer(iter, 2);
2261   *iter = tao->niter;
2262   PetscFunctionReturn(PETSC_SUCCESS);
2263 }
2264 
2265 /*@
2266   TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2267   at this time.
2268 
2269   Not Collective
2270 
2271   Input Parameter:
2272 . tao - the `Tao` context
2273 
2274   Output Parameter:
2275 . value - the current value
2276 
2277   Level: intermediate
2278 
2279   Developer Notes:
2280   This is the 2-norm of the residual, we cannot use `TaoGetGradientNorm()` because that has
2281   a different meaning. For some reason `Tao` sometimes calls the gradient the residual.
2282 
2283 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2284 @*/
2285 PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2286 {
2287   PetscFunctionBegin;
2288   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2289   PetscAssertPointer(value, 2);
2290   *value = tao->residual;
2291   PetscFunctionReturn(PETSC_SUCCESS);
2292 }
2293 
2294 /*@
2295   TaoSetIterationNumber - Sets the current iteration number.
2296 
2297   Logically Collective
2298 
2299   Input Parameters:
2300 + tao  - the `Tao` context
2301 - iter - iteration number
2302 
2303   Level: developer
2304 
2305 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2306 @*/
2307 PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2308 {
2309   PetscFunctionBegin;
2310   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2311   PetscValidLogicalCollectiveInt(tao, iter, 2);
2312   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2313   tao->niter = iter;
2314   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2315   PetscFunctionReturn(PETSC_SUCCESS);
2316 }
2317 
2318 /*@
2319   TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2320   completed. This number keeps accumulating if multiple solves
2321   are called with the `Tao` object.
2322 
2323   Not Collective
2324 
2325   Input Parameter:
2326 . tao - the `Tao` context
2327 
2328   Output Parameter:
2329 . iter - number of iterations
2330 
2331   Level: intermediate
2332 
2333   Note:
2334   The total iteration count is updated after each solve, if there is a current
2335   `TaoSolve()` in progress then those iterations are not included in the count
2336 
2337 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2338 @*/
2339 PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2340 {
2341   PetscFunctionBegin;
2342   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2343   PetscAssertPointer(iter, 2);
2344   *iter = tao->ntotalits;
2345   PetscFunctionReturn(PETSC_SUCCESS);
2346 }
2347 
2348 /*@
2349   TaoSetTotalIterationNumber - Sets the current total iteration number.
2350 
2351   Logically Collective
2352 
2353   Input Parameters:
2354 + tao  - the `Tao` context
2355 - iter - the iteration number
2356 
2357   Level: developer
2358 
2359 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2360 @*/
2361 PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2362 {
2363   PetscFunctionBegin;
2364   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2365   PetscValidLogicalCollectiveInt(tao, iter, 2);
2366   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2367   tao->ntotalits = iter;
2368   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2369   PetscFunctionReturn(PETSC_SUCCESS);
2370 }
2371 
2372 /*@
2373   TaoSetConvergedReason - Sets the termination flag on a `Tao` object
2374 
2375   Logically Collective
2376 
2377   Input Parameters:
2378 + tao    - the `Tao` context
2379 - reason - the `TaoConvergedReason`
2380 
2381   Level: intermediate
2382 
2383 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2384 @*/
2385 PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2386 {
2387   PetscFunctionBegin;
2388   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2389   PetscValidLogicalCollectiveEnum(tao, reason, 2);
2390   tao->reason = reason;
2391   PetscFunctionReturn(PETSC_SUCCESS);
2392 }
2393 
2394 /*@
2395   TaoGetConvergedReason - Gets the reason the `TaoSolve()` was stopped.
2396 
2397   Not Collective
2398 
2399   Input Parameter:
2400 . tao - the `Tao` solver context
2401 
2402   Output Parameter:
2403 . reason - value of `TaoConvergedReason`
2404 
2405   Level: intermediate
2406 
2407 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`
2408 @*/
2409 PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2410 {
2411   PetscFunctionBegin;
2412   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2413   PetscAssertPointer(reason, 2);
2414   *reason = tao->reason;
2415   PetscFunctionReturn(PETSC_SUCCESS);
2416 }
2417 
2418 /*@
2419   TaoGetSolutionStatus - Get the current iterate, objective value,
2420   residual, infeasibility, and termination from a `Tao` object
2421 
2422   Not Collective
2423 
2424   Input Parameter:
2425 . tao - the `Tao` context
2426 
2427   Output Parameters:
2428 + its    - the current iterate number (>=0)
2429 . f      - the current function value
2430 . gnorm  - the square of the gradient norm, duality gap, or other measure indicating distance from optimality.
2431 . cnorm  - the infeasibility of the current solution with regard to the constraints.
2432 . xdiff  - the step length or trust region radius of the most recent iterate.
2433 - reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`
2434 
2435   Level: intermediate
2436 
2437   Notes:
2438   Tao returns the values set by the solvers in the routine `TaoMonitor()`.
2439 
2440   If any of the output arguments are set to `NULL`, no corresponding value will be returned.
2441 
2442 .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2443 @*/
2444 PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2445 {
2446   PetscFunctionBegin;
2447   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2448   if (its) *its = tao->niter;
2449   if (f) *f = tao->fc;
2450   if (gnorm) *gnorm = tao->residual;
2451   if (cnorm) *cnorm = tao->cnorm;
2452   if (reason) *reason = tao->reason;
2453   if (xdiff) *xdiff = tao->step;
2454   PetscFunctionReturn(PETSC_SUCCESS);
2455 }
2456 
2457 /*@
2458   TaoGetType - Gets the current `TaoType` being used in the `Tao` object
2459 
2460   Not Collective
2461 
2462   Input Parameter:
2463 . tao - the `Tao` solver context
2464 
2465   Output Parameter:
2466 . type - the `TaoType`
2467 
2468   Level: intermediate
2469 
2470 .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`
2471 @*/
2472 PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2473 {
2474   PetscFunctionBegin;
2475   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2476   PetscAssertPointer(type, 2);
2477   *type = ((PetscObject)tao)->type_name;
2478   PetscFunctionReturn(PETSC_SUCCESS);
2479 }
2480 
2481 /*@C
2482   TaoMonitor - Monitor the solver and the current solution.  This
2483   routine will record the iteration number and residual statistics,
2484   and call any monitors specified by the user.
2485 
2486   Input Parameters:
2487 + tao        - the `Tao` context
2488 . its        - the current iterate number (>=0)
2489 . f          - the current objective function value
2490 . res        - the gradient norm, square root of the duality gap, or other measure indicating distance from optimality.  This measure will be recorded and
2491           used for some termination tests.
2492 . cnorm      - the infeasibility of the current solution with regard to the constraints.
2493 - steplength - multiple of the step direction added to the previous iterate.
2494 
2495   Options Database Key:
2496 . -tao_monitor - Use the default monitor, which prints statistics to standard output
2497 
2498   Level: developer
2499 
2500 .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoMonitorSet()`
2501 @*/
2502 PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2503 {
2504   PetscInt i;
2505 
2506   PetscFunctionBegin;
2507   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2508   tao->fc       = f;
2509   tao->residual = res;
2510   tao->cnorm    = cnorm;
2511   tao->step     = steplength;
2512   if (!its) {
2513     tao->cnorm0 = cnorm;
2514     tao->gnorm0 = res;
2515   }
2516   PetscCall(VecLockReadPush(tao->solution));
2517   for (i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2518   PetscCall(VecLockReadPop(tao->solution));
2519   PetscFunctionReturn(PETSC_SUCCESS);
2520 }
2521 
2522 /*@
2523   TaoSetConvergenceHistory - Sets the array used to hold the convergence history.
2524 
2525   Logically Collective
2526 
2527   Input Parameters:
2528 + tao   - the `Tao` solver context
2529 . obj   - array to hold objective value history
2530 . resid - array to hold residual history
2531 . cnorm - array to hold constraint violation history
2532 . lits  - integer array holds the number of linear iterations for each Tao iteration
2533 . na    - size of `obj`, `resid`, and `cnorm`
2534 - reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2535            else it continues storing new values for new minimizations after the old ones
2536 
2537   Level: intermediate
2538 
2539   Notes:
2540   If set, `Tao` will fill the given arrays with the indicated
2541   information at each iteration.  If 'obj','resid','cnorm','lits' are
2542   *all* `NULL` then space (using size `na`, or 1000 if `na` is `PETSC_DECIDE`) is allocated for the history.
2543   If not all are `NULL`, then only the non-`NULL` information categories
2544   will be stored, the others will be ignored.
2545 
2546   Any convergence information after iteration number 'na' will not be stored.
2547 
2548   This routine is useful, e.g., when running a code for purposes
2549   of accurate performance monitoring, when no I/O should be done
2550   during the section of code that is being timed.
2551 
2552 .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2553 @*/
2554 PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2555 {
2556   PetscFunctionBegin;
2557   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2558   if (obj) PetscAssertPointer(obj, 2);
2559   if (resid) PetscAssertPointer(resid, 3);
2560   if (cnorm) PetscAssertPointer(cnorm, 4);
2561   if (lits) PetscAssertPointer(lits, 5);
2562 
2563   if (na == PETSC_DECIDE || na == PETSC_CURRENT) na = 1000;
2564   if (!obj && !resid && !cnorm && !lits) {
2565     PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2566     tao->hist_malloc = PETSC_TRUE;
2567   }
2568 
2569   tao->hist_obj   = obj;
2570   tao->hist_resid = resid;
2571   tao->hist_cnorm = cnorm;
2572   tao->hist_lits  = lits;
2573   tao->hist_max   = na;
2574   tao->hist_reset = reset;
2575   tao->hist_len   = 0;
2576   PetscFunctionReturn(PETSC_SUCCESS);
2577 }
2578 
2579 /*@C
2580   TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.
2581 
2582   Collective
2583 
2584   Input Parameter:
2585 . tao - the `Tao` context
2586 
2587   Output Parameters:
2588 + obj   - array used to hold objective value history
2589 . resid - array used to hold residual history
2590 . cnorm - array used to hold constraint violation history
2591 . lits  - integer array used to hold linear solver iteration count
2592 - nhist - size of `obj`, `resid`, `cnorm`, and `lits`
2593 
2594   Level: advanced
2595 
2596   Notes:
2597   This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2598   and `TaoSolve()`, otherwise it returns useless information.
2599 
2600   This routine is useful, e.g., when running a code for purposes
2601   of accurate performance monitoring, when no I/O should be done
2602   during the section of code that is being timed.
2603 
2604   Fortran Notes:
2605   The calling sequence is
2606 .vb
2607    call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2608 .ve
2609   In other words this gets the current number of entries in the history. Access the history through the array you passed to `TaoSetConvergenceHistory()`
2610 
2611 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2612 @*/
2613 PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2614 {
2615   PetscFunctionBegin;
2616   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2617   if (obj) *obj = tao->hist_obj;
2618   if (cnorm) *cnorm = tao->hist_cnorm;
2619   if (resid) *resid = tao->hist_resid;
2620   if (lits) *lits = tao->hist_lits;
2621   if (nhist) *nhist = tao->hist_len;
2622   PetscFunctionReturn(PETSC_SUCCESS);
2623 }
2624 
2625 /*@
2626   TaoSetApplicationContext - Sets the optional user-defined context for a `Tao` solver that can be accessed later, for example in the
2627   `Tao` callback functions with `TaoGetApplicationContext()`
2628 
2629   Logically Collective
2630 
2631   Input Parameters:
2632 + tao - the `Tao` context
2633 - ctx - the user context
2634 
2635   Level: intermediate
2636 
2637   Fortran Note:
2638   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
2639   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `TaoGetApplicationContext()` for
2640   an example.
2641 
2642 .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`
2643 @*/
2644 PetscErrorCode TaoSetApplicationContext(Tao tao, void *ctx)
2645 {
2646   PetscFunctionBegin;
2647   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2648   tao->ctx = ctx;
2649   PetscFunctionReturn(PETSC_SUCCESS);
2650 }
2651 
2652 /*@
2653   TaoGetApplicationContext - Gets the user-defined context for a `Tao` solver provided with `TaoSetApplicationContext()`
2654 
2655   Not Collective
2656 
2657   Input Parameter:
2658 . tao - the `Tao` context
2659 
2660   Output Parameter:
2661 . ctx - a pointer to the user context
2662 
2663   Level: intermediate
2664 
2665   Fortran Notes:
2666   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
2667   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
2668 .vb
2669   Interface TaoGetApplicationContext
2670     Subroutine TaoGetApplicationContext(tao,ctx,ierr)
2671   #include <petsc/finclude/petsctao.h>
2672       use petsctao
2673       Tao tao
2674       type(tUsertype), pointer :: ctx
2675       PetscErrorCode ierr
2676     End Subroutine
2677   End Interface TaoGetApplicationContext
2678 .ve
2679 
2680   The prototype for `ctx` must be
2681 .vb
2682   type(tUsertype), pointer :: ctx
2683 .ve
2684 
2685 .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2686 @*/
2687 PetscErrorCode TaoGetApplicationContext(Tao tao, PeCtx ctx)
2688 {
2689   PetscFunctionBegin;
2690   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2691   PetscAssertPointer(ctx, 2);
2692   *(void **)ctx = tao->ctx;
2693   PetscFunctionReturn(PETSC_SUCCESS);
2694 }
2695 
2696 /*@
2697   TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient in some of the `Tao` algorithms
2698 
2699   Collective
2700 
2701   Input Parameters:
2702 + tao - the `Tao` context
2703 - M   - matrix that defines the norm
2704 
2705   Level: beginner
2706 
2707 .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2708 @*/
2709 PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2710 {
2711   PetscFunctionBegin;
2712   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2713   PetscValidHeaderSpecific(M, MAT_CLASSID, 2);
2714   PetscCall(PetscObjectReference((PetscObject)M));
2715   PetscCall(MatDestroy(&tao->gradient_norm));
2716   PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2717   tao->gradient_norm = M;
2718   PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2719   PetscFunctionReturn(PETSC_SUCCESS);
2720 }
2721 
2722 /*@
2723   TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient in some of the `Tao` algorithms
2724 
2725   Not Collective
2726 
2727   Input Parameter:
2728 . tao - the `Tao` context
2729 
2730   Output Parameter:
2731 . M - gradient norm
2732 
2733   Level: beginner
2734 
2735 .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2736 @*/
2737 PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2738 {
2739   PetscFunctionBegin;
2740   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2741   PetscAssertPointer(M, 2);
2742   *M = tao->gradient_norm;
2743   PetscFunctionReturn(PETSC_SUCCESS);
2744 }
2745 
2746 /*@
2747   TaoGradientNorm - Compute the norm using the `NormType`, the user has selected
2748 
2749   Collective
2750 
2751   Input Parameters:
2752 + tao      - the `Tao` context
2753 . gradient - the gradient
2754 - type     - the norm type
2755 
2756   Output Parameter:
2757 . gnorm - the gradient norm
2758 
2759   Level: advanced
2760 
2761   Note:
2762   If `TaoSetGradientNorm()` has been set and `type` is `NORM_2` then the norm provided with `TaoSetGradientNorm()` is used.
2763 
2764   Developer Notes:
2765   Should be named `TaoComputeGradientNorm()`.
2766 
2767   The usage is a bit confusing, with `TaoSetGradientNorm()` plus `NORM_2` resulting in the computation of the user provided
2768   norm, perhaps a refactorization is in order.
2769 
2770 .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2771 @*/
2772 PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2773 {
2774   PetscFunctionBegin;
2775   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2776   PetscValidHeaderSpecific(gradient, VEC_CLASSID, 2);
2777   PetscValidLogicalCollectiveEnum(tao, type, 3);
2778   PetscAssertPointer(gnorm, 4);
2779   if (tao->gradient_norm) {
2780     PetscScalar gnorms;
2781 
2782     PetscCheck(type == NORM_2, PetscObjectComm((PetscObject)gradient), PETSC_ERR_ARG_WRONG, "Norm type must be NORM_2 if an inner product for the gradient norm is set.");
2783     PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2784     PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2785     *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2786   } else {
2787     PetscCall(VecNorm(gradient, type, gnorm));
2788   }
2789   PetscFunctionReturn(PETSC_SUCCESS);
2790 }
2791 
2792 /*@C
2793   TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorSolutionDraw()`
2794 
2795   Collective
2796 
2797   Input Parameters:
2798 + comm     - the communicator to share the context
2799 . host     - the name of the X Windows host that will display the monitor
2800 . label    - the label to put at the top of the display window
2801 . x        - the horizontal coordinate of the lower left corner of the window to open
2802 . y        - the vertical coordinate of the lower left corner of the window to open
2803 . m        - the width of the window
2804 . n        - the height of the window
2805 - howoften - how many `Tao` iterations between displaying the monitor information
2806 
2807   Output Parameter:
2808 . ctx - the monitor context
2809 
2810   Options Database Keys:
2811 + -tao_monitor_solution_draw - use `TaoMonitorSolutionDraw()` to monitor the solution
2812 - -tao_draw_solution_initial - show initial guess as well as current solution
2813 
2814   Level: intermediate
2815 
2816   Note:
2817   The context this creates, along with `TaoMonitorSolutionDraw()`, and `TaoMonitorDrawCtxDestroy()`
2818   are passed to `TaoMonitorSet()`.
2819 
2820 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2821 @*/
2822 PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2823 {
2824   PetscFunctionBegin;
2825   PetscCall(PetscNew(ctx));
2826   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
2827   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
2828   (*ctx)->howoften = howoften;
2829   PetscFunctionReturn(PETSC_SUCCESS);
2830 }
2831 
2832 /*@C
2833   TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorSolutionDraw()`
2834 
2835   Collective
2836 
2837   Input Parameter:
2838 . ictx - the monitor context
2839 
2840   Level: intermediate
2841 
2842   Note:
2843   This is passed to `TaoMonitorSet()` as the final argument, along with `TaoMonitorSolutionDraw()`, and the context
2844   obtained with `TaoMonitorDrawCtxCreate()`.
2845 
2846 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorSolutionDraw()`
2847 @*/
2848 PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2849 {
2850   PetscFunctionBegin;
2851   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
2852   PetscCall(PetscFree(*ictx));
2853   PetscFunctionReturn(PETSC_SUCCESS);
2854 }
2855