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