Actual source code: taosolver.c
1: #include <petsc/private/taoimpl.h>
2: #include <petsc/private/snesimpl.h>
4: PetscBool TaoRegisterAllCalled = PETSC_FALSE;
5: PetscFunctionList TaoList = NULL;
7: PetscClassId TAO_CLASSID;
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;
17: const char *TaoSubSetTypes[] = {"subvec", "mask", "matrixfree", "TaoSubSetType", "TAO_SUBSET_", NULL};
19: struct _n_TaoMonitorDrawCtx {
20: PetscViewer viewer;
21: PetscInt howoften; /* when > 0 uses iteration % howoften, when negative only final solution plotted */
22: };
24: static PetscErrorCode KSPPreSolve_TAOEW_Private(KSP ksp, Vec b, Vec x, Tao tao)
25: {
26: SNES snes_ewdummy = tao->snes_ewdummy;
28: PetscFunctionBegin;
29: if (!snes_ewdummy) PetscFunctionReturn(PETSC_SUCCESS);
30: /* populate snes_ewdummy struct values used in KSPPreSolve_SNESEW */
31: snes_ewdummy->vec_func = b;
32: snes_ewdummy->rtol = tao->gttol;
33: snes_ewdummy->iter = tao->niter;
34: PetscCall(VecNorm(b, NORM_2, &snes_ewdummy->norm));
35: PetscCall(KSPPreSolve_SNESEW(ksp, b, x, snes_ewdummy));
36: snes_ewdummy->vec_func = NULL;
37: PetscFunctionReturn(PETSC_SUCCESS);
38: }
40: static PetscErrorCode KSPPostSolve_TAOEW_Private(KSP ksp, Vec b, Vec x, Tao tao)
41: {
42: SNES snes_ewdummy = tao->snes_ewdummy;
44: PetscFunctionBegin;
45: if (!snes_ewdummy) PetscFunctionReturn(PETSC_SUCCESS);
46: PetscCall(KSPPostSolve_SNESEW(ksp, b, x, snes_ewdummy));
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: static PetscErrorCode TaoSetUpEW_Private(Tao tao)
51: {
52: SNESKSPEW *kctx;
53: const char *ewprefix;
55: PetscFunctionBegin;
56: if (!tao->ksp) PetscFunctionReturn(PETSC_SUCCESS);
57: if (tao->ksp_ewconv) {
58: if (!tao->snes_ewdummy) PetscCall(SNESCreate(PetscObjectComm((PetscObject)tao), &tao->snes_ewdummy));
59: tao->snes_ewdummy->ksp_ewconv = PETSC_TRUE;
60: PetscCall(KSPSetPreSolve(tao->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_TAOEW_Private, tao));
61: PetscCall(KSPSetPostSolve(tao->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_TAOEW_Private, tao));
63: PetscCall(KSPGetOptionsPrefix(tao->ksp, &ewprefix));
64: kctx = (SNESKSPEW *)tao->snes_ewdummy->kspconvctx;
65: PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_FALSE, PetscObjectComm((PetscObject)tao), ewprefix));
66: } else PetscCall(SNESDestroy(&tao->snes_ewdummy));
67: PetscFunctionReturn(PETSC_SUCCESS);
68: }
70: /*@
71: TaoCreate - Creates a Tao solver
73: Collective
75: Input Parameter:
76: . comm - MPI communicator
78: Output Parameter:
79: . newtao - the new `Tao` context
81: Options Database Key:
82: . -tao_type - select which method Tao should use
84: Level: beginner
86: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoDestroy()`, `TAOSetFromOptions()`, `TAOSetType()`
87: @*/
88: PetscErrorCode TaoCreate(MPI_Comm comm, Tao *newtao)
89: {
90: Tao tao;
92: PetscFunctionBegin;
93: PetscAssertPointer(newtao, 2);
94: PetscCall(TaoInitializePackage());
95: PetscCall(TaoLineSearchInitializePackage());
96: PetscCall(PetscHeaderCreate(tao, TAO_CLASSID, "Tao", "Optimization solver", "Tao", comm, TaoDestroy, TaoView));
98: /* Set non-NULL defaults */
99: tao->ops->convergencetest = TaoDefaultConvergenceTest;
101: tao->max_it = 10000;
102: tao->max_funcs = -1;
103: #if defined(PETSC_USE_REAL_SINGLE)
104: tao->gatol = 1e-5;
105: tao->grtol = 1e-5;
106: tao->crtol = 1e-5;
107: tao->catol = 1e-5;
108: #else
109: tao->gatol = 1e-8;
110: tao->grtol = 1e-8;
111: tao->crtol = 1e-8;
112: tao->catol = 1e-8;
113: #endif
114: tao->gttol = 0.0;
115: tao->steptol = 0.0;
116: tao->trust0 = PETSC_INFINITY;
117: tao->fmin = PETSC_NINFINITY;
119: tao->hist_reset = PETSC_TRUE;
121: PetscCall(TaoResetStatistics(tao));
122: *newtao = tao;
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
126: /*@
127: TaoSolve - Solves an optimization problem min F(x) s.t. l <= x <= u
129: Collective
131: Input Parameter:
132: . tao - the `Tao` context
134: Level: beginner
136: Notes:
137: The user must set up the `Tao` object with calls to `TaoSetSolution()`, `TaoSetObjective()`, `TaoSetGradient()`, and (if using 2nd order method) `TaoSetHessian()`.
139: You should call `TaoGetConvergedReason()` or run with `-tao_converged_reason` to determine if the optimization algorithm actually succeeded or
140: why it failed.
142: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoGetConvergedReason()`, `TaoSetUp()`
143: @*/
144: PetscErrorCode TaoSolve(Tao tao)
145: {
146: static PetscBool set = PETSC_FALSE;
148: PetscFunctionBegin;
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));
163: PetscCall(PetscLogEventBegin(TAO_Solve, tao, 0, 0, 0));
164: PetscTryTypeMethod(tao, solve);
165: PetscCall(PetscLogEventEnd(TAO_Solve, tao, 0, 0, 0));
167: PetscCall(VecViewFromOptions(tao->solution, (PetscObject)tao, "-tao_view_solution"));
169: tao->ntotalits += tao->niter;
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: }
185: /*@
186: TaoSetUp - Sets up the internal data structures for the later use
187: of a Tao solver
189: Collective
191: Input Parameter:
192: . tao - the `Tao` context
194: Level: advanced
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()`.
202: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
203: @*/
204: PetscErrorCode TaoSetUp(Tao tao)
205: {
206: PetscFunctionBegin;
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: }
216: /*@C
217: TaoDestroy - Destroys the `Tao` context that was created with `TaoCreate()`
219: Collective
221: Input Parameter:
222: . tao - the `Tao` context
224: Level: beginner
226: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
227: @*/
228: PetscErrorCode TaoDestroy(Tao *tao)
229: {
230: PetscFunctionBegin;
231: if (!*tao) PetscFunctionReturn(PETSC_SUCCESS);
233: if (--((PetscObject)*tao)->refct > 0) {
234: *tao = NULL;
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: if ((*tao)->ops->destroy) PetscCall((*((*tao))->ops->destroy)(*tao));
239: PetscCall(KSPDestroy(&(*tao)->ksp));
240: PetscCall(SNESDestroy(&(*tao)->snes_ewdummy));
241: PetscCall(TaoLineSearchDestroy(&(*tao)->linesearch));
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));
251: if ((*tao)->gradient_norm) {
252: PetscCall(PetscObjectDereference((PetscObject)(*tao)->gradient_norm));
253: PetscCall(VecDestroy(&(*tao)->gradient_norm_tmp));
254: }
256: PetscCall(VecDestroy(&(*tao)->XL));
257: PetscCall(VecDestroy(&(*tao)->XU));
258: PetscCall(VecDestroy(&(*tao)->IL));
259: PetscCall(VecDestroy(&(*tao)->IU));
260: PetscCall(VecDestroy(&(*tao)->DE));
261: PetscCall(VecDestroy(&(*tao)->DI));
262: PetscCall(VecDestroy(&(*tao)->constraints));
263: PetscCall(VecDestroy(&(*tao)->constraints_equality));
264: PetscCall(VecDestroy(&(*tao)->constraints_inequality));
265: PetscCall(VecDestroy(&(*tao)->stepdirection));
266: PetscCall(MatDestroy(&(*tao)->hessian_pre));
267: PetscCall(MatDestroy(&(*tao)->hessian));
268: PetscCall(MatDestroy(&(*tao)->ls_jac));
269: PetscCall(MatDestroy(&(*tao)->ls_jac_pre));
270: PetscCall(MatDestroy(&(*tao)->jacobian_pre));
271: PetscCall(MatDestroy(&(*tao)->jacobian));
272: PetscCall(MatDestroy(&(*tao)->jacobian_state_pre));
273: PetscCall(MatDestroy(&(*tao)->jacobian_state));
274: PetscCall(MatDestroy(&(*tao)->jacobian_state_inv));
275: PetscCall(MatDestroy(&(*tao)->jacobian_design));
276: PetscCall(MatDestroy(&(*tao)->jacobian_equality));
277: PetscCall(MatDestroy(&(*tao)->jacobian_equality_pre));
278: PetscCall(MatDestroy(&(*tao)->jacobian_inequality));
279: PetscCall(MatDestroy(&(*tao)->jacobian_inequality_pre));
280: PetscCall(ISDestroy(&(*tao)->state_is));
281: PetscCall(ISDestroy(&(*tao)->design_is));
282: PetscCall(VecDestroy(&(*tao)->res_weights_v));
283: PetscCall(TaoCancelMonitors(*tao));
284: if ((*tao)->hist_malloc) PetscCall(PetscFree4((*tao)->hist_obj, (*tao)->hist_resid, (*tao)->hist_cnorm, (*tao)->hist_lits));
285: if ((*tao)->res_weights_n) {
286: PetscCall(PetscFree((*tao)->res_weights_rows));
287: PetscCall(PetscFree((*tao)->res_weights_cols));
288: PetscCall(PetscFree((*tao)->res_weights_w));
289: }
290: PetscCall(PetscHeaderDestroy(tao));
291: PetscFunctionReturn(PETSC_SUCCESS);
292: }
294: /*@
295: TaoKSPSetUseEW - Sets `SNES` to use Eisenstat-Walker method {cite}`ew96`for computing relative tolerance for linear solvers.
297: Logically Collective
299: Input Parameters:
300: + tao - Tao context
301: - flag - `PETSC_TRUE` or `PETSC_FALSE`
303: Level: advanced
305: Note:
306: See `SNESKSPSetUseEW()` for customization details.
308: .seealso: [](ch_tao), `Tao`, `SNESKSPSetUseEW()`
309: @*/
310: PetscErrorCode TaoKSPSetUseEW(Tao tao, PetscBool flag)
311: {
312: PetscFunctionBegin;
315: tao->ksp_ewconv = flag;
316: PetscFunctionReturn(PETSC_SUCCESS);
317: }
319: /*@
320: TaoSetFromOptions - Sets various Tao parameters from the options database
322: Collective
324: Input Parameter:
325: . tao - the `Tao` solver context
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_monitor - prints function value and residual norm at each iteration
338: . -tao_smonitor - same as tao_monitor, but truncates very small values
339: . -tao_cmonitor - prints function value, residual, and constraint norm at each iteration
340: . -tao_view_solution - prints solution vector at each iteration
341: . -tao_view_ls_residual - prints least-squares residual vector at each iteration
342: . -tao_view_stepdirection - prints step direction vector at each iteration
343: . -tao_view_gradient - prints gradient vector at each iteration
344: . -tao_draw_solution - graphically view solution vector at each iteration
345: . -tao_draw_step - graphically view step vector at each iteration
346: . -tao_draw_gradient - graphically view gradient at each iteration
347: . -tao_fd_gradient - use gradient computed with finite differences
348: . -tao_fd_hessian - use hessian computed with finite differences
349: . -tao_mf_hessian - use matrix-free hessian computed with finite differences
350: . -tao_cancelmonitors - cancels all monitors (except those set with command line)
351: . -tao_view - prints information about the Tao after solving
352: - -tao_converged_reason - prints the reason Tao stopped iterating
354: Level: beginner
356: Note:
357: To see all options, run your program with the `-help` option or consult the
358: user's manual. Should be called after `TaoCreate()` but before `TaoSolve()`
360: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
361: @*/
362: PetscErrorCode TaoSetFromOptions(Tao tao)
363: {
364: TaoType default_type = TAOLMVM;
365: char type[256], monfilename[PETSC_MAX_PATH_LEN];
366: PetscViewer monviewer;
367: PetscBool flg;
368: MPI_Comm comm;
370: PetscFunctionBegin;
372: PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
374: if (((PetscObject)tao)->type_name) default_type = ((PetscObject)tao)->type_name;
376: PetscObjectOptionsBegin((PetscObject)tao);
377: /* Check for type from options */
378: PetscCall(PetscOptionsFList("-tao_type", "Tao Solver type", "TaoSetType", TaoList, default_type, type, 256, &flg));
379: if (flg) {
380: PetscCall(TaoSetType(tao, type));
381: } else if (!((PetscObject)tao)->type_name) {
382: PetscCall(TaoSetType(tao, default_type));
383: }
385: /* Tao solvers do not set the prefix, set it here if not yet done
386: We do it after SetType since solver may have been changed */
387: if (tao->linesearch) {
388: const char *prefix;
389: PetscCall(TaoLineSearchGetOptionsPrefix(tao->linesearch, &prefix));
390: if (!prefix) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, ((PetscObject)(tao))->prefix));
391: }
393: PetscCall(PetscOptionsReal("-tao_catol", "Stop if constraints violations within", "TaoSetConstraintTolerances", tao->catol, &tao->catol, &flg));
394: if (flg) tao->catol_changed = PETSC_TRUE;
395: PetscCall(PetscOptionsReal("-tao_crtol", "Stop if relative constraint violations within", "TaoSetConstraintTolerances", tao->crtol, &tao->crtol, &flg));
396: if (flg) tao->crtol_changed = PETSC_TRUE;
397: PetscCall(PetscOptionsReal("-tao_gatol", "Stop if norm of gradient less than", "TaoSetTolerances", tao->gatol, &tao->gatol, &flg));
398: if (flg) tao->gatol_changed = PETSC_TRUE;
399: PetscCall(PetscOptionsReal("-tao_grtol", "Stop if norm of gradient divided by the function value is less than", "TaoSetTolerances", tao->grtol, &tao->grtol, &flg));
400: if (flg) tao->grtol_changed = PETSC_TRUE;
401: 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));
402: if (flg) tao->gttol_changed = PETSC_TRUE;
403: PetscCall(PetscOptionsInt("-tao_max_it", "Stop if iteration number exceeds", "TaoSetMaximumIterations", tao->max_it, &tao->max_it, &flg));
404: if (flg) tao->max_it_changed = PETSC_TRUE;
405: PetscCall(PetscOptionsInt("-tao_max_funcs", "Stop if number of function evaluations exceeds", "TaoSetMaximumFunctionEvaluations", tao->max_funcs, &tao->max_funcs, &flg));
406: if (flg) tao->max_funcs_changed = PETSC_TRUE;
407: PetscCall(PetscOptionsReal("-tao_fmin", "Stop if function less than", "TaoSetFunctionLowerBound", tao->fmin, &tao->fmin, &flg));
408: if (flg) tao->fmin_changed = PETSC_TRUE;
409: PetscCall(PetscOptionsReal("-tao_steptol", "Stop if step size or trust region radius less than", "", tao->steptol, &tao->steptol, &flg));
410: if (flg) tao->steptol_changed = PETSC_TRUE;
411: PetscCall(PetscOptionsReal("-tao_trust0", "Initial trust region radius", "TaoSetTrustRegionRadius", tao->trust0, &tao->trust0, &flg));
412: if (flg) tao->trust0_changed = PETSC_TRUE;
413: PetscCall(PetscOptionsString("-tao_view_solution", "view solution vector after each evaluation", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
414: if (flg) {
415: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
416: PetscCall(TaoSetMonitor(tao, TaoSolutionMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
417: }
419: PetscCall(PetscOptionsBool("-tao_converged_reason", "Print reason for Tao converged", "TaoSolve", tao->printreason, &tao->printreason, NULL));
420: PetscCall(PetscOptionsString("-tao_view_gradient", "view gradient vector after each evaluation", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
421: if (flg) {
422: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
423: PetscCall(TaoSetMonitor(tao, TaoGradientMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
424: }
426: PetscCall(PetscOptionsString("-tao_view_stepdirection", "view step direction vector after each iteration", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
427: if (flg) {
428: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
429: PetscCall(TaoSetMonitor(tao, TaoStepDirectionMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
430: }
432: PetscCall(PetscOptionsString("-tao_view_residual", "view least-squares residual vector after each evaluation", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
433: if (flg) {
434: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
435: PetscCall(TaoSetMonitor(tao, TaoResidualMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
436: }
438: PetscCall(PetscOptionsString("-tao_monitor", "Use the default convergence monitor", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
439: if (flg) {
440: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
441: PetscCall(TaoSetMonitor(tao, TaoMonitorDefault, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
442: }
444: PetscCall(PetscOptionsString("-tao_gmonitor", "Use the convergence monitor with extra globalization info", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
445: if (flg) {
446: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
447: PetscCall(TaoSetMonitor(tao, TaoDefaultGMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
448: }
450: PetscCall(PetscOptionsString("-tao_smonitor", "Use the short convergence monitor", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
451: if (flg) {
452: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
453: PetscCall(TaoSetMonitor(tao, TaoDefaultSMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
454: }
456: PetscCall(PetscOptionsString("-tao_cmonitor", "Use the default convergence monitor with constraint norm", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
457: if (flg) {
458: PetscCall(PetscViewerASCIIOpen(comm, monfilename, &monviewer));
459: PetscCall(TaoSetMonitor(tao, TaoDefaultCMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy));
460: }
462: flg = PETSC_FALSE;
463: PetscCall(PetscOptionsBool("-tao_cancelmonitors", "cancel all monitors and call any registered destroy routines", "TaoCancelMonitors", flg, &flg, NULL));
464: if (flg) PetscCall(TaoCancelMonitors(tao));
466: flg = PETSC_FALSE;
467: PetscCall(PetscOptionsBool("-tao_draw_solution", "Plot solution vector at each iteration", "TaoSetMonitor", flg, &flg, NULL));
468: if (flg) {
469: TaoMonitorDrawCtx drawctx;
470: PetscInt howoften = 1;
471: PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
472: PetscCall(TaoSetMonitor(tao, TaoDrawSolutionMonitor, drawctx, (PetscErrorCode(*)(void **))TaoMonitorDrawCtxDestroy));
473: }
475: flg = PETSC_FALSE;
476: PetscCall(PetscOptionsBool("-tao_draw_step", "plots step direction at each iteration", "TaoSetMonitor", flg, &flg, NULL));
477: if (flg) PetscCall(TaoSetMonitor(tao, TaoDrawStepMonitor, NULL, NULL));
479: flg = PETSC_FALSE;
480: PetscCall(PetscOptionsBool("-tao_draw_gradient", "plots gradient at each iteration", "TaoSetMonitor", flg, &flg, NULL));
481: if (flg) {
482: TaoMonitorDrawCtx drawctx;
483: PetscInt howoften = 1;
484: PetscCall(TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx));
485: PetscCall(TaoSetMonitor(tao, TaoDrawGradientMonitor, drawctx, (PetscErrorCode(*)(void **))TaoMonitorDrawCtxDestroy));
486: }
487: flg = PETSC_FALSE;
488: PetscCall(PetscOptionsBool("-tao_fd_gradient", "compute gradient using finite differences", "TaoDefaultComputeGradient", flg, &flg, NULL));
489: if (flg) PetscCall(TaoSetGradient(tao, NULL, TaoDefaultComputeGradient, NULL));
490: flg = PETSC_FALSE;
491: PetscCall(PetscOptionsBool("-tao_fd_hessian", "compute hessian using finite differences", "TaoDefaultComputeHessian", flg, &flg, NULL));
492: if (flg) {
493: Mat H;
495: PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
496: PetscCall(MatSetType(H, MATAIJ));
497: PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessian, NULL));
498: PetscCall(MatDestroy(&H));
499: }
500: flg = PETSC_FALSE;
501: PetscCall(PetscOptionsBool("-tao_mf_hessian", "compute matrix-free hessian using finite differences", "TaoDefaultComputeHessianMFFD", flg, &flg, NULL));
502: if (flg) {
503: Mat H;
505: PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &H));
506: PetscCall(TaoSetHessian(tao, H, H, TaoDefaultComputeHessianMFFD, NULL));
507: PetscCall(MatDestroy(&H));
508: }
509: flg = PETSC_FALSE;
510: PetscCall(PetscOptionsBool("-tao_recycle_history", "enable recycling/re-using information from the previous TaoSolve() call for some algorithms", "TaoSetRecycleHistory", flg, &flg, NULL));
511: if (flg) PetscCall(TaoSetRecycleHistory(tao, PETSC_TRUE));
512: PetscCall(PetscOptionsEnum("-tao_subset_type", "subset type", "", TaoSubSetTypes, (PetscEnum)tao->subset_type, (PetscEnum *)&tao->subset_type, NULL));
514: if (tao->ksp) {
515: PetscCall(PetscOptionsBool("-tao_ksp_ew", "Use Eisentat-Walker linear system convergence test", "TaoKSPSetUseEW", tao->ksp_ewconv, &tao->ksp_ewconv, NULL));
516: PetscCall(TaoKSPSetUseEW(tao, tao->ksp_ewconv));
517: }
519: PetscTryTypeMethod(tao, setfromoptions, PetscOptionsObject);
521: /* process any options handlers added with PetscObjectAddOptionsHandler() */
522: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)tao, PetscOptionsObject));
523: PetscOptionsEnd();
525: if (tao->linesearch) PetscCall(TaoLineSearchSetFromOptions(tao->linesearch));
526: PetscFunctionReturn(PETSC_SUCCESS);
527: }
529: /*@C
530: TaoViewFromOptions - View a `Tao` object based on values in the options database
532: Collective
534: Input Parameters:
535: + A - the `Tao` context
536: . obj - Optional object that provides the prefix for the options database
537: - name - command line option
539: Level: intermediate
541: .seealso: [](ch_tao), `Tao`, `TaoView`, `PetscObjectViewFromOptions()`, `TaoCreate()`
542: @*/
543: PetscErrorCode TaoViewFromOptions(Tao A, PetscObject obj, const char name[])
544: {
545: PetscFunctionBegin;
547: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
548: PetscFunctionReturn(PETSC_SUCCESS);
549: }
551: /*@C
552: TaoView - Prints information about the `Tao` object
554: Collective
556: Input Parameters:
557: + tao - the `Tao` context
558: - viewer - visualization context
560: Options Database Key:
561: . -tao_view - Calls `TaoView()` at the end of `TaoSolve()`
563: Level: beginner
565: Notes:
566: The available visualization contexts include
567: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
568: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
569: output where only the first processor opens
570: the file. All other processors send their
571: data to the first processor to print.
573: .seealso: [](ch_tao), `Tao`, `PetscViewerASCIIOpen()`
574: @*/
575: PetscErrorCode TaoView(Tao tao, PetscViewer viewer)
576: {
577: PetscBool isascii, isstring;
578: TaoType type;
580: PetscFunctionBegin;
582: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)tao)->comm, &viewer));
584: PetscCheckSameComm(tao, 1, viewer, 2);
586: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
587: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
588: if (isascii) {
589: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)tao, viewer));
591: if (tao->ops->view) {
592: PetscCall(PetscViewerASCIIPushTab(viewer));
593: PetscUseTypeMethod(tao, view, viewer);
594: PetscCall(PetscViewerASCIIPopTab(viewer));
595: }
596: if (tao->linesearch) {
597: PetscCall(PetscViewerASCIIPushTab(viewer));
598: PetscCall(TaoLineSearchView(tao->linesearch, viewer));
599: PetscCall(PetscViewerASCIIPopTab(viewer));
600: }
601: if (tao->ksp) {
602: PetscCall(PetscViewerASCIIPushTab(viewer));
603: PetscCall(KSPView(tao->ksp, viewer));
604: PetscCall(PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", tao->ksp_tot_its));
605: PetscCall(PetscViewerASCIIPopTab(viewer));
606: }
608: PetscCall(PetscViewerASCIIPushTab(viewer));
610: if (tao->XL || tao->XU) PetscCall(PetscViewerASCIIPrintf(viewer, "Active Set subset type: %s\n", TaoSubSetTypes[tao->subset_type]));
612: PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: gatol=%g,", (double)tao->gatol));
613: PetscCall(PetscViewerASCIIPrintf(viewer, " steptol=%g,", (double)tao->steptol));
614: PetscCall(PetscViewerASCIIPrintf(viewer, " gttol=%g\n", (double)tao->gttol));
615: PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Function/Gradient:=%g\n", (double)tao->residual));
617: if (tao->constrained) {
618: PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances:"));
619: PetscCall(PetscViewerASCIIPrintf(viewer, " catol=%g,", (double)tao->catol));
620: PetscCall(PetscViewerASCIIPrintf(viewer, " crtol=%g\n", (double)tao->crtol));
621: PetscCall(PetscViewerASCIIPrintf(viewer, "Residual in Constraints:=%g\n", (double)tao->cnorm));
622: }
624: if (tao->trust < tao->steptol) {
625: PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: steptol=%g\n", (double)tao->steptol));
626: PetscCall(PetscViewerASCIIPrintf(viewer, "Final trust region radius:=%g\n", (double)tao->trust));
627: }
629: if (tao->fmin > -1.e25) PetscCall(PetscViewerASCIIPrintf(viewer, "convergence tolerances: function minimum=%g\n", (double)tao->fmin));
630: PetscCall(PetscViewerASCIIPrintf(viewer, "Objective value=%g\n", (double)tao->fc));
632: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of iterations=%" PetscInt_FMT ", ", tao->niter));
633: PetscCall(PetscViewerASCIIPrintf(viewer, " (max: %" PetscInt_FMT ")\n", tao->max_it));
635: if (tao->nfuncs > 0) {
636: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT ",", tao->nfuncs));
637: PetscCall(PetscViewerASCIIPrintf(viewer, " max: %" PetscInt_FMT "\n", tao->max_funcs));
638: }
639: if (tao->ngrads > 0) {
640: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT ",", tao->ngrads));
641: PetscCall(PetscViewerASCIIPrintf(viewer, " max: %" PetscInt_FMT "\n", tao->max_funcs));
642: }
643: if (tao->nfuncgrads > 0) {
644: PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT ",", tao->nfuncgrads));
645: PetscCall(PetscViewerASCIIPrintf(viewer, " (max: %" PetscInt_FMT ")\n", tao->max_funcs));
646: }
647: if (tao->nhess > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", tao->nhess));
648: if (tao->nconstraints > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of constraint function evaluations=%" PetscInt_FMT "\n", tao->nconstraints));
649: if (tao->njac > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of Jacobian evaluations=%" PetscInt_FMT "\n", tao->njac));
651: if (tao->reason > 0) {
652: PetscCall(PetscViewerASCIIPrintf(viewer, "Solution converged: "));
653: switch (tao->reason) {
654: case TAO_CONVERGED_GATOL:
655: PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)|| <= gatol\n"));
656: break;
657: case TAO_CONVERGED_GRTOL:
658: PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/|f(X)| <= grtol\n"));
659: break;
660: case TAO_CONVERGED_GTTOL:
661: PetscCall(PetscViewerASCIIPrintf(viewer, " ||g(X)||/||g(X0)|| <= gttol\n"));
662: break;
663: case TAO_CONVERGED_STEPTOL:
664: PetscCall(PetscViewerASCIIPrintf(viewer, " Steptol -- step size small\n"));
665: break;
666: case TAO_CONVERGED_MINF:
667: PetscCall(PetscViewerASCIIPrintf(viewer, " Minf -- f < fmin\n"));
668: break;
669: case TAO_CONVERGED_USER:
670: PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
671: break;
672: default:
673: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
674: break;
675: }
676: } else {
677: PetscCall(PetscViewerASCIIPrintf(viewer, "Solver terminated: %d", tao->reason));
678: switch (tao->reason) {
679: case TAO_DIVERGED_MAXITS:
680: PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Iterations\n"));
681: break;
682: case TAO_DIVERGED_NAN:
683: PetscCall(PetscViewerASCIIPrintf(viewer, " NAN or Inf encountered\n"));
684: break;
685: case TAO_DIVERGED_MAXFCN:
686: PetscCall(PetscViewerASCIIPrintf(viewer, " Maximum Function Evaluations\n"));
687: break;
688: case TAO_DIVERGED_LS_FAILURE:
689: PetscCall(PetscViewerASCIIPrintf(viewer, " Line Search Failure\n"));
690: break;
691: case TAO_DIVERGED_TR_REDUCTION:
692: PetscCall(PetscViewerASCIIPrintf(viewer, " Trust Region too small\n"));
693: break;
694: case TAO_DIVERGED_USER:
695: PetscCall(PetscViewerASCIIPrintf(viewer, " User Terminated\n"));
696: break;
697: default:
698: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
699: break;
700: }
701: }
702: PetscCall(PetscViewerASCIIPopTab(viewer));
703: } else if (isstring) {
704: PetscCall(TaoGetType(tao, &type));
705: PetscCall(PetscViewerStringSPrintf(viewer, " %-3.3s", type));
706: }
707: PetscFunctionReturn(PETSC_SUCCESS);
708: }
710: /*@
711: TaoSetRecycleHistory - Sets the boolean flag to enable/disable re-using
712: iterate information from the previous `TaoSolve()`. This feature is disabled by
713: default.
715: Logically Collective
717: Input Parameters:
718: + tao - the `Tao` context
719: - recycle - boolean flag
721: Options Database Key:
722: . -tao_recycle_history <true,false> - reuse the history
724: Level: intermediate
726: Notes:
727: For conjugate gradient methods (`TAOBNCG`), this re-uses the latest search direction
728: from the previous `TaoSolve()` call when computing the first search direction in a
729: new solution. By default, CG methods set the first search direction to the
730: negative gradient.
732: For quasi-Newton family of methods (`TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`), this re-uses
733: the accumulated quasi-Newton Hessian approximation from the previous `TaoSolve()`
734: call. By default, QN family of methods reset the initial Hessian approximation to
735: the identity matrix.
737: For any other algorithm, this setting has no effect.
739: .seealso: [](ch_tao), `Tao`, `TaoGetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
740: @*/
741: PetscErrorCode TaoSetRecycleHistory(Tao tao, PetscBool recycle)
742: {
743: PetscFunctionBegin;
746: tao->recycle = recycle;
747: PetscFunctionReturn(PETSC_SUCCESS);
748: }
750: /*@
751: TaoGetRecycleHistory - Retrieve the boolean flag for re-using iterate information
752: from the previous `TaoSolve()`. This feature is disabled by default.
754: Logically Collective
756: Input Parameter:
757: . tao - the `Tao` context
759: Output Parameter:
760: . recycle - boolean flag
762: Level: intermediate
764: .seealso: [](ch_tao), `Tao`, `TaoSetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`
765: @*/
766: PetscErrorCode TaoGetRecycleHistory(Tao tao, PetscBool *recycle)
767: {
768: PetscFunctionBegin;
770: PetscAssertPointer(recycle, 2);
771: *recycle = tao->recycle;
772: PetscFunctionReturn(PETSC_SUCCESS);
773: }
775: /*@
776: TaoSetTolerances - Sets parameters used in `TaoSolve()` convergence tests
778: Logically Collective
780: Input Parameters:
781: + tao - the `Tao` context
782: . gatol - stop if norm of gradient is less than this
783: . grtol - stop if relative norm of gradient is less than this
784: - gttol - stop if norm of gradient is reduced by this factor
786: Options Database Keys:
787: + -tao_gatol <gatol> - Sets gatol
788: . -tao_grtol <grtol> - Sets grtol
789: - -tao_gttol <gttol> - Sets gttol
791: Stopping Criteria\:
792: .vb
793: ||g(X)|| <= gatol
794: ||g(X)|| / |f(X)| <= grtol
795: ||g(X)|| / ||g(X0)|| <= gttol
796: .ve
798: Level: beginner
800: Note:
801: Use `PETSC_DEFAULT` to leave one or more tolerances unchanged.
803: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`
804: @*/
805: PetscErrorCode TaoSetTolerances(Tao tao, PetscReal gatol, PetscReal grtol, PetscReal gttol)
806: {
807: PetscFunctionBegin;
813: if (gatol != (PetscReal)PETSC_DEFAULT) {
814: if (gatol < 0) {
815: PetscCall(PetscInfo(tao, "Tried to set negative gatol -- ignored.\n"));
816: } else {
817: tao->gatol = PetscMax(0, gatol);
818: tao->gatol_changed = PETSC_TRUE;
819: }
820: }
822: if (grtol != (PetscReal)PETSC_DEFAULT) {
823: if (grtol < 0) {
824: PetscCall(PetscInfo(tao, "Tried to set negative grtol -- ignored.\n"));
825: } else {
826: tao->grtol = PetscMax(0, grtol);
827: tao->grtol_changed = PETSC_TRUE;
828: }
829: }
831: if (gttol != (PetscReal)PETSC_DEFAULT) {
832: if (gttol < 0) {
833: PetscCall(PetscInfo(tao, "Tried to set negative gttol -- ignored.\n"));
834: } else {
835: tao->gttol = PetscMax(0, gttol);
836: tao->gttol_changed = PETSC_TRUE;
837: }
838: }
839: PetscFunctionReturn(PETSC_SUCCESS);
840: }
842: /*@
843: TaoSetConstraintTolerances - Sets constraint tolerance parameters used in `TaoSolve()` convergence tests
845: Logically Collective
847: Input Parameters:
848: + tao - the `Tao` context
849: . catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for gatol convergence criteria
850: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for gatol, gttol convergence criteria
852: Options Database Keys:
853: + -tao_catol <catol> - Sets catol
854: - -tao_crtol <crtol> - Sets crtol
856: Level: intermediate
858: Notes:
859: Use `PETSC_DEFAULT` to leave any tolerance unchanged.
861: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoGetTolerances()`, `TaoGetConstraintTolerances()`, `TaoSetTolerances()`
862: @*/
863: PetscErrorCode TaoSetConstraintTolerances(Tao tao, PetscReal catol, PetscReal crtol)
864: {
865: PetscFunctionBegin;
870: if (catol != (PetscReal)PETSC_DEFAULT) {
871: if (catol < 0) {
872: PetscCall(PetscInfo(tao, "Tried to set negative catol -- ignored.\n"));
873: } else {
874: tao->catol = PetscMax(0, catol);
875: tao->catol_changed = PETSC_TRUE;
876: }
877: }
879: if (crtol != (PetscReal)PETSC_DEFAULT) {
880: if (crtol < 0) {
881: PetscCall(PetscInfo(tao, "Tried to set negative crtol -- ignored.\n"));
882: } else {
883: tao->crtol = PetscMax(0, crtol);
884: tao->crtol_changed = PETSC_TRUE;
885: }
886: }
887: PetscFunctionReturn(PETSC_SUCCESS);
888: }
890: /*@
891: TaoGetConstraintTolerances - Gets constraint tolerance parameters used in `TaoSolve()` convergence tests
893: Not Collective
895: Input Parameter:
896: . tao - the `Tao` context
898: Output Parameters:
899: + catol - absolute constraint tolerance, constraint norm must be less than `catol` for used for gatol convergence criteria
900: - crtol - relative constraint tolerance, constraint norm must be less than `crtol` for used for gatol, gttol convergence criteria
902: Level: intermediate
904: .seealso: [](ch_tao), `Tao`, `TaoConvergedReasons`,`TaoGetTolerances()`, `TaoSetTolerances()`, `TaoSetConstraintTolerances()`
905: @*/
906: PetscErrorCode TaoGetConstraintTolerances(Tao tao, PetscReal *catol, PetscReal *crtol)
907: {
908: PetscFunctionBegin;
910: if (catol) *catol = tao->catol;
911: if (crtol) *crtol = tao->crtol;
912: PetscFunctionReturn(PETSC_SUCCESS);
913: }
915: /*@
916: TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
917: When an approximate solution with an objective value below this number
918: has been found, the solver will terminate.
920: Logically Collective
922: Input Parameters:
923: + tao - the Tao solver context
924: - fmin - the tolerance
926: Options Database Key:
927: . -tao_fmin <fmin> - sets the minimum function value
929: Level: intermediate
931: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetTolerances()`
932: @*/
933: PetscErrorCode TaoSetFunctionLowerBound(Tao tao, PetscReal fmin)
934: {
935: PetscFunctionBegin;
938: tao->fmin = fmin;
939: tao->fmin_changed = PETSC_TRUE;
940: PetscFunctionReturn(PETSC_SUCCESS);
941: }
943: /*@
944: TaoGetFunctionLowerBound - Gets the bound on the solution objective value.
945: When an approximate solution with an objective value below this number
946: has been found, the solver will terminate.
948: Not Collective
950: Input Parameter:
951: . tao - the `Tao` solver context
953: Output Parameter:
954: . fmin - the minimum function value
956: Level: intermediate
958: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetFunctionLowerBound()`
959: @*/
960: PetscErrorCode TaoGetFunctionLowerBound(Tao tao, PetscReal *fmin)
961: {
962: PetscFunctionBegin;
964: PetscAssertPointer(fmin, 2);
965: *fmin = tao->fmin;
966: PetscFunctionReturn(PETSC_SUCCESS);
967: }
969: /*@
970: TaoSetMaximumFunctionEvaluations - Sets a maximum number of function evaluations allowed for a `TaoSolve()`.
972: Logically Collective
974: Input Parameters:
975: + tao - the `Tao` solver context
976: - nfcn - the maximum number of function evaluations (>=0)
978: Options Database Key:
979: . -tao_max_funcs <nfcn> - sets the maximum number of function evaluations
981: Level: intermediate
983: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumIterations()`
984: @*/
985: PetscErrorCode TaoSetMaximumFunctionEvaluations(Tao tao, PetscInt nfcn)
986: {
987: PetscFunctionBegin;
990: if (nfcn >= 0) {
991: tao->max_funcs = PetscMax(0, nfcn);
992: } else {
993: tao->max_funcs = -1;
994: }
995: tao->max_funcs_changed = PETSC_TRUE;
996: PetscFunctionReturn(PETSC_SUCCESS);
997: }
999: /*@
1000: TaoGetMaximumFunctionEvaluations - Gets a maximum number of function evaluations allowed for a `TaoSolve()`
1002: Logically Collective
1004: Input Parameter:
1005: . tao - the `Tao` solver context
1007: Output Parameter:
1008: . nfcn - the maximum number of function evaluations
1010: Level: intermediate
1012: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1013: @*/
1014: PetscErrorCode TaoGetMaximumFunctionEvaluations(Tao tao, PetscInt *nfcn)
1015: {
1016: PetscFunctionBegin;
1018: PetscAssertPointer(nfcn, 2);
1019: *nfcn = tao->max_funcs;
1020: PetscFunctionReturn(PETSC_SUCCESS);
1021: }
1023: /*@
1024: TaoGetCurrentFunctionEvaluations - Get current number of function evaluations used by a `Tao` object
1026: Not Collective
1028: Input Parameter:
1029: . tao - the `Tao` solver context
1031: Output Parameter:
1032: . nfuncs - the current number of function evaluations (maximum between gradient and function evaluations)
1034: Level: intermediate
1036: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1037: @*/
1038: PetscErrorCode TaoGetCurrentFunctionEvaluations(Tao tao, PetscInt *nfuncs)
1039: {
1040: PetscFunctionBegin;
1042: PetscAssertPointer(nfuncs, 2);
1043: *nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1044: PetscFunctionReturn(PETSC_SUCCESS);
1045: }
1047: /*@
1048: TaoSetMaximumIterations - Sets a maximum number of iterates to be used in `TaoSolve()`
1050: Logically Collective
1052: Input Parameters:
1053: + tao - the `Tao` solver context
1054: - maxits - the maximum number of iterates (>=0)
1056: Options Database Key:
1057: . -tao_max_it <its> - sets the maximum number of iterations
1059: Level: intermediate
1061: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoSetMaximumFunctionEvaluations()`
1062: @*/
1063: PetscErrorCode TaoSetMaximumIterations(Tao tao, PetscInt maxits)
1064: {
1065: PetscFunctionBegin;
1068: tao->max_it = PetscMax(0, maxits);
1069: tao->max_it_changed = PETSC_TRUE;
1070: PetscFunctionReturn(PETSC_SUCCESS);
1071: }
1073: /*@
1074: TaoGetMaximumIterations - Gets a maximum number of iterates that will be used
1076: Not Collective
1078: Input Parameter:
1079: . tao - the `Tao` solver context
1081: Output Parameter:
1082: . maxits - the maximum number of iterates
1084: Level: intermediate
1086: .seealso: [](ch_tao), `Tao`, `TaoSetMaximumIterations()`, `TaoGetMaximumFunctionEvaluations()`
1087: @*/
1088: PetscErrorCode TaoGetMaximumIterations(Tao tao, PetscInt *maxits)
1089: {
1090: PetscFunctionBegin;
1092: PetscAssertPointer(maxits, 2);
1093: *maxits = tao->max_it;
1094: PetscFunctionReturn(PETSC_SUCCESS);
1095: }
1097: /*@
1098: TaoSetInitialTrustRegionRadius - Sets the initial trust region radius.
1100: Logically Collective
1102: Input Parameters:
1103: + tao - a `Tao` optimization solver
1104: - radius - the trust region radius
1106: Options Database Key:
1107: . -tao_trust0 <t0> - sets initial trust region radius
1109: Level: intermediate
1111: .seealso: [](ch_tao), `Tao`, `TaoGetTrustRegionRadius()`, `TaoSetTrustRegionTolerance()`, `TAONTR`
1112: @*/
1113: PetscErrorCode TaoSetInitialTrustRegionRadius(Tao tao, PetscReal radius)
1114: {
1115: PetscFunctionBegin;
1118: tao->trust0 = PetscMax(0.0, radius);
1119: tao->trust0_changed = PETSC_TRUE;
1120: PetscFunctionReturn(PETSC_SUCCESS);
1121: }
1123: /*@
1124: TaoGetInitialTrustRegionRadius - Gets the initial trust region radius.
1126: Not Collective
1128: Input Parameter:
1129: . tao - a `Tao` optimization solver
1131: Output Parameter:
1132: . radius - the trust region radius
1134: Level: intermediate
1136: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetCurrentTrustRegionRadius()`, `TAONTR`
1137: @*/
1138: PetscErrorCode TaoGetInitialTrustRegionRadius(Tao tao, PetscReal *radius)
1139: {
1140: PetscFunctionBegin;
1142: PetscAssertPointer(radius, 2);
1143: *radius = tao->trust0;
1144: PetscFunctionReturn(PETSC_SUCCESS);
1145: }
1147: /*@
1148: TaoGetCurrentTrustRegionRadius - Gets the current trust region radius.
1150: Not Collective
1152: Input Parameter:
1153: . tao - a `Tao` optimization solver
1155: Output Parameter:
1156: . radius - the trust region radius
1158: Level: intermediate
1160: .seealso: [](ch_tao), `Tao`, `TaoSetInitialTrustRegionRadius()`, `TaoGetInitialTrustRegionRadius()`, `TAONTR`
1161: @*/
1162: PetscErrorCode TaoGetCurrentTrustRegionRadius(Tao tao, PetscReal *radius)
1163: {
1164: PetscFunctionBegin;
1166: PetscAssertPointer(radius, 2);
1167: *radius = tao->trust;
1168: PetscFunctionReturn(PETSC_SUCCESS);
1169: }
1171: /*@
1172: TaoGetTolerances - gets the current values of some tolerances used for the convergence testing of `TaoSolve()`
1174: Not Collective
1176: Input Parameter:
1177: . tao - the `Tao` context
1179: Output Parameters:
1180: + gatol - stop if norm of gradient is less than this
1181: . grtol - stop if relative norm of gradient is less than this
1182: - gttol - stop if norm of gradient is reduced by a this factor
1184: Level: intermediate
1186: Note:
1187: `NULL` can be used as an argument if not all tolerances values are needed
1189: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`
1190: @*/
1191: PetscErrorCode TaoGetTolerances(Tao tao, PetscReal *gatol, PetscReal *grtol, PetscReal *gttol)
1192: {
1193: PetscFunctionBegin;
1195: if (gatol) *gatol = tao->gatol;
1196: if (grtol) *grtol = tao->grtol;
1197: if (gttol) *gttol = tao->gttol;
1198: PetscFunctionReturn(PETSC_SUCCESS);
1199: }
1201: /*@
1202: TaoGetKSP - Gets the linear solver used by the optimization solver.
1204: Not Collective
1206: Input Parameter:
1207: . tao - the `Tao` solver
1209: Output Parameter:
1210: . ksp - the `KSP` linear solver used in the optimization solver
1212: Level: intermediate
1214: .seealso: [](ch_tao), `Tao`, `KSP`
1215: @*/
1216: PetscErrorCode TaoGetKSP(Tao tao, KSP *ksp)
1217: {
1218: PetscFunctionBegin;
1220: PetscAssertPointer(ksp, 2);
1221: *ksp = tao->ksp;
1222: PetscFunctionReturn(PETSC_SUCCESS);
1223: }
1225: /*@
1226: TaoGetLinearSolveIterations - Gets the total number of linear iterations
1227: used by the `Tao` solver
1229: Not Collective
1231: Input Parameter:
1232: . tao - the `Tao` context
1234: Output Parameter:
1235: . lits - number of linear iterations
1237: Level: intermediate
1239: Note:
1240: This counter is reset to zero for each successive call to `TaoSolve()`
1242: .seealso: [](ch_tao), `Tao`, `TaoGetKSP()`
1243: @*/
1244: PetscErrorCode TaoGetLinearSolveIterations(Tao tao, PetscInt *lits)
1245: {
1246: PetscFunctionBegin;
1248: PetscAssertPointer(lits, 2);
1249: *lits = tao->ksp_tot_its;
1250: PetscFunctionReturn(PETSC_SUCCESS);
1251: }
1253: /*@
1254: TaoGetLineSearch - Gets the line search used by the optimization solver.
1256: Not Collective
1258: Input Parameter:
1259: . tao - the `Tao` solver
1261: Output Parameter:
1262: . ls - the line search used in the optimization solver
1264: Level: intermediate
1266: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`
1267: @*/
1268: PetscErrorCode TaoGetLineSearch(Tao tao, TaoLineSearch *ls)
1269: {
1270: PetscFunctionBegin;
1272: PetscAssertPointer(ls, 2);
1273: *ls = tao->linesearch;
1274: PetscFunctionReturn(PETSC_SUCCESS);
1275: }
1277: /*@
1278: TaoAddLineSearchCounts - Adds the number of function evaluations spent
1279: in the line search to the running total.
1281: Input Parameters:
1282: . tao - the `Tao` solver
1284: Level: developer
1286: .seealso: [](ch_tao), `Tao`, `TaoGetLineSearch()`, `TaoLineSearchApply()`
1287: @*/
1288: PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1289: {
1290: PetscBool flg;
1291: PetscInt nfeval, ngeval, nfgeval;
1293: PetscFunctionBegin;
1295: if (tao->linesearch) {
1296: PetscCall(TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg));
1297: if (!flg) {
1298: PetscCall(TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval));
1299: tao->nfuncs += nfeval;
1300: tao->ngrads += ngeval;
1301: tao->nfuncgrads += nfgeval;
1302: }
1303: }
1304: PetscFunctionReturn(PETSC_SUCCESS);
1305: }
1307: /*@
1308: TaoGetSolution - Returns the vector with the current solution from the `Tao` object
1310: Not Collective
1312: Input Parameter:
1313: . tao - the `Tao` context
1315: Output Parameter:
1316: . X - the current solution
1318: Level: intermediate
1320: Note:
1321: The returned vector will be the same object that was passed into `TaoSetSolution()`
1323: .seealso: [](ch_tao), `Tao`, `TaoSetSolution()`, `TaoSolve()`
1324: @*/
1325: PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1326: {
1327: PetscFunctionBegin;
1329: PetscAssertPointer(X, 2);
1330: *X = tao->solution;
1331: PetscFunctionReturn(PETSC_SUCCESS);
1332: }
1334: /*@
1335: TaoResetStatistics - Initialize the statistics collected by the `Tao` object.
1336: These statistics include the iteration number, residual norms, and convergence status.
1337: This routine gets called before solving each optimization problem.
1339: Collective
1341: Input Parameter:
1342: . tao - the `Tao` context
1344: Level: developer
1346: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`
1347: @*/
1348: PetscErrorCode TaoResetStatistics(Tao tao)
1349: {
1350: PetscFunctionBegin;
1352: tao->niter = 0;
1353: tao->nfuncs = 0;
1354: tao->nfuncgrads = 0;
1355: tao->ngrads = 0;
1356: tao->nhess = 0;
1357: tao->njac = 0;
1358: tao->nconstraints = 0;
1359: tao->ksp_its = 0;
1360: tao->ksp_tot_its = 0;
1361: tao->reason = TAO_CONTINUE_ITERATING;
1362: tao->residual = 0.0;
1363: tao->cnorm = 0.0;
1364: tao->step = 0.0;
1365: tao->lsflag = PETSC_FALSE;
1366: if (tao->hist_reset) tao->hist_len = 0;
1367: PetscFunctionReturn(PETSC_SUCCESS);
1368: }
1370: /*@C
1371: TaoSetUpdate - Sets the general-purpose update function called
1372: at the beginning of every iteration of the optimization algorithm. Called after the new solution and the gradient
1373: is determined, but before the Hessian is computed (if applicable).
1375: Logically Collective
1377: Input Parameters:
1378: + tao - The `Tao` solver context
1379: - func - The function
1381: Calling sequence of `func`:
1382: + tao - the optimizer context
1383: - ctx - The current step of the iteration
1385: Level: advanced
1387: .seealso: [](ch_tao), `Tao`, `TaoSolve()`
1388: @*/
1389: PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao, PetscInt, void *), void *ctx)
1390: {
1391: PetscFunctionBegin;
1393: tao->ops->update = func;
1394: tao->user_update = ctx;
1395: PetscFunctionReturn(PETSC_SUCCESS);
1396: }
1398: /*@C
1399: TaoSetConvergenceTest - Sets the function that is to be used to test
1400: for convergence o fthe iterative minimization solution. The new convergence
1401: testing routine will replace Tao's default convergence test.
1403: Logically Collective
1405: Input Parameters:
1406: + tao - the `Tao` object
1407: . conv - the routine to test for convergence
1408: - ctx - [optional] context for private data for the convergence routine
1409: (may be `NULL`)
1411: Calling sequence of `conv`:
1412: + tao - the `Tao` object
1413: - ctx - [optional] convergence context
1415: Level: advanced
1417: Note:
1418: The new convergence testing routine should call `TaoSetConvergedReason()`.
1420: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoSetMonitor`
1421: @*/
1422: PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao, void *), void *ctx)
1423: {
1424: PetscFunctionBegin;
1426: tao->ops->convergencetest = conv;
1427: tao->cnvP = ctx;
1428: PetscFunctionReturn(PETSC_SUCCESS);
1429: }
1431: /*@C
1432: TaoSetMonitor - Sets an additional function that is to be used at every
1433: iteration of the solver to display the iteration's
1434: progress.
1436: Logically Collective
1438: Input Parameters:
1439: + tao - the `Tao` solver context
1440: . func - monitoring routine
1441: . ctx - [optional] user-defined context for private data for the monitor routine (may be `NULL`)
1442: - dest - [optional] function to destroy the context when the `Tao` is destroyed
1444: Calling sequence of `func`:
1445: + tao - the `Tao` solver context
1446: - ctx - [optional] monitoring context
1448: Calling sequence of `dest`:
1449: . ctx - monitoring context
1451: Options Database Keys:
1452: + -tao_monitor - sets the default monitor `TaoMonitorDefault()`
1453: . -tao_smonitor - sets short monitor
1454: . -tao_cmonitor - same as smonitor plus constraint norm
1455: . -tao_view_solution - view solution at each iteration
1456: . -tao_view_gradient - view gradient at each iteration
1457: . -tao_view_ls_residual - view least-squares residual vector at each iteration
1458: - -tao_cancelmonitors - cancels all monitors that have been hardwired into a code by calls to TaoSetMonitor(), but does not cancel those set via the options database.
1460: Level: intermediate
1462: Notes:
1463: Several different monitoring routines may be set by calling
1464: `TaoSetMonitor()` multiple times; all will be called in the
1465: order in which they were set.
1467: Fortran Notes:
1468: Only one monitor function may be set
1470: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoMonitorDefault()`, `TaoCancelMonitors()`, `TaoSetDestroyRoutine()`, `TaoView()`
1471: @*/
1472: PetscErrorCode TaoSetMonitor(Tao tao, PetscErrorCode (*func)(Tao, void *), void *ctx, PetscErrorCode (*dest)(void **))
1473: {
1474: PetscInt i;
1475: PetscBool identical;
1477: PetscFunctionBegin;
1479: PetscCheck(tao->numbermonitors < MAXTAOMONITORS, PetscObjectComm((PetscObject)tao), PETSC_ERR_SUP, "Cannot attach another monitor -- max=%d", MAXTAOMONITORS);
1481: for (i = 0; i < tao->numbermonitors; i++) {
1482: PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))func, ctx, dest, (PetscErrorCode(*)(void))tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical));
1483: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
1484: }
1485: tao->monitor[tao->numbermonitors] = func;
1486: tao->monitorcontext[tao->numbermonitors] = (void *)ctx;
1487: tao->monitordestroy[tao->numbermonitors] = dest;
1488: ++tao->numbermonitors;
1489: PetscFunctionReturn(PETSC_SUCCESS);
1490: }
1492: /*@
1493: TaoCancelMonitors - Clears all the monitor functions for a `Tao` object.
1495: Logically Collective
1497: Input Parameter:
1498: . tao - the `Tao` solver context
1500: Options Database Key:
1501: . -tao_cancelmonitors - cancels all monitors that have been hardwired
1502: into a code by calls to `TaoSetMonitor()`, but does not cancel those
1503: set via the options database
1505: Level: advanced
1507: Note:
1508: There is no way to clear one specific monitor from a `Tao` object.
1510: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoSetMonitor()`
1511: @*/
1512: PetscErrorCode TaoCancelMonitors(Tao tao)
1513: {
1514: PetscInt i;
1516: PetscFunctionBegin;
1518: for (i = 0; i < tao->numbermonitors; i++) {
1519: if (tao->monitordestroy[i]) PetscCall((*tao->monitordestroy[i])(&tao->monitorcontext[i]));
1520: }
1521: tao->numbermonitors = 0;
1522: PetscFunctionReturn(PETSC_SUCCESS);
1523: }
1525: /*@
1526: TaoMonitorDefault - Default routine for monitoring progress of `TaoSolve()`
1528: Collective
1530: Input Parameters:
1531: + tao - the `Tao` context
1532: - ctx - `PetscViewer` context or `NULL`
1534: Options Database Key:
1535: . -tao_monitor - turn on default monitoring
1537: Level: advanced
1539: Note:
1540: This monitor prints the function value and gradient
1541: norm at each iteration.
1543: .seealso: [](ch_tao), `Tao`, `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1544: @*/
1545: PetscErrorCode TaoMonitorDefault(Tao tao, void *ctx)
1546: {
1547: PetscInt its, tabs;
1548: PetscReal fct, gnorm;
1549: PetscViewer viewer = (PetscViewer)ctx;
1551: PetscFunctionBegin;
1554: its = tao->niter;
1555: fct = tao->fc;
1556: gnorm = tao->residual;
1557: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1558: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1559: if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1560: PetscCall(PetscViewerASCIIPrintf(viewer, " Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1561: tao->header_printed = PETSC_TRUE;
1562: }
1563: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1564: PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct));
1565: if (gnorm >= PETSC_INFINITY) {
1566: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf \n"));
1567: } else {
1568: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm));
1569: }
1570: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1571: PetscFunctionReturn(PETSC_SUCCESS);
1572: }
1574: /*@
1575: TaoDefaultGMonitor - Default routine for monitoring progress of `TaoSolve()` with extra detail on the globalization method.
1577: Collective
1579: Input Parameters:
1580: + tao - the `Tao` context
1581: - ctx - `PetscViewer` context or `NULL`
1583: Options Database Key:
1584: . -tao_gmonitor - turn on monitoring with globalization information
1586: Level: advanced
1588: Note:
1589: This monitor prints the function value and gradient norm at each
1590: iteration, as well as the step size and trust radius. Note that the
1591: step size and trust radius may be the same for some algorithms.
1593: .seealso: [](ch_tao), `Tao`, `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1594: @*/
1595: PetscErrorCode TaoDefaultGMonitor(Tao tao, void *ctx)
1596: {
1597: PetscInt its, tabs;
1598: PetscReal fct, gnorm, stp, tr;
1599: PetscViewer viewer = (PetscViewer)ctx;
1601: PetscFunctionBegin;
1604: its = tao->niter;
1605: fct = tao->fc;
1606: gnorm = tao->residual;
1607: stp = tao->step;
1608: tr = tao->trust;
1609: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1610: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1611: if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1612: PetscCall(PetscViewerASCIIPrintf(viewer, " Iteration information for %s solve.\n", ((PetscObject)tao)->prefix));
1613: tao->header_printed = PETSC_TRUE;
1614: }
1615: PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its));
1616: PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct));
1617: if (gnorm >= PETSC_INFINITY) {
1618: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf,"));
1619: } else {
1620: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g,", (double)gnorm));
1621: }
1622: PetscCall(PetscViewerASCIIPrintf(viewer, " Step: %g, Trust: %g\n", (double)stp, (double)tr));
1623: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1624: PetscFunctionReturn(PETSC_SUCCESS);
1625: }
1627: /*@
1628: TaoDefaultSMonitor - Default routine for monitoring progress of `TaoSolve()`
1630: Collective
1632: Input Parameters:
1633: + tao - the `Tao` context
1634: - ctx - `PetscViewer` context of type `PETSCVIEWERASCII`
1636: Options Database Key:
1637: . -tao_smonitor - turn on default short monitoring
1639: Level: advanced
1641: Note:
1642: Same as `TaoMonitorDefault()` except
1643: it prints fewer digits of the residual as the residual gets smaller.
1644: This is because the later digits are meaningless and are often
1645: different on different machines; by using this routine different
1646: machines will usually generate the same output.
1648: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoSetMonitor()`
1649: @*/
1650: PetscErrorCode TaoDefaultSMonitor(Tao tao, void *ctx)
1651: {
1652: PetscInt its, tabs;
1653: PetscReal fct, gnorm;
1654: PetscViewer viewer = (PetscViewer)ctx;
1656: PetscFunctionBegin;
1659: its = tao->niter;
1660: fct = tao->fc;
1661: gnorm = tao->residual;
1662: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1663: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1664: PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %3" PetscInt_FMT ",", its));
1665: PetscCall(PetscViewerASCIIPrintf(viewer, " Function value %g,", (double)fct));
1666: if (gnorm >= PETSC_INFINITY) {
1667: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: Inf \n"));
1668: } else if (gnorm > 1.e-6) {
1669: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm));
1670: } else if (gnorm > 1.e-11) {
1671: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-6 \n"));
1672: } else {
1673: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-11 \n"));
1674: }
1675: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1676: PetscFunctionReturn(PETSC_SUCCESS);
1677: }
1679: /*@
1680: TaoDefaultCMonitor - same as `TaoMonitorDefault()` except
1681: it prints the norm of the constraint function.
1683: Collective
1685: Input Parameters:
1686: + tao - the `Tao` context
1687: - ctx - `PetscViewer` context or `NULL`
1689: Options Database Key:
1690: . -tao_cmonitor - monitor the constraints
1692: Level: advanced
1694: .seealso: [](ch_tao), `Tao`, `TaoMonitorDefault()`, `TaoSetMonitor()`
1695: @*/
1696: PetscErrorCode TaoDefaultCMonitor(Tao tao, void *ctx)
1697: {
1698: PetscInt its, tabs;
1699: PetscReal fct, gnorm;
1700: PetscViewer viewer = (PetscViewer)ctx;
1702: PetscFunctionBegin;
1705: its = tao->niter;
1706: fct = tao->fc;
1707: gnorm = tao->residual;
1708: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
1709: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
1710: PetscCall(PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", its));
1711: PetscCall(PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct));
1712: PetscCall(PetscViewerASCIIPrintf(viewer, " Residual: %g ", (double)gnorm));
1713: PetscCall(PetscViewerASCIIPrintf(viewer, " Constraint: %g \n", (double)tao->cnorm));
1714: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1715: PetscFunctionReturn(PETSC_SUCCESS);
1716: }
1718: /*@C
1719: TaoSolutionMonitor - Views the solution at each iteration of `TaoSolve()`
1721: Collective
1723: Input Parameters:
1724: + tao - the `Tao` context
1725: - ctx - `PetscViewer` context or `NULL`
1727: Options Database Key:
1728: . -tao_view_solution - view the solution
1730: Level: advanced
1732: .seealso: [](ch_tao), `Tao`, `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1733: @*/
1734: PetscErrorCode TaoSolutionMonitor(Tao tao, void *ctx)
1735: {
1736: PetscViewer viewer = (PetscViewer)ctx;
1738: PetscFunctionBegin;
1741: PetscCall(VecView(tao->solution, viewer));
1742: PetscFunctionReturn(PETSC_SUCCESS);
1743: }
1745: /*@C
1746: TaoGradientMonitor - Views the gradient at each iteration of `TaoSolve()`
1748: Collective
1750: Input Parameters:
1751: + tao - the `Tao` context
1752: - ctx - `PetscViewer` context or `NULL`
1754: Options Database Key:
1755: . -tao_view_gradient - view the gradient at each iteration
1757: Level: advanced
1759: .seealso: [](ch_tao), `Tao`, `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1760: @*/
1761: PetscErrorCode TaoGradientMonitor(Tao tao, void *ctx)
1762: {
1763: PetscViewer viewer = (PetscViewer)ctx;
1765: PetscFunctionBegin;
1768: PetscCall(VecView(tao->gradient, viewer));
1769: PetscFunctionReturn(PETSC_SUCCESS);
1770: }
1772: /*@C
1773: TaoStepDirectionMonitor - Views the step-direction at each iteration of `TaoSolve()`
1775: Collective
1777: Input Parameters:
1778: + tao - the `Tao` context
1779: - ctx - `PetscViewer` context or `NULL`
1781: Options Database Key:
1782: . -tao_view_stepdirection - view the step direction vector at each iteration
1784: Level: advanced
1786: .seealso: [](ch_tao), `Tao`, `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1787: @*/
1788: PetscErrorCode TaoStepDirectionMonitor(Tao tao, void *ctx)
1789: {
1790: PetscViewer viewer = (PetscViewer)ctx;
1792: PetscFunctionBegin;
1795: PetscCall(VecView(tao->stepdirection, viewer));
1796: PetscFunctionReturn(PETSC_SUCCESS);
1797: }
1799: /*@C
1800: TaoDrawSolutionMonitor - Plots the solution at each iteration of `TaoSolve()`
1802: Collective
1804: Input Parameters:
1805: + tao - the `Tao` context
1806: - ctx - `TaoMonitorDraw` context
1808: Options Database Key:
1809: . -tao_draw_solution - draw the solution at each iteration
1811: Level: advanced
1813: .seealso: [](ch_tao), `Tao`, `TaoSolutionMonitor()`, `TaoSetMonitor()`, `TaoDrawGradientMonitor`, `TaoMonitorDraw`
1814: @*/
1815: PetscErrorCode TaoDrawSolutionMonitor(Tao tao, void *ctx)
1816: {
1817: TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
1819: PetscFunctionBegin;
1821: if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1822: PetscCall(VecView(tao->solution, ictx->viewer));
1823: PetscFunctionReturn(PETSC_SUCCESS);
1824: }
1826: /*@C
1827: TaoDrawGradientMonitor - Plots the gradient at each iteration of `TaoSolve()`
1829: Collective
1831: Input Parameters:
1832: + tao - the `Tao` context
1833: - ctx - `PetscViewer` context
1835: Options Database Key:
1836: . -tao_draw_gradient - draw the gradient at each iteration
1838: Level: advanced
1840: .seealso: [](ch_tao), `Tao`, `TaoGradientMonitor()`, `TaoSetMonitor()`, `TaoDrawSolutionMonitor`
1841: @*/
1842: PetscErrorCode TaoDrawGradientMonitor(Tao tao, void *ctx)
1843: {
1844: TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;
1846: PetscFunctionBegin;
1848: if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) PetscFunctionReturn(PETSC_SUCCESS);
1849: PetscCall(VecView(tao->gradient, ictx->viewer));
1850: PetscFunctionReturn(PETSC_SUCCESS);
1851: }
1853: /*@C
1854: TaoDrawStepMonitor - Plots the step direction at each iteration of `TaoSolve()`
1856: Collective
1858: Input Parameters:
1859: + tao - the `Tao` context
1860: - ctx - the `PetscViewer` context
1862: Options Database Key:
1863: . -tao_draw_step - draw the step direction at each iteration
1865: Level: advanced
1867: .seealso: [](ch_tao), `Tao`, `TaoSetMonitor()`, `TaoDrawSolutionMonitor`
1868: @*/
1869: PetscErrorCode TaoDrawStepMonitor(Tao tao, void *ctx)
1870: {
1871: PetscViewer viewer = (PetscViewer)ctx;
1873: PetscFunctionBegin;
1876: PetscCall(VecView(tao->stepdirection, viewer));
1877: PetscFunctionReturn(PETSC_SUCCESS);
1878: }
1880: /*@C
1881: TaoResidualMonitor - Views the least-squares residual at each iteration of `TaoSolve()`
1883: Collective
1885: Input Parameters:
1886: + tao - the `Tao` context
1887: - ctx - the `PetscViewer` context or `NULL`
1889: Options Database Key:
1890: . -tao_view_ls_residual - view the residual at each iteration
1892: Level: advanced
1894: .seealso: [](ch_tao), `Tao`, `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1895: @*/
1896: PetscErrorCode TaoResidualMonitor(Tao tao, void *ctx)
1897: {
1898: PetscViewer viewer = (PetscViewer)ctx;
1900: PetscFunctionBegin;
1903: PetscCall(VecView(tao->ls_res, viewer));
1904: PetscFunctionReturn(PETSC_SUCCESS);
1905: }
1907: /*@
1908: TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
1909: or terminate.
1911: Collective
1913: Input Parameters:
1914: + tao - the `Tao` context
1915: - dummy - unused dummy context
1917: Level: developer
1919: Notes:
1920: This routine checks the residual in the optimality conditions, the
1921: relative residual in the optimity conditions, the number of function
1922: evaluations, and the function value to test convergence. Some
1923: solvers may use different convergence routines.
1925: .seealso: [](ch_tao), `Tao`, `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
1926: @*/
1927: PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
1928: {
1929: PetscInt niter = tao->niter, nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1930: PetscInt max_funcs = tao->max_funcs;
1931: PetscReal gnorm = tao->residual, gnorm0 = tao->gnorm0;
1932: PetscReal f = tao->fc, steptol = tao->steptol, trradius = tao->step;
1933: PetscReal gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
1934: PetscReal catol = tao->catol, crtol = tao->crtol;
1935: PetscReal fmin = tao->fmin, cnorm = tao->cnorm;
1936: TaoConvergedReason reason = tao->reason;
1938: PetscFunctionBegin;
1940: if (reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(PETSC_SUCCESS);
1942: if (PetscIsInfOrNanReal(f)) {
1943: PetscCall(PetscInfo(tao, "Failed to converged, function value is Inf or NaN\n"));
1944: reason = TAO_DIVERGED_NAN;
1945: } else if (f <= fmin && cnorm <= catol) {
1946: PetscCall(PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin));
1947: reason = TAO_CONVERGED_MINF;
1948: } else if (gnorm <= gatol && cnorm <= catol) {
1949: PetscCall(PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol));
1950: reason = TAO_CONVERGED_GATOL;
1951: } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
1952: PetscCall(PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol));
1953: reason = TAO_CONVERGED_GRTOL;
1954: } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
1955: PetscCall(PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol));
1956: reason = TAO_CONVERGED_GTTOL;
1957: } else if (max_funcs >= 0 && nfuncs > max_funcs) {
1958: PetscCall(PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs));
1959: reason = TAO_DIVERGED_MAXFCN;
1960: } else if (tao->lsflag != 0) {
1961: PetscCall(PetscInfo(tao, "Tao Line Search failure.\n"));
1962: reason = TAO_DIVERGED_LS_FAILURE;
1963: } else if (trradius < steptol && niter > 0) {
1964: PetscCall(PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol));
1965: reason = TAO_CONVERGED_STEPTOL;
1966: } else if (niter >= tao->max_it) {
1967: PetscCall(PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it));
1968: reason = TAO_DIVERGED_MAXITS;
1969: } else {
1970: reason = TAO_CONTINUE_ITERATING;
1971: }
1972: tao->reason = reason;
1973: PetscFunctionReturn(PETSC_SUCCESS);
1974: }
1976: /*@C
1977: TaoSetOptionsPrefix - Sets the prefix used for searching for all
1978: Tao options in the database.
1980: Logically Collective
1982: Input Parameters:
1983: + tao - the `Tao` context
1984: - p - the prefix string to prepend to all Tao option requests
1986: Level: advanced
1988: Notes:
1989: A hyphen (-) must NOT be given at the beginning of the prefix name.
1990: The first character of all runtime options is AUTOMATICALLY the hyphen.
1992: For example, to distinguish between the runtime options for two
1993: different Tao solvers, one could call
1994: .vb
1995: TaoSetOptionsPrefix(tao1,"sys1_")
1996: TaoSetOptionsPrefix(tao2,"sys2_")
1997: .ve
1999: This would enable use of different options for each system, such as
2000: .vb
2001: -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
2002: -sys2_tao_method lmvm -sys2_tao_grtol 1.e-4
2003: .ve
2005: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
2006: @*/
2007: PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
2008: {
2009: PetscFunctionBegin;
2011: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tao, p));
2012: if (tao->linesearch) PetscCall(TaoLineSearchSetOptionsPrefix(tao->linesearch, p));
2013: if (tao->ksp) PetscCall(KSPSetOptionsPrefix(tao->ksp, p));
2014: PetscFunctionReturn(PETSC_SUCCESS);
2015: }
2017: /*@C
2018: TaoAppendOptionsPrefix - Appends to the prefix used for searching for all Tao options in the database.
2020: Logically Collective
2022: Input Parameters:
2023: + tao - the `Tao` solver context
2024: - p - the prefix string to prepend to all `Tao` option requests
2026: Level: advanced
2028: Note:
2029: A hyphen (-) must NOT be given at the beginning of the prefix name.
2030: The first character of all runtime options is automatically the hyphen.
2032: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2033: @*/
2034: PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2035: {
2036: PetscFunctionBegin;
2038: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao, p));
2039: if (tao->linesearch) PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p));
2040: if (tao->ksp) PetscCall(KSPAppendOptionsPrefix(tao->ksp, p));
2041: PetscFunctionReturn(PETSC_SUCCESS);
2042: }
2044: /*@C
2045: TaoGetOptionsPrefix - Gets the prefix used for searching for all
2046: Tao options in the database
2048: Not Collective
2050: Input Parameter:
2051: . tao - the `Tao` context
2053: Output Parameter:
2054: . p - pointer to the prefix string used is returned
2056: Fortran Notes:
2057: Pass in a string 'prefix' of sufficient length to hold the prefix.
2059: Level: advanced
2061: .seealso: [](ch_tao), `Tao`, `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2062: @*/
2063: PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2064: {
2065: PetscFunctionBegin;
2067: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tao, p));
2068: PetscFunctionReturn(PETSC_SUCCESS);
2069: }
2071: /*@C
2072: TaoSetType - Sets the `TaoType` for the minimization solver.
2074: Collective
2076: Input Parameters:
2077: + tao - the `Tao` solver context
2078: - type - a known method
2080: Options Database Key:
2081: . -tao_type <type> - Sets the method; use -help for a list
2082: of available methods (for instance, "-tao_type lmvm" or "-tao_type tron")
2084: Level: intermediate
2086: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`
2087: @*/
2088: PetscErrorCode TaoSetType(Tao tao, TaoType type)
2089: {
2090: PetscErrorCode (*create_xxx)(Tao);
2091: PetscBool issame;
2093: PetscFunctionBegin;
2096: PetscCall(PetscObjectTypeCompare((PetscObject)tao, type, &issame));
2097: if (issame) PetscFunctionReturn(PETSC_SUCCESS);
2099: PetscCall(PetscFunctionListFind(TaoList, type, (void (**)(void)) & create_xxx));
2100: PetscCheck(create_xxx, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Tao type %s", type);
2102: /* Destroy the existing solver information */
2103: PetscTryTypeMethod(tao, destroy);
2104: PetscCall(KSPDestroy(&tao->ksp));
2105: PetscCall(TaoLineSearchDestroy(&tao->linesearch));
2106: tao->ops->setup = NULL;
2107: tao->ops->solve = NULL;
2108: tao->ops->view = NULL;
2109: tao->ops->setfromoptions = NULL;
2110: tao->ops->destroy = NULL;
2112: tao->setupcalled = PETSC_FALSE;
2114: PetscCall((*create_xxx)(tao));
2115: PetscCall(PetscObjectChangeTypeName((PetscObject)tao, type));
2116: PetscFunctionReturn(PETSC_SUCCESS);
2117: }
2119: /*@C
2120: TaoRegister - Adds a method to the Tao package for minimization.
2122: Not Collective
2124: Input Parameters:
2125: + sname - name of a new user-defined solver
2126: - func - routine to Create method context
2128: Example Usage:
2129: .vb
2130: TaoRegister("my_solver", MySolverCreate);
2131: .ve
2133: Then, your solver can be chosen with the procedural interface via
2134: $ TaoSetType(tao, "my_solver")
2135: or at runtime via the option
2136: $ -tao_type my_solver
2138: Level: advanced
2140: Note:
2141: `TaoRegister()` may be called multiple times to add several user-defined solvers.
2143: .seealso: [](ch_tao), `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2144: @*/
2145: PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao))
2146: {
2147: PetscFunctionBegin;
2148: PetscCall(TaoInitializePackage());
2149: PetscCall(PetscFunctionListAdd(&TaoList, sname, (void (*)(void))func));
2150: PetscFunctionReturn(PETSC_SUCCESS);
2151: }
2153: /*@C
2154: TaoRegisterDestroy - Frees the list of minimization solvers that were
2155: registered by `TaoRegister()`.
2157: Not Collective
2159: Level: advanced
2161: .seealso: [](ch_tao), `Tao`, `TaoRegisterAll()`, `TaoRegister()`
2162: @*/
2163: PetscErrorCode TaoRegisterDestroy(void)
2164: {
2165: PetscFunctionBegin;
2166: PetscCall(PetscFunctionListDestroy(&TaoList));
2167: TaoRegisterAllCalled = PETSC_FALSE;
2168: PetscFunctionReturn(PETSC_SUCCESS);
2169: }
2171: /*@
2172: TaoGetIterationNumber - Gets the number of `TaoSolve()` iterations completed
2173: at this time.
2175: Not Collective
2177: Input Parameter:
2178: . tao - the `Tao` context
2180: Output Parameter:
2181: . iter - iteration number
2183: Notes:
2184: For example, during the computation of iteration 2 this would return 1.
2186: Level: intermediate
2188: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2189: @*/
2190: PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2191: {
2192: PetscFunctionBegin;
2194: PetscAssertPointer(iter, 2);
2195: *iter = tao->niter;
2196: PetscFunctionReturn(PETSC_SUCCESS);
2197: }
2199: /*@
2200: TaoGetResidualNorm - Gets the current value of the norm of the residual (gradient)
2201: at this time.
2203: Not Collective
2205: Input Parameter:
2206: . tao - the `Tao` context
2208: Output Parameter:
2209: . value - the current value
2211: Level: intermediate
2213: Developer Notes:
2214: This is the 2-norm of the residual, we cannot use `TaoGetGradientNorm()` because that has
2215: a different meaning. For some reason `Tao` sometimes calls the gradient the residual.
2217: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2218: @*/
2219: PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2220: {
2221: PetscFunctionBegin;
2223: PetscAssertPointer(value, 2);
2224: *value = tao->residual;
2225: PetscFunctionReturn(PETSC_SUCCESS);
2226: }
2228: /*@
2229: TaoSetIterationNumber - Sets the current iteration number.
2231: Logically Collective
2233: Input Parameters:
2234: + tao - the `Tao` context
2235: - iter - iteration number
2237: Level: developer
2239: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2240: @*/
2241: PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2242: {
2243: PetscFunctionBegin;
2246: PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2247: tao->niter = iter;
2248: PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2249: PetscFunctionReturn(PETSC_SUCCESS);
2250: }
2252: /*@
2253: TaoGetTotalIterationNumber - Gets the total number of `TaoSolve()` iterations
2254: completed. This number keeps accumulating if multiple solves
2255: are called with the `Tao` object.
2257: Not Collective
2259: Input Parameter:
2260: . tao - the `Tao` context
2262: Output Parameter:
2263: . iter - number of iterations
2265: Level: intermediate
2267: Note:
2268: The total iteration count is updated after each solve, if there is a current
2269: `TaoSolve()` in progress then those iterations are not included in the count
2271: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2272: @*/
2273: PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2274: {
2275: PetscFunctionBegin;
2277: PetscAssertPointer(iter, 2);
2278: *iter = tao->ntotalits;
2279: PetscFunctionReturn(PETSC_SUCCESS);
2280: }
2282: /*@
2283: TaoSetTotalIterationNumber - Sets the current total iteration number.
2285: Logically Collective
2287: Input Parameters:
2288: + tao - the `Tao` context
2289: - iter - the iteration number
2291: Level: developer
2293: .seealso: [](ch_tao), `Tao`, `TaoGetLinearSolveIterations()`
2294: @*/
2295: PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2296: {
2297: PetscFunctionBegin;
2300: PetscCall(PetscObjectSAWsTakeAccess((PetscObject)tao));
2301: tao->ntotalits = iter;
2302: PetscCall(PetscObjectSAWsGrantAccess((PetscObject)tao));
2303: PetscFunctionReturn(PETSC_SUCCESS);
2304: }
2306: /*@
2307: TaoSetConvergedReason - Sets the termination flag on a `Tao` object
2309: Logically Collective
2311: Input Parameters:
2312: + tao - the `Tao` context
2313: - reason - the `TaoConvergedReason`
2315: Level: intermediate
2317: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`
2318: @*/
2319: PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2320: {
2321: PetscFunctionBegin;
2324: tao->reason = reason;
2325: PetscFunctionReturn(PETSC_SUCCESS);
2326: }
2328: /*@
2329: TaoGetConvergedReason - Gets the reason the `TaoSolve()` was stopped.
2331: Not Collective
2333: Input Parameter:
2334: . tao - the `Tao` solver context
2336: Output Parameter:
2337: . reason - value of `TaoConvergedReason`
2339: Level: intermediate
2341: .seealso: [](ch_tao), `Tao`, `TaoConvergedReason`, `TaoSetConvergenceTest()`, `TaoSetTolerances()`
2342: @*/
2343: PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2344: {
2345: PetscFunctionBegin;
2347: PetscAssertPointer(reason, 2);
2348: *reason = tao->reason;
2349: PetscFunctionReturn(PETSC_SUCCESS);
2350: }
2352: /*@
2353: TaoGetSolutionStatus - Get the current iterate, objective value,
2354: residual, infeasibility, and termination from a `Tao` object
2356: Not Collective
2358: Input Parameter:
2359: . tao - the `Tao` context
2361: Output Parameters:
2362: + its - the current iterate number (>=0)
2363: . f - the current function value
2364: . gnorm - the square of the gradient norm, duality gap, or other measure indicating distance from optimality.
2365: . cnorm - the infeasibility of the current solution with regard to the constraints.
2366: . xdiff - the step length or trust region radius of the most recent iterate.
2367: - reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`
2369: Level: intermediate
2371: Notes:
2372: Tao returns the values set by the solvers in the routine `TaoMonitor()`.
2374: If any of the output arguments are set to `NULL`, no corresponding value will be returned.
2376: .seealso: [](ch_tao), `TaoMonitor()`, `TaoGetConvergedReason()`
2377: @*/
2378: PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2379: {
2380: PetscFunctionBegin;
2382: if (its) *its = tao->niter;
2383: if (f) *f = tao->fc;
2384: if (gnorm) *gnorm = tao->residual;
2385: if (cnorm) *cnorm = tao->cnorm;
2386: if (reason) *reason = tao->reason;
2387: if (xdiff) *xdiff = tao->step;
2388: PetscFunctionReturn(PETSC_SUCCESS);
2389: }
2391: /*@C
2392: TaoGetType - Gets the current `TaoType` being used in the `Tao` object
2394: Not Collective
2396: Input Parameter:
2397: . tao - the `Tao` solver context
2399: Output Parameter:
2400: . type - the `TaoType`
2402: Level: intermediate
2404: .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoSetType()`
2405: @*/
2406: PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2407: {
2408: PetscFunctionBegin;
2410: PetscAssertPointer(type, 2);
2411: *type = ((PetscObject)tao)->type_name;
2412: PetscFunctionReturn(PETSC_SUCCESS);
2413: }
2415: /*@C
2416: TaoMonitor - Monitor the solver and the current solution. This
2417: routine will record the iteration number and residual statistics,
2418: and call any monitors specified by the user.
2420: Input Parameters:
2421: + tao - the `Tao` context
2422: . its - the current iterate number (>=0)
2423: . f - the current objective function value
2424: . res - the gradient norm, square root of the duality gap, or other measure indicating distance from optimality. This measure will be recorded and
2425: used for some termination tests.
2426: . cnorm - the infeasibility of the current solution with regard to the constraints.
2427: - steplength - multiple of the step direction added to the previous iterate.
2429: Options Database Key:
2430: . -tao_monitor - Use the default monitor, which prints statistics to standard output
2432: Level: developer
2434: .seealso: [](ch_tao), `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoSetMonitor()`
2435: @*/
2436: PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2437: {
2438: PetscInt i;
2440: PetscFunctionBegin;
2442: tao->fc = f;
2443: tao->residual = res;
2444: tao->cnorm = cnorm;
2445: tao->step = steplength;
2446: if (!its) {
2447: tao->cnorm0 = cnorm;
2448: tao->gnorm0 = res;
2449: }
2450: PetscCall(VecLockReadPush(tao->solution));
2451: for (i = 0; i < tao->numbermonitors; i++) PetscCall((*tao->monitor[i])(tao, tao->monitorcontext[i]));
2452: PetscCall(VecLockReadPop(tao->solution));
2453: PetscFunctionReturn(PETSC_SUCCESS);
2454: }
2456: /*@
2457: TaoSetConvergenceHistory - Sets the array used to hold the convergence history.
2459: Logically Collective
2461: Input Parameters:
2462: + tao - the `Tao` solver context
2463: . obj - array to hold objective value history
2464: . resid - array to hold residual history
2465: . cnorm - array to hold constraint violation history
2466: . lits - integer array holds the number of linear iterations for each Tao iteration
2467: . na - size of `obj`, `resid`, and `cnorm`
2468: - reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2469: else it continues storing new values for new minimizations after the old ones
2471: Level: intermediate
2473: Notes:
2474: If set, `Tao` will fill the given arrays with the indicated
2475: information at each iteration. If 'obj','resid','cnorm','lits' are
2476: *all* `NULL` then space (using size `na`, or 1000 if na is `PETSC_DECIDE` or
2477: `PETSC_DEFAULT`) is allocated for the history.
2478: If not all are `NULL`, then only the non-`NULL` information categories
2479: will be stored, the others will be ignored.
2481: Any convergence information after iteration number 'na' will not be stored.
2483: This routine is useful, e.g., when running a code for purposes
2484: of accurate performance monitoring, when no I/O should be done
2485: during the section of code that is being timed.
2487: .seealso: [](ch_tao), `TaoGetConvergenceHistory()`
2488: @*/
2489: PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2490: {
2491: PetscFunctionBegin;
2493: if (obj) PetscAssertPointer(obj, 2);
2494: if (resid) PetscAssertPointer(resid, 3);
2495: if (cnorm) PetscAssertPointer(cnorm, 4);
2496: if (lits) PetscAssertPointer(lits, 5);
2498: if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
2499: if (!obj && !resid && !cnorm && !lits) {
2500: PetscCall(PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits));
2501: tao->hist_malloc = PETSC_TRUE;
2502: }
2504: tao->hist_obj = obj;
2505: tao->hist_resid = resid;
2506: tao->hist_cnorm = cnorm;
2507: tao->hist_lits = lits;
2508: tao->hist_max = na;
2509: tao->hist_reset = reset;
2510: tao->hist_len = 0;
2511: PetscFunctionReturn(PETSC_SUCCESS);
2512: }
2514: /*@C
2515: TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.
2517: Collective
2519: Input Parameter:
2520: . tao - the `Tao` context
2522: Output Parameters:
2523: + obj - array used to hold objective value history
2524: . resid - array used to hold residual history
2525: . cnorm - array used to hold constraint violation history
2526: . lits - integer array used to hold linear solver iteration count
2527: - nhist - size of `obj`, `resid`, `cnorm`, and `lits`
2529: Level: advanced
2531: Notes:
2532: This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2533: and `TaoSolve()`, otherwise it returns useless information.
2535: This routine is useful, e.g., when running a code for purposes
2536: of accurate performance monitoring, when no I/O should be done
2537: during the section of code that is being timed.
2539: Fortran Notes:
2540: The calling sequence is
2541: .vb
2542: call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)
2543: .ve
2545: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`
2546: @*/
2547: PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2548: {
2549: PetscFunctionBegin;
2551: if (obj) *obj = tao->hist_obj;
2552: if (cnorm) *cnorm = tao->hist_cnorm;
2553: if (resid) *resid = tao->hist_resid;
2554: if (lits) *lits = tao->hist_lits;
2555: if (nhist) *nhist = tao->hist_len;
2556: PetscFunctionReturn(PETSC_SUCCESS);
2557: }
2559: /*@
2560: TaoSetApplicationContext - Sets the optional user-defined context for a `Tao` solver.
2562: Logically Collective
2564: Input Parameters:
2565: + tao - the `Tao` context
2566: - usrP - optional user context
2568: Level: intermediate
2570: .seealso: [](ch_tao), `Tao`, `TaoGetApplicationContext()`
2571: @*/
2572: PetscErrorCode TaoSetApplicationContext(Tao tao, void *usrP)
2573: {
2574: PetscFunctionBegin;
2576: tao->user = usrP;
2577: PetscFunctionReturn(PETSC_SUCCESS);
2578: }
2580: /*@
2581: TaoGetApplicationContext - Gets the user-defined context for a `Tao` solver
2583: Not Collective
2585: Input Parameter:
2586: . tao - the `Tao` context
2588: Output Parameter:
2589: . usrP - user context
2591: Level: intermediate
2593: .seealso: [](ch_tao), `Tao`, `TaoSetApplicationContext()`
2594: @*/
2595: PetscErrorCode TaoGetApplicationContext(Tao tao, void *usrP)
2596: {
2597: PetscFunctionBegin;
2599: PetscAssertPointer(usrP, 2);
2600: *(void **)usrP = tao->user;
2601: PetscFunctionReturn(PETSC_SUCCESS);
2602: }
2604: /*@
2605: TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient.
2607: Collective
2609: Input Parameters:
2610: + tao - the `Tao` context
2611: - M - matrix that defines the norm
2613: Level: beginner
2615: .seealso: [](ch_tao), `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2616: @*/
2617: PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2618: {
2619: PetscFunctionBegin;
2622: PetscCall(PetscObjectReference((PetscObject)M));
2623: PetscCall(MatDestroy(&tao->gradient_norm));
2624: PetscCall(VecDestroy(&tao->gradient_norm_tmp));
2625: tao->gradient_norm = M;
2626: PetscCall(MatCreateVecs(M, NULL, &tao->gradient_norm_tmp));
2627: PetscFunctionReturn(PETSC_SUCCESS);
2628: }
2630: /*@
2631: TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient.
2633: Not Collective
2635: Input Parameter:
2636: . tao - the `Tao` context
2638: Output Parameter:
2639: . M - gradient norm
2641: Level: beginner
2643: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2644: @*/
2645: PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2646: {
2647: PetscFunctionBegin;
2649: PetscAssertPointer(M, 2);
2650: *M = tao->gradient_norm;
2651: PetscFunctionReturn(PETSC_SUCCESS);
2652: }
2654: /*@C
2655: TaoGradientNorm - Compute the norm using the `NormType`, the user has selected
2657: Collective
2659: Input Parameters:
2660: + tao - the `Tao` context
2661: . gradient - the gradient to be computed
2662: - type - the norm type
2664: Output Parameter:
2665: . gnorm - the gradient norm
2667: Level: advanced
2669: .seealso: [](ch_tao), `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2670: @*/
2671: PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2672: {
2673: PetscFunctionBegin;
2677: PetscAssertPointer(gnorm, 4);
2678: if (tao->gradient_norm) {
2679: PetscScalar gnorms;
2681: 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.");
2682: PetscCall(MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp));
2683: PetscCall(VecDot(gradient, tao->gradient_norm_tmp, &gnorms));
2684: *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2685: } else {
2686: PetscCall(VecNorm(gradient, type, gnorm));
2687: }
2688: PetscFunctionReturn(PETSC_SUCCESS);
2689: }
2691: /*@C
2692: TaoMonitorDrawCtxCreate - Creates the monitor context for `TaoMonitorDrawSolution()`
2694: Collective
2696: Input Parameters:
2697: + comm - the communicator to share the context
2698: . host - the name of the X Windows host that will display the monitor
2699: . label - the label to put at the top of the display window
2700: . x - the horizontal coordinate of the lower left corner of the window to open
2701: . y - the vertical coordinate of the lower left corner of the window to open
2702: . m - the width of the window
2703: . n - the height of the window
2704: - howoften - how many `Tao` iterations between displaying the monitor information
2706: Output Parameter:
2707: . ctx - the monitor context
2709: Options Database Key:
2710: . -tao_draw_solution_initial - show initial guess as well as current solution
2712: Level: intermediate
2714: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2715: @*/
2716: PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2717: {
2718: PetscFunctionBegin;
2719: PetscCall(PetscNew(ctx));
2720: PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
2721: PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
2722: (*ctx)->howoften = howoften;
2723: PetscFunctionReturn(PETSC_SUCCESS);
2724: }
2726: /*@C
2727: TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorDrawSolution()`
2729: Collective
2731: Input Parameter:
2732: . ictx - the monitor context
2734: Level: intermediate
2736: .seealso: [](ch_tao), `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawSolution()`
2737: @*/
2738: PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2739: {
2740: PetscFunctionBegin;
2741: PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
2742: PetscCall(PetscFree(*ictx));
2743: PetscFunctionReturn(PETSC_SUCCESS);
2744: }