xref: /petsc/src/tao/interface/taosolver.c (revision 9d13fa56c5c6523e02c36edc0e4e22bf2d0334a8)
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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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 
1287    Level: developer
1288 
1289 .seealso: [](ch_tao), `Tao`, `TaoGetLineSearch()`, `TaoLineSearchApply()`
1290 @*/
1291 PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1292 {
1293   PetscBool flg;
1294   PetscInt  nfeval, ngeval, nfgeval;
1295 
1296   PetscFunctionBegin;
1297   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1298   if (tao->linesearch) {
1299     PetscCall(TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg));
1300     if (!flg) {
1301       PetscCall(TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval));
1302       tao->nfuncs += nfeval;
1303       tao->ngrads += ngeval;
1304       tao->nfuncgrads += nfgeval;
1305     }
1306   }
1307   PetscFunctionReturn(PETSC_SUCCESS);
1308 }
1309 
1310 /*@
1311   TaoGetSolution - Returns the vector with the current solution from the `Tao` object
1312 
1313   Not Collective
1314 
1315   Input Parameter:
1316 . tao - the `Tao` context
1317 
1318   Output Parameter:
1319 . X - the current solution
1320 
1321   Level: intermediate
1322 
1323   Note:
1324   The returned vector will be the same object that was passed into `TaoSetSolution()`
1325 
1326 .seealso: [](ch_tao), `Tao`, `TaoSetSolution()`, `TaoSolve()`
1327 @*/
1328 PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1329 {
1330   PetscFunctionBegin;
1331   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1332   PetscValidPointer(X, 2);
1333   *X = tao->solution;
1334   PetscFunctionReturn(PETSC_SUCCESS);
1335 }
1336 
1337 /*@
1338    TaoResetStatistics - Initialize the statistics collected by the `Tao` object.
1339    These statistics include the iteration number, residual norms, and convergence status.
1340    This routine gets called before solving each optimization problem.
1341 
1342    Collective
1343 
1344    Input Parameter:
1345 .  solver - the `Tao` context
1346 
1347    Level: developer
1348 
1349 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
1350 @*/
1351 PetscErrorCode TaoResetStatistics(Tao tao)
1352 {
1353   PetscFunctionBegin;
1354   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1355   tao->niter        = 0;
1356   tao->nfuncs       = 0;
1357   tao->nfuncgrads   = 0;
1358   tao->ngrads       = 0;
1359   tao->nhess        = 0;
1360   tao->njac         = 0;
1361   tao->nconstraints = 0;
1362   tao->ksp_its      = 0;
1363   tao->ksp_tot_its  = 0;
1364   tao->reason       = TAO_CONTINUE_ITERATING;
1365   tao->residual     = 0.0;
1366   tao->cnorm        = 0.0;
1367   tao->step         = 0.0;
1368   tao->lsflag       = PETSC_FALSE;
1369   if (tao->hist_reset) tao->hist_len = 0;
1370   PetscFunctionReturn(PETSC_SUCCESS);
1371 }
1372 
1373 /*@C
1374   TaoSetUpdate - Sets the general-purpose update function called
1375   at the beginning of every iteration of the optimization algorithm. Called after the new solution and the gradient
1376   is determined, but before the Hessian is computed (if applicable).
1377 
1378   Logically Collective
1379 
1380   Input Parameters:
1381 + tao - The `Tao` solver context
1382 - func - The function
1383 
1384   Calling sequence of `func`:
1385 $   PetscErrorCode func(Tao tao, PetscInt step);
1386 + tao - the optimizer context
1387 - step - The current step of the iteration
1388 
1389   Level: advanced
1390 
1391 .seealso: [](ch_tao), `Tao`, `TaoSolve()`
1392 @*/
1393 PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao, PetscInt, void *), void *ctx)
1394 {
1395   PetscFunctionBegin;
1396   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1397   tao->ops->update = func;
1398   tao->user_update = ctx;
1399   PetscFunctionReturn(PETSC_SUCCESS);
1400 }
1401 
1402 /*@C
1403   TaoSetConvergenceTest - Sets the function that is to be used to test
1404   for convergence o fthe iterative minimization solution.  The new convergence
1405   testing routine will replace Tao's default convergence test.
1406 
1407   Logically Collective
1408 
1409   Input Parameters:
1410 + tao - the `Tao` object
1411 . conv - the routine to test for convergence
1412 - ctx - [optional] context for private data for the convergence routine
1413         (may be `NULL`)
1414 
1415   Calling sequence of `conv`:
1416 $   PetscErrorCode conv(Tao tao, void *ctx)
1417 + tao - the `Tao` object
1418 - ctx - [optional] convergence context
1419 
1420   Level: advanced
1421 
1422   Note:
1423   The new convergence testing routine should call `TaoSetConvergedReason()`.
1424 
1425 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoSetMonitor`
1426 @*/
1427 PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao, void *), void *ctx)
1428 {
1429   PetscFunctionBegin;
1430   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1431   tao->ops->convergencetest = conv;
1432   tao->cnvP                 = ctx;
1433   PetscFunctionReturn(PETSC_SUCCESS);
1434 }
1435 
1436 /*@C
1437    TaoSetMonitor - Sets an additional function that is to be used at every
1438    iteration of the solver to display the iteration's
1439    progress.
1440 
1441    Logically Collective
1442 
1443    Input Parameters:
1444 +  tao - the `Tao` solver context
1445 .  func - monitoring routine
1446 .  ctx - [optional] user-defined context for private data for the monitor routine (may be `NULL`)
1447 -  dest - [optional] function to destroy the context when the `Tao` is destroyed
1448 
1449    Calling sequence of `func`:
1450 $     PetscErrorCode func(Tao tao, void *ctx)
1451 +    tao - the `Tao` solver context
1452 -    ctx - [optional] monitoring context
1453 
1454    Calling sequence of `dest`:
1455 $     PetscErrorCode dest(void *ctx)
1456 .    ctx -  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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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    Level: developer
1925 
1926    Notes:
1927    This routine checks the residual in the optimality conditions, the
1928    relative residual in the optimity conditions, the number of function
1929    evaluations, and the function value to test convergence.  Some
1930    solvers may use different convergence routines.
1931 
1932 .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
1933 @*/
1934 PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
1935 {
1936   PetscInt           niter = tao->niter, nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1937   PetscInt           max_funcs = tao->max_funcs;
1938   PetscReal          gnorm = tao->residual, gnorm0 = tao->gnorm0;
1939   PetscReal          f = tao->fc, steptol = tao->steptol, trradius = tao->step;
1940   PetscReal          gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
1941   PetscReal          catol = tao->catol, crtol = tao->crtol;
1942   PetscReal          fmin = tao->fmin, cnorm = tao->cnorm;
1943   TaoConvergedReason reason = tao->reason;
1944 
1945   PetscFunctionBegin;
1946   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
1947   if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);
1948 
1949   if (PetscIsInfOrNanReal(f)) {
1950     PetscCall(PetscInfo(tao, "Failed to converged, function value is Inf or NaN\n"));
1951     reason = TAO_DIVERGED_NAN;
1952   } else if (f <= fmin && cnorm <= catol) {
1953     PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
1954     reason = TAO_CONVERGED_MINF;
1955   } else if (gnorm <= gatol && cnorm <= catol) {
1956     PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
1957     reason = TAO_CONVERGED_GATOL;
1958   } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
1959     PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
1960     reason = TAO_CONVERGED_GRTOL;
1961   } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
1962     PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
1963     reason = TAO_CONVERGED_GTTOL;
1964   } else if (max_funcs >= 0 && nfuncs > max_funcs) {
1965     PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
1966     reason = TAO_DIVERGED_MAXFCN;
1967   } else if (tao->lsflag != 0) {
1968     PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
1969     reason = TAO_DIVERGED_LS_FAILURE;
1970   } else if (trradius < steptol && niter > 0) {
1971     PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
1972     reason = TAO_CONVERGED_STEPTOL;
1973   } else if (niter >= tao->max_it) {
1974     PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
1975     reason = TAO_DIVERGED_MAXITS;
1976   } else {
1977     reason = TAO_CONTINUE_ITERATING;
1978   }
1979   tao->reason = reason;
1980   PetscFunctionReturn(PETSC_SUCCESS);
1981 }
1982 
1983 /*@C
1984    TaoSetOptionsPrefix - Sets the prefix used for searching for all
1985    Tao options in the database.
1986 
1987    Logically Collective
1988 
1989    Input Parameters:
1990 +  tao - the `Tao` context
1991 -  prefix - the prefix string to prepend to all Tao option requests
1992 
1993    Level: advanced
1994 
1995    Notes:
1996    A hyphen (-) must NOT be given at the beginning of the prefix name.
1997    The first character of all runtime options is AUTOMATICALLY the hyphen.
1998 
1999    For example, to distinguish between the runtime options for two
2000    different Tao solvers, one could call
2001 .vb
2002       TaoSetOptionsPrefix(tao1,"sys1_")
2003       TaoSetOptionsPrefix(tao2,"sys2_")
2004 .ve
2005 
2006    This would enable use of different options for each system, such as
2007 .vb
2008       -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2009       -sys2_tao_method lmvm  -sys2_tao_grtol 1.e-4
2010 .ve
2011 
2012 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2013 @*/
2014 PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2015 {
2016   PetscFunctionBegin;
2017   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2018   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2019   if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2020   if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2021   PetscFunctionReturn(PETSC_SUCCESS);
2022 }
2023 
2024 /*@C
2025    TaoAppendOptionsPrefix - Appends to the prefix used for searching for all Tao options in the database.
2026 
2027    Logically Collective
2028 
2029    Input Parameters:
2030 +  tao - the `Tao` solver context
2031 -  prefix - the prefix string to prepend to all `Tao` option requests
2032 
2033    Level: advanced
2034 
2035    Note:
2036    A hyphen (-) must NOT be given at the beginning of the prefix name.
2037    The first character of all runtime options is automatically the hyphen.
2038 
2039 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2040 @*/
2041 PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2042 {
2043   PetscFunctionBegin;
2044   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2045   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2046   if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2047   if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2048   PetscFunctionReturn(PETSC_SUCCESS);
2049 }
2050 
2051 /*@C
2052   TaoGetOptionsPrefix - Gets the prefix used for searching for all
2053   Tao options in the database
2054 
2055   Not Collective
2056 
2057   Input Parameter:
2058 . tao - the `Tao` context
2059 
2060   Output Parameter:
2061 . prefix - pointer to the prefix string used is returned
2062 
2063   Fortran Note:
2064   Pass in a string 'prefix' of sufficient length to hold the prefix.
2065 
2066   Level: advanced
2067 
2068 .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2069 @*/
2070 PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2071 {
2072   PetscFunctionBegin;
2073   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2074   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2075   PetscFunctionReturn(PETSC_SUCCESS);
2076 }
2077 
2078 /*@C
2079    TaoSetType - Sets the `TaoType` for the minimization solver.
2080 
2081    Collective
2082 
2083    Input Parameters:
2084 +  solver - the `Tao` solver context
2085 -  type - a known method
2086 
2087    Options Database Key:
2088 .  -tao_type <type> - Sets the method; use -help for a list
2089    of available methods (for instance, "-tao_type lmvm" or "-tao_type tron")
2090 
2091   Level: intermediate
2092 
2093 .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2094 @*/
2095 PetscErrorCode TaoSetType(Tao tao, TaoType type)
2096 {
2097   PetscErrorCode (*create_xxx)(Tao);
2098   PetscBool issame;
2099 
2100   PetscFunctionBegin;
2101   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2102 
2103   PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2104   if (issame) PetscFunctionReturn(PETSC_SUCCESS);
2105 
2106   PetscCall(PetscFunctionListFind(TaoList, type, (void (**)(void)) & create_xxx));
2107   PetscCheck(create_xxx, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Tao type %s", type);
2108 
2109   /* Destroy the existing solver information */
2110   PetscTryTypeMethod(tao, destroy);
2111   PetscCall(KSPDestroy(&tao->ksp));
2112   PetscCall(TaoLineSearchDestroy(&tao->linesearch));
2113   tao->ops->setup          = NULL;
2114   tao->ops->solve          = NULL;
2115   tao->ops->view           = NULL;
2116   tao->ops->setfromoptions = NULL;
2117   tao->ops->destroy        = NULL;
2118 
2119   tao->setupcalled = PETSC_FALSE;
2120 
2121   PetscCall((*create_xxx)(tao));
2122   PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2123   PetscFunctionReturn(PETSC_SUCCESS);
2124 }
2125 
2126 /*@C
2127    TaoRegister - Adds a method to the Tao package for minimization.
2128 
2129    Not Collective
2130 
2131    Input Parameters:
2132 +  sname - name of a new user-defined solver
2133 -  func - routine to Create method context
2134 
2135    Sample usage:
2136 .vb
2137    TaoRegister("my_solver", MySolverCreate);
2138 .ve
2139 
2140    Then, your solver can be chosen with the procedural interface via
2141 $     TaoSetType(tao, "my_solver")
2142    or at runtime via the option
2143 $     -tao_type my_solver
2144 
2145    Level: advanced
2146 
2147    Note:
2148    `TaoRegister()` may be called multiple times to add several user-defined solvers.
2149 
2150 .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2151 @*/
2152 PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao))
2153 {
2154   PetscFunctionBegin;
2155   PetscCall(TaoInitializePackage());
2156   PetscCall(PetscFunctionListAdd(&TaoList, sname, (void (*)(void))func));
2157   PetscFunctionReturn(PETSC_SUCCESS);
2158 }
2159 
2160 /*@C
2161    TaoRegisterDestroy - Frees the list of minimization solvers that were
2162    registered by `TaoRegister()`.
2163 
2164    Not Collective
2165 
2166    Level: advanced
2167 
2168 .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2169 @*/
2170 PetscErrorCode TaoRegisterDestroy(void)
2171 {
2172   PetscFunctionBegin;
2173   PetscCall(PetscFunctionListDestroy(&TaoList));
2174   TaoRegisterAllCalled = PETSC_FALSE;
2175   PetscFunctionReturn(PETSC_SUCCESS);
2176 }
2177 
2178 /*@
2179    TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2180    at this time.
2181 
2182    Not Collective
2183 
2184    Input Parameter:
2185 .  tao - the `Tao` context
2186 
2187    Output Parameter:
2188 .  iter - iteration number
2189 
2190    Notes:
2191    For example, during the computation of iteration 2 this would return 1.
2192 
2193    Level: intermediate
2194 
2195 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2196 @*/
2197 PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2198 {
2199   PetscFunctionBegin;
2200   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2201   PetscValidIntPointer(iter, 2);
2202   *iter = tao->niter;
2203   PetscFunctionReturn(PETSC_SUCCESS);
2204 }
2205 
2206 /*@
2207    TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2208    at this time.
2209 
2210    Not Collective
2211 
2212    Input Parameter:
2213 .  tao - the `Tao` context
2214 
2215    Output Parameter:
2216 .  value - the current value
2217 
2218    Level: intermediate
2219 
2220    Developer Note:
2221    This is the 2-norm of the residual, we cannot use `TaoGetGradientNorm()` because that has
2222    a different meaning. For some reason `Tao` sometimes calls the gradient the residual.
2223 
2224 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2225 @*/
2226 PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2227 {
2228   PetscFunctionBegin;
2229   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2230   PetscValidRealPointer(value, 2);
2231   *value = tao->residual;
2232   PetscFunctionReturn(PETSC_SUCCESS);
2233 }
2234 
2235 /*@
2236    TaoSetIterationNumber - Sets the current iteration number.
2237 
2238    Logically Collective
2239 
2240    Input Parameters:
2241 +  tao - the `Tao` context
2242 -  iter - iteration number
2243 
2244    Level: developer
2245 
2246 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2247 @*/
2248 PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2249 {
2250   PetscFunctionBegin;
2251   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2252   PetscValidLogicalCollectiveInt(tao, iter, 2);
2253   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2254   tao->niter = iter;
2255   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2256   PetscFunctionReturn(PETSC_SUCCESS);
2257 }
2258 
2259 /*@
2260    TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2261    completed. This number keeps accumulating if multiple solves
2262    are called with the `Tao` object.
2263 
2264    Not Collective
2265 
2266    Input Parameter:
2267 .  tao - the `Tao` context
2268 
2269    Output Parameter:
2270 .  iter - number of iterations
2271 
2272    Level: intermediate
2273 
2274    Note:
2275    The total iteration count is updated after each solve, if there is a current
2276    `TaoSolve()` in progress then those iterations are not included in the count
2277 
2278 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2279 @*/
2280 PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2281 {
2282   PetscFunctionBegin;
2283   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2284   PetscValidIntPointer(iter, 2);
2285   *iter = tao->ntotalits;
2286   PetscFunctionReturn(PETSC_SUCCESS);
2287 }
2288 
2289 /*@
2290    TaoSetTotalIterationNumber - Sets the current total iteration number.
2291 
2292    Logically Collective
2293 
2294    Input Parameters:
2295 +  tao - the `Tao` context
2296 -  iter - the iteration number
2297 
2298    Level: developer
2299 
2300 .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2301 @*/
2302 PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2303 {
2304   PetscFunctionBegin;
2305   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2306   PetscValidLogicalCollectiveInt(tao, iter, 2);
2307   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2308   tao->ntotalits = iter;
2309   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2310   PetscFunctionReturn(PETSC_SUCCESS);
2311 }
2312 
2313 /*@
2314   TaoSetConvergedReason - Sets the termination flag on a `Tao` object
2315 
2316   Logically Collective
2317 
2318   Input Parameters:
2319 + tao - the `Tao` context
2320 - reason - the `TaoConvergedReason`
2321 
2322    Level: intermediate
2323 
2324 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2325 @*/
2326 PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2327 {
2328   PetscFunctionBegin;
2329   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2330   PetscValidLogicalCollectiveEnum(tao, reason, 2);
2331   tao->reason = reason;
2332   PetscFunctionReturn(PETSC_SUCCESS);
2333 }
2334 
2335 /*@
2336    TaoGetConvergedReason - Gets the reason the `TaoSolve()` was stopped.
2337 
2338    Not Collective
2339 
2340    Input Parameter:
2341 .  tao - the `Tao` solver context
2342 
2343    Output Parameter:
2344 .  reason - value of `TaoConvergedReason`
2345 
2346    Level: intermediate
2347 
2348 .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`
2349 @*/
2350 PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2351 {
2352   PetscFunctionBegin;
2353   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2354   PetscValidPointer(reason, 2);
2355   *reason = tao->reason;
2356   PetscFunctionReturn(PETSC_SUCCESS);
2357 }
2358 
2359 /*@
2360    TaoGetSolutionStatus - Get the current iterate, objective value,
2361    residual, infeasibility, and termination from a `Tao` object
2362 
2363    Not Collective
2364 
2365    Input Parameter:
2366 .  tao - the `Tao` context
2367 
2368    Output Parameters:
2369 +  iterate - the current iterate number (>=0)
2370 .  f - the current function value
2371 .  gnorm - the square of the gradient norm, duality gap, or other measure indicating distance from optimality.
2372 .  cnorm - the infeasibility of the current solution with regard to the constraints.
2373 .  xdiff - the step length or trust region radius of the most recent iterate.
2374 -  reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`
2375 
2376    Level: intermediate
2377 
2378    Notes:
2379    Tao returns the values set by the solvers in the routine `TaoMonitor()`.
2380 
2381    If any of the output arguments are set to `NULL`, no corresponding value will be returned.
2382 
2383 .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2384 @*/
2385 PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2386 {
2387   PetscFunctionBegin;
2388   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2389   if (its) *its = tao->niter;
2390   if (f) *f = tao->fc;
2391   if (gnorm) *gnorm = tao->residual;
2392   if (cnorm) *cnorm = tao->cnorm;
2393   if (reason) *reason = tao->reason;
2394   if (xdiff) *xdiff = tao->step;
2395   PetscFunctionReturn(PETSC_SUCCESS);
2396 }
2397 
2398 /*@C
2399    TaoGetType - Gets the current `TaoType` being used in the `Tao` object
2400 
2401    Not Collective
2402 
2403    Input Parameter:
2404 .  tao - the `Tao` solver context
2405 
2406    Output Parameter:
2407 .  type - the `TaoType`
2408 
2409    Level: intermediate
2410 
2411 .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`
2412 @*/
2413 PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2414 {
2415   PetscFunctionBegin;
2416   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2417   PetscValidPointer(type, 2);
2418   *type = ((PetscObject)tao)->type_name;
2419   PetscFunctionReturn(PETSC_SUCCESS);
2420 }
2421 
2422 /*@C
2423   TaoMonitor - Monitor the solver and the current solution.  This
2424   routine will record the iteration number and residual statistics,
2425   and call any monitors specified by the user.
2426 
2427    Input Parameters:
2428 +  tao - the `Tao` context
2429 .  its - the current iterate number (>=0)
2430 .  f - the current objective function value
2431 .  res - the gradient norm, square root of the duality gap, or other measure indicating distince from optimality.  This measure will be recorded and
2432           used for some termination tests.
2433 .  cnorm - the infeasibility of the current solution with regard to the constraints.
2434 -  steplength - multiple of the step direction added to the previous iterate.
2435 
2436    Options Database Key:
2437 .  -tao_monitor - Use the default monitor, which prints statistics to standard output
2438 
2439    Level: developer
2440 
2441 .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoSetMonitor()`
2442 @*/
2443 PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2444 {
2445   PetscInt i;
2446 
2447   PetscFunctionBegin;
2448   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2449   tao->fc       = f;
2450   tao->residual = res;
2451   tao->cnorm    = cnorm;
2452   tao->step     = steplength;
2453   if (!its) {
2454     tao->cnorm0 = cnorm;
2455     tao->gnorm0 = res;
2456   }
2457   PetscCall(VecLockReadPush(tao->solution));
2458   for (i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2459   PetscCall(VecLockReadPop(tao->solution));
2460   PetscFunctionReturn(PETSC_SUCCESS);
2461 }
2462 
2463 /*@
2464    TaoSetConvergenceHistory - Sets the array used to hold the convergence history.
2465 
2466    Logically Collective
2467 
2468    Input Parameters:
2469 +  tao - the `Tao` solver context
2470 .  obj   - array to hold objective value history
2471 .  resid - array to hold residual history
2472 .  cnorm - array to hold constraint violation history
2473 .  lits - integer array holds the number of linear iterations for each Tao iteration
2474 .  na  - size of `obj`, `resid`, and `cnorm`
2475 -  reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2476            else it continues storing new values for new minimizations after the old ones
2477 
2478    Level: intermediate
2479 
2480    Notes:
2481    If set, `Tao` will fill the given arrays with the indicated
2482    information at each iteration.  If 'obj','resid','cnorm','lits' are
2483    *all* `NULL` then space (using size `na`, or 1000 if na is `PETSC_DECIDE` or
2484    `PETSC_DEFAULT`) is allocated for the history.
2485    If not all are `NULL`, then only the non-`NULL` information categories
2486    will be stored, the others will be ignored.
2487 
2488    Any convergence information after iteration number 'na' will not be stored.
2489 
2490    This routine is useful, e.g., when running a code for purposes
2491    of accurate performance monitoring, when no I/O should be done
2492    during the section of code that is being timed.
2493 
2494 .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2495 @*/
2496 PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2497 {
2498   PetscFunctionBegin;
2499   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2500   if (obj) PetscValidRealPointer(obj, 2);
2501   if (resid) PetscValidRealPointer(resid, 3);
2502   if (cnorm) PetscValidRealPointer(cnorm, 4);
2503   if (lits) PetscValidIntPointer(lits, 5);
2504 
2505   if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
2506   if (!obj && !resid && !cnorm && !lits) {
2507     PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2508     tao->hist_malloc = PETSC_TRUE;
2509   }
2510 
2511   tao->hist_obj   = obj;
2512   tao->hist_resid = resid;
2513   tao->hist_cnorm = cnorm;
2514   tao->hist_lits  = lits;
2515   tao->hist_max   = na;
2516   tao->hist_reset = reset;
2517   tao->hist_len   = 0;
2518   PetscFunctionReturn(PETSC_SUCCESS);
2519 }
2520 
2521 /*@C
2522    TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.
2523 
2524    Collective
2525 
2526    Input Parameter:
2527 .  tao - the `Tao` context
2528 
2529    Output Parameters:
2530 +  obj   - array used to hold objective value history
2531 .  resid - array used to hold residual history
2532 .  cnorm - array used to hold constraint violation history
2533 .  lits  - integer array used to hold linear solver iteration count
2534 -  nhist  - size of `obj`, `resid`, `cnorm`, and `lits`
2535 
2536    Level: advanced
2537 
2538    Notes:
2539     This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2540     and `TaoSolve()`, otherwise it returns useless information.
2541 
2542    This routine is useful, e.g., when running a code for purposes
2543    of accurate performance monitoring, when no I/O should be done
2544    during the section of code that is being timed.
2545 
2546    Fortran Note:
2547    The calling sequence is
2548 .vb
2549    call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2550 .ve
2551 
2552 .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2553 @*/
2554 PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2555 {
2556   PetscFunctionBegin;
2557   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2558   if (obj) *obj = tao->hist_obj;
2559   if (cnorm) *cnorm = tao->hist_cnorm;
2560   if (resid) *resid = tao->hist_resid;
2561   if (lits) *lits = tao->hist_lits;
2562   if (nhist) *nhist = tao->hist_len;
2563   PetscFunctionReturn(PETSC_SUCCESS);
2564 }
2565 
2566 /*@
2567    TaoSetApplicationContext - Sets the optional user-defined context for a `Tao` solver.
2568 
2569    Logically Collective
2570 
2571    Input Parameters:
2572 +  tao  - the `Tao` context
2573 -  usrP - optional user context
2574 
2575    Level: intermediate
2576 
2577 .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`, `TaoSetApplicationContext()`
2578 @*/
2579 PetscErrorCode TaoSetApplicationContext(Tao tao, void *usrP)
2580 {
2581   PetscFunctionBegin;
2582   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2583   tao->user = usrP;
2584   PetscFunctionReturn(PETSC_SUCCESS);
2585 }
2586 
2587 /*@
2588    TaoGetApplicationContext - Gets the user-defined context for a `Tao` solver
2589 
2590    Not Collective
2591 
2592    Input Parameter:
2593 .  tao  - the `Tao` context
2594 
2595    Output Parameter:
2596 .  usrP - user context
2597 
2598    Level: intermediate
2599 
2600 .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2601 @*/
2602 PetscErrorCode TaoGetApplicationContext(Tao tao, void *usrP)
2603 {
2604   PetscFunctionBegin;
2605   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2606   PetscValidPointer(usrP, 2);
2607   *(void **)usrP = tao->user;
2608   PetscFunctionReturn(PETSC_SUCCESS);
2609 }
2610 
2611 /*@
2612    TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient.
2613 
2614    Collective
2615 
2616    Input Parameters:
2617 +  tao  - the `Tao` context
2618 -  M    - matrix that defines the norm
2619 
2620    Level: beginner
2621 
2622 .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2623 @*/
2624 PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2625 {
2626   PetscFunctionBegin;
2627   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2628   PetscValidHeaderSpecific(M, MAT_CLASSID, 2);
2629   PetscCall(PetscObjectReference((PetscObject)M));
2630   PetscCall(MatDestroy(&tao->gradient_norm));
2631   PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2632   tao->gradient_norm = M;
2633   PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2634   PetscFunctionReturn(PETSC_SUCCESS);
2635 }
2636 
2637 /*@
2638    TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient.
2639 
2640    Not Collective
2641 
2642    Input Parameter:
2643 .  tao  - the `Tao` context
2644 
2645    Output Parameter:
2646 .  M - gradient norm
2647 
2648    Level: beginner
2649 
2650 .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2651 @*/
2652 PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2653 {
2654   PetscFunctionBegin;
2655   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2656   PetscValidPointer(M, 2);
2657   *M = tao->gradient_norm;
2658   PetscFunctionReturn(PETSC_SUCCESS);
2659 }
2660 
2661 /*@C
2662    TaoGradientNorm - Compute the norm using the `NormType`, the user has selected
2663 
2664    Collective
2665 
2666    Input Parameters:
2667 +  tao      - the `Tao` context
2668 .  gradient - the gradient to be computed
2669 -  norm     - the norm type
2670 
2671    Output Parameter:
2672 .  gnorm    - the gradient norm
2673 
2674    Level: advanced
2675 
2676 .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2677 @*/
2678 PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2679 {
2680   PetscFunctionBegin;
2681   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
2682   PetscValidHeaderSpecific(gradient, VEC_CLASSID, 2);
2683   PetscValidLogicalCollectiveEnum(tao, type, 3);
2684   PetscValidRealPointer(gnorm, 4);
2685   if (tao->gradient_norm) {
2686     PetscScalar gnorms;
2687 
2688     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.");
2689     PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2690     PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2691     *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2692   } else {
2693     PetscCall(VecNorm(gradient, type, gnorm));
2694   }
2695   PetscFunctionReturn(PETSC_SUCCESS);
2696 }
2697 
2698 /*@C
2699    TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorDrawSolution()`
2700 
2701    Collective
2702 
2703    Input Parameters:
2704 +  comm - the communicator to share the context
2705 .  host - the name of the X Windows host that will display the monitor
2706 .  label - the label to put at the top of the display window
2707 .  x - the horizontal coordinate of the lower left corner of the window to open
2708 .  y - the vertical coordinate of the lower left corner of the window to open
2709 .  m - the width of the window
2710 .  n - the height of the window
2711 -  howoften - how many `Tao` iterations between displaying the monitor information
2712 
2713    Output Parameter:
2714 .    ctx - the monitor context
2715 
2716    Options Database Key:
2717 .   -tao_draw_solution_initial - show initial guess as well as current solution
2718 
2719    Level: intermediate
2720 
2721 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2722 @*/
2723 PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2724 {
2725   PetscFunctionBegin;
2726   PetscCall(PetscNew(ctx));
2727   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
2728   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
2729   (*ctx)->howoften = howoften;
2730   PetscFunctionReturn(PETSC_SUCCESS);
2731 }
2732 
2733 /*@C
2734    TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorDrawSolution()`
2735 
2736    Collective
2737 
2738    Input Parameter:
2739 .    ctx - the monitor context
2740 
2741    Level: intermediate
2742 
2743 .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawSolution()`
2744 @*/
2745 PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2746 {
2747   PetscFunctionBegin;
2748   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
2749   PetscCall(PetscFree(*ictx));
2750   PetscFunctionReturn(PETSC_SUCCESS);
2751 }
2752