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