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:   if (!snes_ewdummy) return 0;
 29:   /* populate snes_ewdummy struct values used in KSPPreSolve_SNESEW */
 30:   snes_ewdummy->vec_func = b;
 31:   snes_ewdummy->rtol     = tao->gttol;
 32:   snes_ewdummy->iter     = tao->niter;
 33:   VecNorm(b, NORM_2, &snes_ewdummy->norm);
 34:   KSPPreSolve_SNESEW(ksp, b, x, snes_ewdummy);
 35:   snes_ewdummy->vec_func = NULL;
 36:   return 0;
 37: }

 39: static PetscErrorCode KSPPostSolve_TAOEW_Private(KSP ksp, Vec b, Vec x, Tao tao)
 40: {
 41:   SNES snes_ewdummy = tao->snes_ewdummy;

 43:   if (!snes_ewdummy) return 0;
 44:   KSPPostSolve_SNESEW(ksp, b, x, snes_ewdummy);
 45:   return 0;
 46: }

 48: static PetscErrorCode TaoSetUpEW_Private(Tao tao)
 49: {
 50:   SNESKSPEW  *kctx;
 51:   const char *ewprefix;

 53:   if (!tao->ksp) return 0;
 54:   if (tao->ksp_ewconv) {
 55:     if (!tao->snes_ewdummy) SNESCreate(PetscObjectComm((PetscObject)tao), &tao->snes_ewdummy);
 56:     tao->snes_ewdummy->ksp_ewconv = PETSC_TRUE;
 57:     KSPSetPreSolve(tao->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_TAOEW_Private, tao);
 58:     KSPSetPostSolve(tao->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_TAOEW_Private, tao);

 60:     KSPGetOptionsPrefix(tao->ksp, &ewprefix);
 61:     kctx = (SNESKSPEW *)tao->snes_ewdummy->kspconvctx;
 62:     SNESEWSetFromOptions_Private(kctx, PetscObjectComm((PetscObject)tao), ewprefix);
 63:   } else SNESDestroy(&tao->snes_ewdummy);
 64:   return 0;
 65: }

 67: /*@
 68:   TaoCreate - Creates a Tao solver

 70:   Collective

 72:   Input Parameter:
 73: . comm - MPI communicator

 75:   Output Parameter:
 76: . newtao - the new Tao context

 78:   Available methods include:
 79: +    `TAONLS` - nls Newton's method with line search for unconstrained minimization
 80: .    `TAONTR` - ntr Newton's method with trust region for unconstrained minimization
 81: .    `TAONTL` - ntl Newton's method with trust region, line search for unconstrained minimization
 82: .    `TAOLMVM` - lmvm Limited memory variable metric method for unconstrained minimization
 83: .    `TAOCG` - cg Nonlinear conjugate gradient method for unconstrained minimization
 84: .    `TAONM` - nm Nelder-Mead algorithm for derivate-free unconstrained minimization
 85: .    `TAOTRON` - tron Newton Trust Region method for bound constrained minimization
 86: .    `TAOGPCG` - gpcg Newton Trust Region method for quadratic bound constrained minimization
 87: .    `TAOBLMVM` - blmvm Limited memory variable metric method for bound constrained minimization
 88: .    `TAOLCL` - lcl Linearly constrained Lagrangian method for pde-constrained minimization
 89: -    `TAOPOUNDERS` - pounders Model-based algorithm for nonlinear least squares

 91:    Options Database Keys:
 92: .   -tao_type - select which method Tao should use

 94:    Level: beginner

 96: .seealso: `Tao`, `TaoSolve()`, `TaoDestroy()`, `TAOSetFromOptions()`, `TAOSetType()`
 97: @*/
 98: PetscErrorCode TaoCreate(MPI_Comm comm, Tao *newtao)
 99: {
100:   Tao tao;

103:   TaoInitializePackage();
104:   TaoLineSearchInitializePackage();
105:   PetscHeaderCreate(tao, TAO_CLASSID, "Tao", "Optimization solver", "Tao", comm, TaoDestroy, TaoView);

107:   /* Set non-NULL defaults */
108:   tao->ops->convergencetest = TaoDefaultConvergenceTest;

110:   tao->max_it    = 10000;
111:   tao->max_funcs = -1;
112: #if defined(PETSC_USE_REAL_SINGLE)
113:   tao->gatol = 1e-5;
114:   tao->grtol = 1e-5;
115:   tao->crtol = 1e-5;
116:   tao->catol = 1e-5;
117: #else
118:   tao->gatol = 1e-8;
119:   tao->grtol = 1e-8;
120:   tao->crtol = 1e-8;
121:   tao->catol = 1e-8;
122: #endif
123:   tao->gttol   = 0.0;
124:   tao->steptol = 0.0;
125:   tao->trust0  = PETSC_INFINITY;
126:   tao->fmin    = PETSC_NINFINITY;

128:   tao->hist_reset = PETSC_TRUE;

130:   TaoResetStatistics(tao);
131:   *newtao = tao;
132:   return 0;
133: }

135: /*@
136:   TaoSolve - Solves an optimization problem min F(x) s.t. l <= x <= u

138:   Collective on tao

140:   Input Parameters:
141: . tao - the Tao context

143:   Notes:
144:   The user must set up the Tao with calls to `TaoSetSolution()`, `TaoSetObjective()`, `TaoSetGradient()`, and (if using 2nd order method) `TaoSetHessian()`.

146:   You should call `TaoGetConvergedReason()` or run with -tao_converged_reason to determine if the optimization algorithm actually succeeded or
147:   why it failed.

149:   Level: beginner

151: .seealso: `Tao`, `TaoCreate()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoGetConvergedReason()`, `TaoSetUp()`
152:  @*/
153: PetscErrorCode TaoSolve(Tao tao)
154: {
155:   static PetscBool set = PETSC_FALSE;

158:   PetscCall(PetscCitationsRegister("@TechReport{tao-user-ref,\n"
159:                                    "title   = {Toolkit for Advanced Optimization (TAO) Users Manual},\n"
160:                                    "author  = {Todd Munson and Jason Sarich and Stefan Wild and Steve Benson and Lois Curfman McInnes},\n"
161:                                    "Institution = {Argonne National Laboratory},\n"
162:                                    "Year   = 2014,\n"
163:                                    "Number = {ANL/MCS-TM-322 - Revision 3.5},\n"
164:                                    "url    = {https://www.mcs.anl.gov/research/projects/tao/}\n}\n",
165:                                    &set));
166:   tao->header_printed = PETSC_FALSE;
167:   TaoSetUp(tao);
168:   TaoResetStatistics(tao);
169:   if (tao->linesearch) TaoLineSearchReset(tao->linesearch);

171:   PetscLogEventBegin(TAO_Solve, tao, 0, 0, 0);
172:   PetscTryTypeMethod(tao, solve);
173:   PetscLogEventEnd(TAO_Solve, tao, 0, 0, 0);

175:   VecViewFromOptions(tao->solution, (PetscObject)tao, "-tao_view_solution");

177:   tao->ntotalits += tao->niter;
178:   TaoViewFromOptions(tao, NULL, "-tao_view");

180:   if (tao->printreason) {
181:     if (tao->reason > 0) {
182:       PetscPrintf(((PetscObject)tao)->comm, "TAO solve converged due to %s iterations %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter);
183:     } else {
184:       PetscPrintf(((PetscObject)tao)->comm, "TAO solve did not converge due to %s iteration %" PetscInt_FMT "\n", TaoConvergedReasons[tao->reason], tao->niter);
185:     }
186:   }
187:   return 0;
188: }

190: /*@
191:   TaoSetUp - Sets up the internal data structures for the later use
192:   of a Tao solver

194:   Collective on tao

196:   Input Parameters:
197: . tao - the Tao context

199:   Notes:
200:   The user will not need to explicitly call `TaoSetUp()`, as it will
201:   automatically be called in `TaoSolve()`.  However, if the user
202:   desires to call it explicitly, it should come after `TaoCreate()`
203:   and any TaoSetSomething() routines, but before `TaoSolve()`.

205:   Level: advanced

207: .seealso: `Tao`, `TaoCreate()`, `TaoSolve()`
208: @*/
209: PetscErrorCode TaoSetUp(Tao tao)
210: {
212:   if (tao->setupcalled) return 0;
213:   TaoSetUpEW_Private(tao);
215:   PetscTryTypeMethod(tao, setup);
216:   tao->setupcalled = PETSC_TRUE;
217:   return 0;
218: }

220: /*@C
221:   TaoDestroy - Destroys the Tao context that was created with `TaoCreate()`

223:   Collective on tao

225:   Input Parameter:
226: . tao - the Tao context

228:   Level: beginner

230: .seealso: `Tao`, `TaoCreate()`, `TaoSolve()`
231: @*/
232: PetscErrorCode TaoDestroy(Tao *tao)
233: {
234:   if (!*tao) return 0;
236:   if (--((PetscObject)*tao)->refct > 0) {
237:     *tao = NULL;
238:     return 0;
239:   }

241:   if ((*tao)->ops->destroy) (*((*tao))->ops->destroy)(*tao);
242:   KSPDestroy(&(*tao)->ksp);
243:   SNESDestroy(&(*tao)->snes_ewdummy);
244:   TaoLineSearchDestroy(&(*tao)->linesearch);

246:   if ((*tao)->ops->convergencedestroy) {
247:     (*(*tao)->ops->convergencedestroy)((*tao)->cnvP);
248:     if ((*tao)->jacobian_state_inv) MatDestroy(&(*tao)->jacobian_state_inv);
249:   }
250:   VecDestroy(&(*tao)->solution);
251:   VecDestroy(&(*tao)->gradient);
252:   VecDestroy(&(*tao)->ls_res);

254:   if ((*tao)->gradient_norm) {
255:     PetscObjectDereference((PetscObject)(*tao)->gradient_norm);
256:     VecDestroy(&(*tao)->gradient_norm_tmp);
257:   }

259:   VecDestroy(&(*tao)->XL);
260:   VecDestroy(&(*tao)->XU);
261:   VecDestroy(&(*tao)->IL);
262:   VecDestroy(&(*tao)->IU);
263:   VecDestroy(&(*tao)->DE);
264:   VecDestroy(&(*tao)->DI);
265:   VecDestroy(&(*tao)->constraints);
266:   VecDestroy(&(*tao)->constraints_equality);
267:   VecDestroy(&(*tao)->constraints_inequality);
268:   VecDestroy(&(*tao)->stepdirection);
269:   MatDestroy(&(*tao)->hessian_pre);
270:   MatDestroy(&(*tao)->hessian);
271:   MatDestroy(&(*tao)->ls_jac);
272:   MatDestroy(&(*tao)->ls_jac_pre);
273:   MatDestroy(&(*tao)->jacobian_pre);
274:   MatDestroy(&(*tao)->jacobian);
275:   MatDestroy(&(*tao)->jacobian_state_pre);
276:   MatDestroy(&(*tao)->jacobian_state);
277:   MatDestroy(&(*tao)->jacobian_state_inv);
278:   MatDestroy(&(*tao)->jacobian_design);
279:   MatDestroy(&(*tao)->jacobian_equality);
280:   MatDestroy(&(*tao)->jacobian_equality_pre);
281:   MatDestroy(&(*tao)->jacobian_inequality);
282:   MatDestroy(&(*tao)->jacobian_inequality_pre);
283:   ISDestroy(&(*tao)->state_is);
284:   ISDestroy(&(*tao)->design_is);
285:   VecDestroy(&(*tao)->res_weights_v);
286:   TaoCancelMonitors(*tao);
287:   if ((*tao)->hist_malloc) PetscFree4((*tao)->hist_obj, (*tao)->hist_resid, (*tao)->hist_cnorm, (*tao)->hist_lits);
288:   if ((*tao)->res_weights_n) {
289:     PetscFree((*tao)->res_weights_rows);
290:     PetscFree((*tao)->res_weights_cols);
291:     PetscFree((*tao)->res_weights_w);
292:   }
293:   PetscHeaderDestroy(tao);
294:   return 0;
295: }

297: /*@
298:    TaoKSPSetUseEW - Sets `SNES` use Eisenstat-Walker method for
299:    computing relative tolerance for linear solvers.

301:    Logically Collective on tao

303:    Input Parameters:
304: +  tao - Tao context
305: -  flag - `PETSC_TRUE` or `PETSC_FALSE`

307:    Notes:
308:    See `SNESKSPSetUseEW()` for customization details.

310:    Level: advanced

312:    Reference:
313:    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
314:    inexact Newton method", SISC 17 (1), pp.16-32, 1996.

316: .seealso: `Tao`, `SNESKSPSetUseEW()`
317: @*/
318: PetscErrorCode TaoKSPSetUseEW(Tao tao, PetscBool flag)
319: {
322:   tao->ksp_ewconv = flag;
323:   return 0;
324: }

326: /*@
327:   TaoSetFromOptions - Sets various Tao parameters from user
328:   options.

330:   Collective on tao

332:   Input Parameter:
333: . tao - the Tao solver context

335:   options Database Keys:
336: + -tao_type <type> - The algorithm that Tao uses (lmvm, nls, etc.)
337: . -tao_gatol <gatol> - absolute error tolerance for ||gradient||
338: . -tao_grtol <grtol> - relative error tolerance for ||gradient||
339: . -tao_gttol <gttol> - reduction of ||gradient|| relative to initial gradient
340: . -tao_max_it <max> - sets maximum number of iterations
341: . -tao_max_funcs <max> - sets maximum number of function evaluations
342: . -tao_fmin <fmin> - stop if function value reaches fmin
343: . -tao_steptol <tol> - stop if trust region radius less than <tol>
344: . -tao_trust0 <t> - initial trust region radius
345: . -tao_monitor - prints function value and residual at each iteration
346: . -tao_smonitor - same as tao_monitor, but truncates very small values
347: . -tao_cmonitor - prints function value, residual, and constraint norm at each iteration
348: . -tao_view_solution - prints solution vector at each iteration
349: . -tao_view_ls_residual - prints least-squares residual vector at each iteration
350: . -tao_view_stepdirection - prints step direction vector at each iteration
351: . -tao_view_gradient - prints gradient vector at each iteration
352: . -tao_draw_solution - graphically view solution vector at each iteration
353: . -tao_draw_step - graphically view step vector at each iteration
354: . -tao_draw_gradient - graphically view gradient at each iteration
355: . -tao_fd_gradient - use gradient computed with finite differences
356: . -tao_fd_hessian - use hessian computed with finite differences
357: . -tao_mf_hessian - use matrix-free hessian computed with finite differences
358: . -tao_cancelmonitors - cancels all monitors (except those set with command line)
359: . -tao_view - prints information about the Tao after solving
360: - -tao_converged_reason - prints the reason Tao stopped iterating

362:   Notes:
363:   To see all options, run your program with the -help option or consult the
364:  user's manual. Should be called after `TaoCreate()` but before `TaoSolve()`

366:   Level: beginner

368: .seealso: `Tao`, `TaoCreate()`, `TaoSolve()`
369: @*/
370: PetscErrorCode TaoSetFromOptions(Tao tao)
371: {
372:   TaoType     default_type = TAOLMVM;
373:   char        type[256], monfilename[PETSC_MAX_PATH_LEN];
374:   PetscViewer monviewer;
375:   PetscBool   flg;
376:   MPI_Comm    comm;

379:   PetscObjectGetComm((PetscObject)tao, &comm);

381:   /* So no warnings are given about unused options */
382:   PetscOptionsHasName(((PetscObject)tao)->options, ((PetscObject)tao)->prefix, "-tao_ls_type", &flg);

384:   PetscObjectOptionsBegin((PetscObject)tao);
385:   {
386:     if (((PetscObject)tao)->type_name) default_type = ((PetscObject)tao)->type_name;
387:     /* Check for type from options */
388:     PetscOptionsFList("-tao_type", "Tao Solver type", "TaoSetType", TaoList, default_type, type, 256, &flg);
389:     if (flg) {
390:       TaoSetType(tao, type);
391:     } else if (!((PetscObject)tao)->type_name) {
392:       TaoSetType(tao, default_type);
393:     }

395:     PetscOptionsReal("-tao_catol", "Stop if constraints violations within", "TaoSetConstraintTolerances", tao->catol, &tao->catol, &flg);
396:     if (flg) tao->catol_changed = PETSC_TRUE;
397:     PetscOptionsReal("-tao_crtol", "Stop if relative constraint violations within", "TaoSetConstraintTolerances", tao->crtol, &tao->crtol, &flg);
398:     if (flg) tao->crtol_changed = PETSC_TRUE;
399:     PetscOptionsReal("-tao_gatol", "Stop if norm of gradient less than", "TaoSetTolerances", tao->gatol, &tao->gatol, &flg);
400:     if (flg) tao->gatol_changed = PETSC_TRUE;
401:     PetscOptionsReal("-tao_grtol", "Stop if norm of gradient divided by the function value is less than", "TaoSetTolerances", tao->grtol, &tao->grtol, &flg);
402:     if (flg) tao->grtol_changed = PETSC_TRUE;
403:     PetscOptionsReal("-tao_gttol", "Stop if the norm of the gradient is less than the norm of the initial gradient times tol", "TaoSetTolerances", tao->gttol, &tao->gttol, &flg);
404:     if (flg) tao->gttol_changed = PETSC_TRUE;
405:     PetscOptionsInt("-tao_max_it", "Stop if iteration number exceeds", "TaoSetMaximumIterations", tao->max_it, &tao->max_it, &flg);
406:     if (flg) tao->max_it_changed = PETSC_TRUE;
407:     PetscOptionsInt("-tao_max_funcs", "Stop if number of function evaluations exceeds", "TaoSetMaximumFunctionEvaluations", tao->max_funcs, &tao->max_funcs, &flg);
408:     if (flg) tao->max_funcs_changed = PETSC_TRUE;
409:     PetscOptionsReal("-tao_fmin", "Stop if function less than", "TaoSetFunctionLowerBound", tao->fmin, &tao->fmin, &flg);
410:     if (flg) tao->fmin_changed = PETSC_TRUE;
411:     PetscOptionsReal("-tao_steptol", "Stop if step size or trust region radius less than", "", tao->steptol, &tao->steptol, &flg);
412:     if (flg) tao->steptol_changed = PETSC_TRUE;
413:     PetscOptionsReal("-tao_trust0", "Initial trust region radius", "TaoSetTrustRegionRadius", tao->trust0, &tao->trust0, &flg);
414:     if (flg) tao->trust0_changed = PETSC_TRUE;
415:     PetscOptionsString("-tao_view_solution", "view solution vector after each evaluation", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
416:     if (flg) {
417:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
418:       TaoSetMonitor(tao, TaoSolutionMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
419:     }

421:     PetscOptionsBool("-tao_converged_reason", "Print reason for Tao converged", "TaoSolve", tao->printreason, &tao->printreason, NULL);
422:     PetscOptionsString("-tao_view_gradient", "view gradient vector after each evaluation", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
423:     if (flg) {
424:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
425:       TaoSetMonitor(tao, TaoGradientMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
426:     }

428:     PetscOptionsString("-tao_view_stepdirection", "view step direction vector after each iteration", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
429:     if (flg) {
430:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
431:       TaoSetMonitor(tao, TaoStepDirectionMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
432:     }

434:     PetscOptionsString("-tao_view_residual", "view least-squares residual vector after each evaluation", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
435:     if (flg) {
436:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
437:       TaoSetMonitor(tao, TaoResidualMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
438:     }

440:     PetscOptionsString("-tao_monitor", "Use the default convergence monitor", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
441:     if (flg) {
442:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
443:       TaoSetMonitor(tao, TaoMonitorDefault, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
444:     }

446:     PetscOptionsString("-tao_gmonitor", "Use the convergence monitor with extra globalization info", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
447:     if (flg) {
448:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
449:       TaoSetMonitor(tao, TaoDefaultGMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
450:     }

452:     PetscOptionsString("-tao_smonitor", "Use the short convergence monitor", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
453:     if (flg) {
454:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
455:       TaoSetMonitor(tao, TaoDefaultSMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
456:     }

458:     PetscOptionsString("-tao_cmonitor", "Use the default convergence monitor with constraint norm", "TaoSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg);
459:     if (flg) {
460:       PetscViewerASCIIOpen(comm, monfilename, &monviewer);
461:       TaoSetMonitor(tao, TaoDefaultCMonitor, monviewer, (PetscErrorCode(*)(void **))PetscViewerDestroy);
462:     }

464:     flg = PETSC_FALSE;
465:     PetscOptionsBool("-tao_cancelmonitors", "cancel all monitors and call any registered destroy routines", "TaoCancelMonitors", flg, &flg, NULL);
466:     if (flg) TaoCancelMonitors(tao);

468:     flg = PETSC_FALSE;
469:     PetscOptionsBool("-tao_draw_solution", "Plot solution vector at each iteration", "TaoSetMonitor", flg, &flg, NULL);
470:     if (flg) {
471:       TaoMonitorDrawCtx drawctx;
472:       PetscInt          howoften = 1;
473:       TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx);
474:       TaoSetMonitor(tao, TaoDrawSolutionMonitor, drawctx, (PetscErrorCode(*)(void **))TaoMonitorDrawCtxDestroy);
475:     }

477:     flg = PETSC_FALSE;
478:     PetscOptionsBool("-tao_draw_step", "plots step direction at each iteration", "TaoSetMonitor", flg, &flg, NULL);
479:     if (flg) TaoSetMonitor(tao, TaoDrawStepMonitor, NULL, NULL);

481:     flg = PETSC_FALSE;
482:     PetscOptionsBool("-tao_draw_gradient", "plots gradient at each iteration", "TaoSetMonitor", flg, &flg, NULL);
483:     if (flg) {
484:       TaoMonitorDrawCtx drawctx;
485:       PetscInt          howoften = 1;
486:       TaoMonitorDrawCtxCreate(PetscObjectComm((PetscObject)tao), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &drawctx);
487:       TaoSetMonitor(tao, TaoDrawGradientMonitor, drawctx, (PetscErrorCode(*)(void **))TaoMonitorDrawCtxDestroy);
488:     }
489:     flg = PETSC_FALSE;
490:     PetscOptionsBool("-tao_fd_gradient", "compute gradient using finite differences", "TaoDefaultComputeGradient", flg, &flg, NULL);
491:     if (flg) TaoSetGradient(tao, NULL, TaoDefaultComputeGradient, NULL);
492:     flg = PETSC_FALSE;
493:     PetscOptionsBool("-tao_fd_hessian", "compute hessian using finite differences", "TaoDefaultComputeHessian", flg, &flg, NULL);
494:     if (flg) {
495:       Mat H;

497:       MatCreate(PetscObjectComm((PetscObject)tao), &H);
498:       MatSetType(H, MATAIJ);
499:       TaoSetHessian(tao, H, H, TaoDefaultComputeHessian, NULL);
500:       MatDestroy(&H);
501:     }
502:     flg = PETSC_FALSE;
503:     PetscOptionsBool("-tao_mf_hessian", "compute matrix-free hessian using finite differences", "TaoDefaultComputeHessianMFFD", flg, &flg, NULL);
504:     if (flg) {
505:       Mat H;

507:       MatCreate(PetscObjectComm((PetscObject)tao), &H);
508:       TaoSetHessian(tao, H, H, TaoDefaultComputeHessianMFFD, NULL);
509:       MatDestroy(&H);
510:     }
511:     flg = PETSC_FALSE;
512:     PetscOptionsBool("-tao_recycle_history", "enable recycling/re-using information from the previous TaoSolve() call for some algorithms", "TaoSetRecycleHistory", flg, &flg, NULL);
513:     if (flg) TaoSetRecycleHistory(tao, PETSC_TRUE);
514:     PetscOptionsEnum("-tao_subset_type", "subset type", "", TaoSubSetTypes, (PetscEnum)tao->subset_type, (PetscEnum *)&tao->subset_type, NULL);

516:     if (tao->ksp) {
517:       PetscOptionsBool("-tao_ksp_ew", "Use Eisentat-Walker linear system convergence test", "TaoKSPSetUseEW", tao->ksp_ewconv, &tao->ksp_ewconv, NULL);
518:       TaoKSPSetUseEW(tao, tao->ksp_ewconv);
519:     }

521:     if (tao->linesearch) TaoLineSearchSetFromOptions(tao->linesearch);

523:     PetscTryTypeMethod(tao, setfromoptions, PetscOptionsObject);
524:   }
525:   PetscOptionsEnd();
526:   return 0;
527: }

529: /*@C
530:    TaoViewFromOptions - View a Tao options from the options database

532:    Collective on tao

534:    Input Parameters:
535: +  A - the  Tao context
536: .  obj - Optional object
537: -  name - command line option

539:    Level: intermediate
540: .seealso: `Tao`, `TaoView`, `PetscObjectViewFromOptions()`, `TaoCreate()`
541: @*/
542: PetscErrorCode TaoViewFromOptions(Tao A, PetscObject obj, const char name[])
543: {
545:   PetscObjectViewFromOptions((PetscObject)A, obj, name);
546:   return 0;
547: }

549: /*@C
550:   TaoView - Prints information about the Tao object

552:   Collective on tao

554:   InputParameters:
555: + tao - the Tao context
556: - viewer - visualization context

558:   Options Database Key:
559: . -tao_view - Calls `TaoView()` at the end of `TaoSolve()`

561:   Notes:
562:   The available visualization contexts include
563: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
564: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
565:          output where only the first processor opens
566:          the file.  All other processors send their
567:          data to the first processor to print.

569:   Level: beginner

571: .seealso: `PetscViewerASCIIOpen()`
572: @*/
573: PetscErrorCode TaoView(Tao tao, PetscViewer viewer)
574: {
575:   PetscBool isascii, isstring;
576:   TaoType   type;

579:   if (!viewer) PetscViewerASCIIGetStdout(((PetscObject)tao)->comm, &viewer);

583:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
584:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring);
585:   if (isascii) {
586:     PetscObjectPrintClassNamePrefixType((PetscObject)tao, viewer);

588:     if (tao->ops->view) {
589:       PetscViewerASCIIPushTab(viewer);
590:       PetscUseTypeMethod(tao, view, viewer);
591:       PetscViewerASCIIPopTab(viewer);
592:     }
593:     if (tao->linesearch) {
594:       PetscViewerASCIIPushTab(viewer);
595:       TaoLineSearchView(tao->linesearch, viewer);
596:       PetscViewerASCIIPopTab(viewer);
597:     }
598:     if (tao->ksp) {
599:       PetscViewerASCIIPushTab(viewer);
600:       KSPView(tao->ksp, viewer);
601:       PetscViewerASCIIPrintf(viewer, "total KSP iterations: %" PetscInt_FMT "\n", tao->ksp_tot_its);
602:       PetscViewerASCIIPopTab(viewer);
603:     }

605:     PetscViewerASCIIPushTab(viewer);

607:     if (tao->XL || tao->XU) PetscViewerASCIIPrintf(viewer, "Active Set subset type: %s\n", TaoSubSetTypes[tao->subset_type]);

609:     PetscViewerASCIIPrintf(viewer, "convergence tolerances: gatol=%g,", (double)tao->gatol);
610:     PetscViewerASCIIPrintf(viewer, " steptol=%g,", (double)tao->steptol);
611:     PetscViewerASCIIPrintf(viewer, " gttol=%g\n", (double)tao->gttol);
612:     PetscViewerASCIIPrintf(viewer, "Residual in Function/Gradient:=%g\n", (double)tao->residual);

614:     if (tao->constrained) {
615:       PetscViewerASCIIPrintf(viewer, "convergence tolerances:");
616:       PetscViewerASCIIPrintf(viewer, " catol=%g,", (double)tao->catol);
617:       PetscViewerASCIIPrintf(viewer, " crtol=%g\n", (double)tao->crtol);
618:       PetscViewerASCIIPrintf(viewer, "Residual in Constraints:=%g\n", (double)tao->cnorm);
619:     }

621:     if (tao->trust < tao->steptol) {
622:       PetscViewerASCIIPrintf(viewer, "convergence tolerances: steptol=%g\n", (double)tao->steptol);
623:       PetscViewerASCIIPrintf(viewer, "Final trust region radius:=%g\n", (double)tao->trust);
624:     }

626:     if (tao->fmin > -1.e25) PetscViewerASCIIPrintf(viewer, "convergence tolerances: function minimum=%g\n", (double)tao->fmin);
627:     PetscViewerASCIIPrintf(viewer, "Objective value=%g\n", (double)tao->fc);

629:     PetscViewerASCIIPrintf(viewer, "total number of iterations=%" PetscInt_FMT ",          ", tao->niter);
630:     PetscViewerASCIIPrintf(viewer, "              (max: %" PetscInt_FMT ")\n", tao->max_it);

632:     if (tao->nfuncs > 0) {
633:       PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT ",", tao->nfuncs);
634:       PetscViewerASCIIPrintf(viewer, "                max: %" PetscInt_FMT "\n", tao->max_funcs);
635:     }
636:     if (tao->ngrads > 0) {
637:       PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT ",", tao->ngrads);
638:       PetscViewerASCIIPrintf(viewer, "                max: %" PetscInt_FMT "\n", tao->max_funcs);
639:     }
640:     if (tao->nfuncgrads > 0) {
641:       PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT ",", tao->nfuncgrads);
642:       PetscViewerASCIIPrintf(viewer, "    (max: %" PetscInt_FMT ")\n", tao->max_funcs);
643:     }
644:     if (tao->nhess > 0) PetscViewerASCIIPrintf(viewer, "total number of Hessian evaluations=%" PetscInt_FMT "\n", tao->nhess);
645:     if (tao->nconstraints > 0) PetscViewerASCIIPrintf(viewer, "total number of constraint function evaluations=%" PetscInt_FMT "\n", tao->nconstraints);
646:     if (tao->njac > 0) PetscViewerASCIIPrintf(viewer, "total number of Jacobian evaluations=%" PetscInt_FMT "\n", tao->njac);

648:     if (tao->reason > 0) {
649:       PetscViewerASCIIPrintf(viewer, "Solution converged: ");
650:       switch (tao->reason) {
651:       case TAO_CONVERGED_GATOL:
652:         PetscViewerASCIIPrintf(viewer, " ||g(X)|| <= gatol\n");
653:         break;
654:       case TAO_CONVERGED_GRTOL:
655:         PetscViewerASCIIPrintf(viewer, " ||g(X)||/|f(X)| <= grtol\n");
656:         break;
657:       case TAO_CONVERGED_GTTOL:
658:         PetscViewerASCIIPrintf(viewer, " ||g(X)||/||g(X0)|| <= gttol\n");
659:         break;
660:       case TAO_CONVERGED_STEPTOL:
661:         PetscViewerASCIIPrintf(viewer, " Steptol -- step size small\n");
662:         break;
663:       case TAO_CONVERGED_MINF:
664:         PetscViewerASCIIPrintf(viewer, " Minf --  f < fmin\n");
665:         break;
666:       case TAO_CONVERGED_USER:
667:         PetscViewerASCIIPrintf(viewer, " User Terminated\n");
668:         break;
669:       default:
670:         PetscViewerASCIIPrintf(viewer, "\n");
671:         break;
672:       }
673:     } else {
674:       PetscViewerASCIIPrintf(viewer, "Solver terminated: %d", tao->reason);
675:       switch (tao->reason) {
676:       case TAO_DIVERGED_MAXITS:
677:         PetscViewerASCIIPrintf(viewer, " Maximum Iterations\n");
678:         break;
679:       case TAO_DIVERGED_NAN:
680:         PetscViewerASCIIPrintf(viewer, " NAN or Inf encountered\n");
681:         break;
682:       case TAO_DIVERGED_MAXFCN:
683:         PetscViewerASCIIPrintf(viewer, " Maximum Function Evaluations\n");
684:         break;
685:       case TAO_DIVERGED_LS_FAILURE:
686:         PetscViewerASCIIPrintf(viewer, " Line Search Failure\n");
687:         break;
688:       case TAO_DIVERGED_TR_REDUCTION:
689:         PetscViewerASCIIPrintf(viewer, " Trust Region too small\n");
690:         break;
691:       case TAO_DIVERGED_USER:
692:         PetscViewerASCIIPrintf(viewer, " User Terminated\n");
693:         break;
694:       default:
695:         PetscViewerASCIIPrintf(viewer, "\n");
696:         break;
697:       }
698:     }
699:     PetscViewerASCIIPopTab(viewer);
700:   } else if (isstring) {
701:     TaoGetType(tao, &type);
702:     PetscViewerStringSPrintf(viewer, " %-3.3s", type);
703:   }
704:   return 0;
705: }

707: /*@
708:   TaoSetRecycleHistory - Sets the boolean flag to enable/disable re-using
709:   iterate information from the previous `TaoSolve()`. This feature is disabled by
710:   default.

712:   For conjugate gradient methods (`TAOBNCG`), this re-uses the latest search direction
713:   from the previous `TaoSolve()` call when computing the first search direction in a
714:   new solution. By default, CG methods set the first search direction to the
715:   negative gradient.

717:   For quasi-Newton family of methods (`TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`), this re-uses
718:   the accumulated quasi-Newton Hessian approximation from the previous `TaoSolve()`
719:   call. By default, QN family of methods reset the initial Hessian approximation to
720:   the identity matrix.

722:   For any other algorithm, this setting has no effect.

724:   Logically collective on tao

726:   Input Parameters:
727: + tao - the Tao context
728: - recycle - boolean flag

730:   Options Database Keys:
731: . -tao_recycle_history <true,false> - reuse the history

733:   Level: intermediate

735: .seealso: `TaoGetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`

737: @*/
738: PetscErrorCode TaoSetRecycleHistory(Tao tao, PetscBool recycle)
739: {
742:   tao->recycle = recycle;
743:   return 0;
744: }

746: /*@
747:   TaoGetRecycleHistory - Retrieve the boolean flag for re-using iterate information
748:   from the previous `TaoSolve()`. This feature is disabled by default.

750:   Logically collective on tao

752:   Input Parameters:
753: . tao - the Tao context

755:   Output Parameters:
756: . recycle - boolean flag

758:   Level: intermediate

760: .seealso: `TaoSetRecycleHistory()`, `TAOBNCG`, `TAOBQNLS`, `TAOBQNKLS`, `TAOBQNKTR`, `TAOBQNKTL`

762: @*/
763: PetscErrorCode TaoGetRecycleHistory(Tao tao, PetscBool *recycle)
764: {
767:   *recycle = tao->recycle;
768:   return 0;
769: }

771: /*@
772:   TaoSetTolerances - Sets parameters used in Tao convergence tests

774:   Logically collective on tao

776:   Input Parameters:
777: + tao - the Tao context
778: . gatol - stop if norm of gradient is less than this
779: . grtol - stop if relative norm of gradient is less than this
780: - gttol - stop if norm of gradient is reduced by this factor

782:   Options Database Keys:
783: + -tao_gatol <gatol> - Sets gatol
784: . -tao_grtol <grtol> - Sets grtol
785: - -tao_gttol <gttol> - Sets gttol

787:   Stopping Criteria:
788: $ ||g(X)||                            <= gatol
789: $ ||g(X)|| / |f(X)|                   <= grtol
790: $ ||g(X)|| / ||g(X0)||                <= gttol

792:   Notes:
793:   Use PETSC_DEFAULT to leave one or more tolerances unchanged.

795:   Level: beginner

797: .seealso: `TaoGetTolerances()`

799: @*/
800: PetscErrorCode TaoSetTolerances(Tao tao, PetscReal gatol, PetscReal grtol, PetscReal gttol)
801: {

807:   if (gatol != PETSC_DEFAULT) {
808:     if (gatol < 0) {
809:       PetscInfo(tao, "Tried to set negative gatol -- ignored.\n");
810:     } else {
811:       tao->gatol         = PetscMax(0, gatol);
812:       tao->gatol_changed = PETSC_TRUE;
813:     }
814:   }

816:   if (grtol != PETSC_DEFAULT) {
817:     if (grtol < 0) {
818:       PetscInfo(tao, "Tried to set negative grtol -- ignored.\n");
819:     } else {
820:       tao->grtol         = PetscMax(0, grtol);
821:       tao->grtol_changed = PETSC_TRUE;
822:     }
823:   }

825:   if (gttol != PETSC_DEFAULT) {
826:     if (gttol < 0) {
827:       PetscInfo(tao, "Tried to set negative gttol -- ignored.\n");
828:     } else {
829:       tao->gttol         = PetscMax(0, gttol);
830:       tao->gttol_changed = PETSC_TRUE;
831:     }
832:   }
833:   return 0;
834: }

836: /*@
837:   TaoSetConstraintTolerances - Sets constraint tolerance parameters used in Tao convergence tests

839:   Logically collective on tao

841:   Input Parameters:
842: + tao - the Tao context
843: . catol - absolute constraint tolerance, constraint norm must be less than catol for used for gatol convergence criteria
844: - crtol - relative constraint tolerance, constraint norm must be less than crtol for used for gatol, gttol convergence criteria

846:   Options Database Keys:
847: + -tao_catol <catol> - Sets catol
848: - -tao_crtol <crtol> - Sets crtol

850:   Notes:
851:   Use PETSC_DEFAULT to leave any tolerance unchanged.

853:   Level: intermediate

855: .seealso: `TaoGetTolerances()`, `TaoGetConstraintTolerances()`, `TaoSetTolerances()`

857: @*/
858: PetscErrorCode TaoSetConstraintTolerances(Tao tao, PetscReal catol, PetscReal crtol)
859: {

864:   if (catol != PETSC_DEFAULT) {
865:     if (catol < 0) {
866:       PetscInfo(tao, "Tried to set negative catol -- ignored.\n");
867:     } else {
868:       tao->catol         = PetscMax(0, catol);
869:       tao->catol_changed = PETSC_TRUE;
870:     }
871:   }

873:   if (crtol != PETSC_DEFAULT) {
874:     if (crtol < 0) {
875:       PetscInfo(tao, "Tried to set negative crtol -- ignored.\n");
876:     } else {
877:       tao->crtol         = PetscMax(0, crtol);
878:       tao->crtol_changed = PETSC_TRUE;
879:     }
880:   }
881:   return 0;
882: }

884: /*@
885:   TaoGetConstraintTolerances - Gets constraint tolerance parameters used in Tao  convergence tests

887:   Not ollective

889:   Input Parameter:
890: . tao - the Tao context

892:   Output Parameters:
893: + catol - absolute constraint tolerance, constraint norm must be less than catol for used for gatol convergence criteria
894: - crtol - relative constraint tolerance, constraint norm must be less than crtol for used for gatol, gttol convergence criteria

896:   Level: intermediate

898: .seealso: `TaoGetTolerances()`, `TaoSetTolerances()`, `TaoSetConstraintTolerances()`

900: @*/
901: PetscErrorCode TaoGetConstraintTolerances(Tao tao, PetscReal *catol, PetscReal *crtol)
902: {
904:   if (catol) *catol = tao->catol;
905:   if (crtol) *crtol = tao->crtol;
906:   return 0;
907: }

909: /*@
910:    TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
911:    When an approximate solution with an objective value below this number
912:    has been found, the solver will terminate.

914:    Logically Collective on tao

916:    Input Parameters:
917: +  tao - the Tao solver context
918: -  fmin - the tolerance

920:    Options Database Keys:
921: .    -tao_fmin <fmin> - sets the minimum function value

923:    Level: intermediate

925: .seealso: `TaoSetTolerances()`
926: @*/
927: PetscErrorCode TaoSetFunctionLowerBound(Tao tao, PetscReal fmin)
928: {
931:   tao->fmin         = fmin;
932:   tao->fmin_changed = PETSC_TRUE;
933:   return 0;
934: }

936: /*@
937:    TaoGetFunctionLowerBound - Gets the bound on the solution objective value.
938:    When an approximate solution with an objective value below this number
939:    has been found, the solver will terminate.

941:    Not collective on tao

943:    Input Parameters:
944: .  tao - the Tao solver context

946:    OutputParameters:
947: .  fmin - the minimum function value

949:    Level: intermediate

951: .seealso: `TaoSetFunctionLowerBound()`
952: @*/
953: PetscErrorCode TaoGetFunctionLowerBound(Tao tao, PetscReal *fmin)
954: {
957:   *fmin = tao->fmin;
958:   return 0;
959: }

961: /*@
962:    TaoSetMaximumFunctionEvaluations - Sets a maximum number of
963:    function evaluations.

965:    Logically Collective on tao

967:    Input Parameters:
968: +  tao - the Tao solver context
969: -  nfcn - the maximum number of function evaluations (>=0)

971:    Options Database Keys:
972: .    -tao_max_funcs <nfcn> - sets the maximum number of function evaluations

974:    Level: intermediate

976: .seealso: `TaoSetTolerances()`, `TaoSetMaximumIterations()`
977: @*/

979: PetscErrorCode TaoSetMaximumFunctionEvaluations(Tao tao, PetscInt nfcn)
980: {
983:   if (nfcn >= 0) {
984:     tao->max_funcs = PetscMax(0, nfcn);
985:   } else {
986:     tao->max_funcs = -1;
987:   }
988:   tao->max_funcs_changed = PETSC_TRUE;
989:   return 0;
990: }

992: /*@
993:    TaoGetMaximumFunctionEvaluations - Gets a maximum number of
994:    function evaluations.

996:    Logically Collective on tao

998:    Input Parameters:
999: .  tao - the Tao solver context

1001:    Output Parameters:
1002: .  nfcn - the maximum number of function evaluations

1004:    Level: intermediate

1006: .seealso: `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1007: @*/

1009: PetscErrorCode TaoGetMaximumFunctionEvaluations(Tao tao, PetscInt *nfcn)
1010: {
1013:   *nfcn = tao->max_funcs;
1014:   return 0;
1015: }

1017: /*@
1018:    TaoGetCurrentFunctionEvaluations - Get current number of
1019:    function evaluations.

1021:    Not Collective

1023:    Input Parameters:
1024: .  tao - the Tao solver context

1026:    Output Parameters:
1027: .  nfuncs - the current number of function evaluations (maximum between gradient and function evaluations)

1029:    Level: intermediate

1031: .seealso: `TaoSetMaximumFunctionEvaluations()`, `TaoGetMaximumFunctionEvaluations()`, `TaoGetMaximumIterations()`
1032: @*/

1034: PetscErrorCode TaoGetCurrentFunctionEvaluations(Tao tao, PetscInt *nfuncs)
1035: {
1038:   *nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1039:   return 0;
1040: }

1042: /*@
1043:    TaoSetMaximumIterations - Sets a maximum number of iterates.

1045:    Logically Collective on tao

1047:    Input Parameters:
1048: +  tao - the Tao solver context
1049: -  maxits - the maximum number of iterates (>=0)

1051:    Options Database Keys:
1052: .    -tao_max_it <its> - sets the maximum number of iterations

1054:    Level: intermediate

1056: .seealso: `TaoSetTolerances()`, `TaoSetMaximumFunctionEvaluations()`
1057: @*/
1058: PetscErrorCode TaoSetMaximumIterations(Tao tao, PetscInt maxits)
1059: {
1062:   tao->max_it         = PetscMax(0, maxits);
1063:   tao->max_it_changed = PETSC_TRUE;
1064:   return 0;
1065: }

1067: /*@
1068:    TaoGetMaximumIterations - Gets a maximum number of iterates that will be used

1070:    Not Collective

1072:    Input Parameters:
1073: .  tao - the Tao solver context

1075:    Output Parameters:
1076: .  maxits - the maximum number of iterates

1078:    Level: intermediate

1080: .seealso: `TaoSetMaximumIterations()`, `TaoGetMaximumFunctionEvaluations()`
1081: @*/
1082: PetscErrorCode TaoGetMaximumIterations(Tao tao, PetscInt *maxits)
1083: {
1086:   *maxits = tao->max_it;
1087:   return 0;
1088: }

1090: /*@
1091:    TaoSetInitialTrustRegionRadius - Sets the initial trust region radius.

1093:    Logically collective on tao

1095:    Input Parameters:
1096: +  tao - a Tao optimization solver
1097: -  radius - the trust region radius

1099:    Level: intermediate

1101:    Options Database Key:
1102: .  -tao_trust0 <t0> - sets initial trust region radius

1104: .seealso: `TaoGetTrustRegionRadius()`, `TaoSetTrustRegionTolerance()`, `TAONTR`
1105: @*/
1106: PetscErrorCode TaoSetInitialTrustRegionRadius(Tao tao, PetscReal radius)
1107: {
1110:   tao->trust0         = PetscMax(0.0, radius);
1111:   tao->trust0_changed = PETSC_TRUE;
1112:   return 0;
1113: }

1115: /*@
1116:    TaoGetInitialTrustRegionRadius - Gets the initial trust region radius.

1118:    Not Collective

1120:    Input Parameter:
1121: .  tao - a Tao optimization solver

1123:    Output Parameter:
1124: .  radius - the trust region radius

1126:    Level: intermediate

1128: .seealso: `TaoSetInitialTrustRegionRadius()`, `TaoGetCurrentTrustRegionRadius()`, `TAONTR`
1129: @*/
1130: PetscErrorCode TaoGetInitialTrustRegionRadius(Tao tao, PetscReal *radius)
1131: {
1134:   *radius = tao->trust0;
1135:   return 0;
1136: }

1138: /*@
1139:    TaoGetCurrentTrustRegionRadius - Gets the current trust region radius.

1141:    Not Collective

1143:    Input Parameter:
1144: .  tao - a Tao optimization solver

1146:    Output Parameter:
1147: .  radius - the trust region radius

1149:    Level: intermediate

1151: .seealso: `TaoSetInitialTrustRegionRadius()`, `TaoGetInitialTrustRegionRadius()`, `TAONTR`
1152: @*/
1153: PetscErrorCode TaoGetCurrentTrustRegionRadius(Tao tao, PetscReal *radius)
1154: {
1157:   *radius = tao->trust;
1158:   return 0;
1159: }

1161: /*@
1162:   TaoGetTolerances - gets the current values of tolerances

1164:   Not Collective

1166:   Input Parameter:
1167: . tao - the Tao context

1169:   Output Parameters:
1170: + gatol - stop if norm of gradient is less than this
1171: . grtol - stop if relative norm of gradient is less than this
1172: - gttol - stop if norm of gradient is reduced by a this factor

1174:   Note: NULL can be used as an argument if not all tolerances values are needed

1176: .seealso `TaoSetTolerances()`

1178:   Level: intermediate
1179: @*/
1180: PetscErrorCode TaoGetTolerances(Tao tao, PetscReal *gatol, PetscReal *grtol, PetscReal *gttol)
1181: {
1183:   if (gatol) *gatol = tao->gatol;
1184:   if (grtol) *grtol = tao->grtol;
1185:   if (gttol) *gttol = tao->gttol;
1186:   return 0;
1187: }

1189: /*@
1190:   TaoGetKSP - Gets the linear solver used by the optimization solver.
1191:   Application writers should use `TaoGetKSP()` if they need direct access
1192:   to the PETSc `KSP` object.

1194:   Not Collective

1196:    Input Parameters:
1197: .  tao - the Tao solver

1199:    Output Parameters:
1200: .  ksp - the KSP linear solver used in the optimization solver

1202:    Level: intermediate

1204: .seealso: `Tao`, `KSP`
1205: @*/
1206: PetscErrorCode TaoGetKSP(Tao tao, KSP *ksp)
1207: {
1210:   *ksp = tao->ksp;
1211:   return 0;
1212: }

1214: /*@
1215:    TaoGetLinearSolveIterations - Gets the total number of linear iterations
1216:    used by the Tao solver

1218:    Not Collective

1220:    Input Parameter:
1221: .  tao - Tao context

1223:    Output Parameter:
1224: .  lits - number of linear iterations

1226:    Notes:
1227:    This counter is reset to zero for each successive call to TaoSolve()

1229:    Level: intermediate

1231: .seealso: `Tao`, `TaoGetKSP()`
1232: @*/
1233: PetscErrorCode TaoGetLinearSolveIterations(Tao tao, PetscInt *lits)
1234: {
1237:   *lits = tao->ksp_tot_its;
1238:   return 0;
1239: }

1241: /*@
1242:   TaoGetLineSearch - Gets the line search used by the optimization solver.
1243:   Application writers should use `TaoGetLineSearch()` if they need direct access
1244:   to the TaoLineSearch object.

1246:   Not Collective

1248:    Input Parameters:
1249: .  tao - the Tao solver

1251:    Output Parameters:
1252: .  ls - the line search used in the optimization solver

1254:    Level: intermediate

1256: @*/
1257: PetscErrorCode TaoGetLineSearch(Tao tao, TaoLineSearch *ls)
1258: {
1261:   *ls = tao->linesearch;
1262:   return 0;
1263: }

1265: /*@
1266:   TaoAddLineSearchCounts - Adds the number of function evaluations spent
1267:   in the line search to the running total.

1269:    Input Parameters:
1270: +  tao - the Tao solver
1271: -  ls - the line search used in the optimization solver

1273:    Level: developer

1275: .seealso: `TaoGetLineSearch()`, `TaoLineSearchApply()`
1276: @*/
1277: PetscErrorCode TaoAddLineSearchCounts(Tao tao)
1278: {
1279:   PetscBool flg;
1280:   PetscInt  nfeval, ngeval, nfgeval;

1283:   if (tao->linesearch) {
1284:     TaoLineSearchIsUsingTaoRoutines(tao->linesearch, &flg);
1285:     if (!flg) {
1286:       TaoLineSearchGetNumberFunctionEvaluations(tao->linesearch, &nfeval, &ngeval, &nfgeval);
1287:       tao->nfuncs += nfeval;
1288:       tao->ngrads += ngeval;
1289:       tao->nfuncgrads += nfgeval;
1290:     }
1291:   }
1292:   return 0;
1293: }

1295: /*@
1296:   TaoGetSolution - Returns the vector with the current Tao solution

1298:   Not Collective

1300:   Input Parameter:
1301: . tao - the Tao context

1303:   Output Parameter:
1304: . X - the current solution

1306:   Level: intermediate

1308:   Note:
1309:   The returned vector will be the same object that was passed into `TaoSetSolution()`

1311: .seealso: `Tao`, `TaoSetSolution()`, `TaoSolve()`
1312: @*/
1313: PetscErrorCode TaoGetSolution(Tao tao, Vec *X)
1314: {
1317:   *X = tao->solution;
1318:   return 0;
1319: }

1321: /*@
1322:    TaoResetStatistics - Initialize the statistics used by Tao for all of the solvers.
1323:    These statistics include the iteration number, residual norms, and convergence status.
1324:    This routine gets called before solving each optimization problem.

1326:    Collective on tao

1328:    Input Parameters:
1329: .  solver - the Tao context

1331:    Level: developer

1333: .seealso: `Tao`, `TaoCreate()`, `TaoSolve()`
1334: @*/
1335: PetscErrorCode TaoResetStatistics(Tao tao)
1336: {
1338:   tao->niter        = 0;
1339:   tao->nfuncs       = 0;
1340:   tao->nfuncgrads   = 0;
1341:   tao->ngrads       = 0;
1342:   tao->nhess        = 0;
1343:   tao->njac         = 0;
1344:   tao->nconstraints = 0;
1345:   tao->ksp_its      = 0;
1346:   tao->ksp_tot_its  = 0;
1347:   tao->reason       = TAO_CONTINUE_ITERATING;
1348:   tao->residual     = 0.0;
1349:   tao->cnorm        = 0.0;
1350:   tao->step         = 0.0;
1351:   tao->lsflag       = PETSC_FALSE;
1352:   if (tao->hist_reset) tao->hist_len = 0;
1353:   return 0;
1354: }

1356: /*@C
1357:   TaoSetUpdate - Sets the general-purpose update function called
1358:   at the beginning of every iteration of the optimization algorithm. Specifically
1359:   it is called at the top of every iteration, after the new solution and the gradient
1360:   is determined, but before the Hessian is computed (if applicable).

1362:   Logically Collective on tao

1364:   Input Parameters:
1365: + tao - The tao solver context
1366: - func - The function

1368:   Calling sequence of func:
1369: $ func (Tao tao, PetscInt step);

1371: . step - The current step of the iteration

1373:   Level: advanced

1375: .seealso `Tao`, `TaoSolve()`
1376: @*/
1377: PetscErrorCode TaoSetUpdate(Tao tao, PetscErrorCode (*func)(Tao, PetscInt, void *), void *ctx)
1378: {
1380:   tao->ops->update = func;
1381:   tao->user_update = ctx;
1382:   return 0;
1383: }

1385: /*@C
1386:   TaoSetConvergenceTest - Sets the function that is to be used to test
1387:   for convergence o fthe iterative minimization solution.  The new convergence
1388:   testing routine will replace Tao's default convergence test.

1390:   Logically Collective on tao

1392:   Input Parameters:
1393: + tao - the Tao object
1394: . conv - the routine to test for convergence
1395: - ctx - [optional] context for private data for the convergence routine
1396:         (may be NULL)

1398:   Calling sequence of conv:
1399: $   PetscErrorCode conv(Tao tao, void *ctx)

1401: + tao - the Tao object
1402: - ctx - [optional] convergence context

1404:   Note:
1405:   The new convergence testing routine should call `TaoSetConvergedReason()`.

1407:   Level: advanced

1409: .seealso: `Tao`, `TaoSolve()`, `TaoSetConvergedReason()`, `TaoGetSolutionStatus()`, `TaoGetTolerances()`, `TaoSetMonitor`

1411: @*/
1412: PetscErrorCode TaoSetConvergenceTest(Tao tao, PetscErrorCode (*conv)(Tao, void *), void *ctx)
1413: {
1415:   tao->ops->convergencetest = conv;
1416:   tao->cnvP                 = ctx;
1417:   return 0;
1418: }

1420: /*@C
1421:    TaoSetMonitor - Sets an additional function that is to be used at every
1422:    iteration of the solver to display the iteration's
1423:    progress.

1425:    Logically Collective on tao

1427:    Input Parameters:
1428: +  tao - the Tao solver context
1429: .  mymonitor - monitoring routine
1430: -  mctx - [optional] user-defined context for private data for the
1431:           monitor routine (may be NULL)

1433:    Calling sequence of mymonitor:
1434: .vb
1435:      PetscErrorCode mymonitor(Tao tao,void *mctx)
1436: .ve

1438: +    tao - the Tao solver context
1439: -    mctx - [optional] monitoring context

1441:    Options Database Keys:
1442: +    -tao_monitor        - sets the default monitor `TaoMonitorDefault()`
1443: .    -tao_smonitor       - sets short monitor
1444: .    -tao_cmonitor       - same as smonitor plus constraint norm
1445: .    -tao_view_solution   - view solution at each iteration
1446: .    -tao_view_gradient   - view gradient at each iteration
1447: .    -tao_view_ls_residual - view least-squares residual vector at each iteration
1448: -    -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.

1450:    Notes:
1451:    Several different monitoring routines may be set by calling
1452:    `TaoSetMonitor()` multiple times; all will be called in the
1453:    order in which they were set.

1455:    Fortran Note:
1456:     Only one monitor function may be set

1458:    Level: intermediate

1460: .seealso: `Tao`, `TaoSolve()`, `TaoMonitorDefault()`, `TaoCancelMonitors()`, `TaoSetDestroyRoutine()`, `TaoView()`
1461: @*/
1462: PetscErrorCode TaoSetMonitor(Tao tao, PetscErrorCode (*func)(Tao, void *), void *ctx, PetscErrorCode (*dest)(void **))
1463: {
1464:   PetscInt  i;
1465:   PetscBool identical;


1470:   for (i = 0; i < tao->numbermonitors; i++) {
1471:     PetscMonitorCompare((PetscErrorCode(*)(void))func, ctx, dest, (PetscErrorCode(*)(void))tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i], &identical);
1472:     if (identical) return 0;
1473:   }
1474:   tao->monitor[tao->numbermonitors]        = func;
1475:   tao->monitorcontext[tao->numbermonitors] = (void *)ctx;
1476:   tao->monitordestroy[tao->numbermonitors] = dest;
1477:   ++tao->numbermonitors;
1478:   return 0;
1479: }

1481: /*@
1482:    TaoCancelMonitors - Clears all the monitor functions for a Tao object.

1484:    Logically Collective on tao

1486:    Input Parameters:
1487: .  tao - the Tao solver context

1489:    Options Database:
1490: .  -tao_cancelmonitors - cancels all monitors that have been hardwired
1491:     into a code by calls to `TaoSetMonitor()`, but does not cancel those
1492:     set via the options database

1494:    Notes:
1495:    There is no way to clear one specific monitor from a Tao object.

1497:    Level: advanced

1499: .seealso: `Tao`, `TaoMonitorDefault()`, `TaoSetMonitor()`
1500: @*/
1501: PetscErrorCode TaoCancelMonitors(Tao tao)
1502: {
1503:   PetscInt i;

1506:   for (i = 0; i < tao->numbermonitors; i++) {
1507:     if (tao->monitordestroy[i]) (*tao->monitordestroy[i])(&tao->monitorcontext[i]);
1508:   }
1509:   tao->numbermonitors = 0;
1510:   return 0;
1511: }

1513: /*@
1514:    TaoMonitorDefault - Default routine for monitoring progress of the
1515:    Tao solvers (default).  This monitor prints the function value and gradient
1516:    norm at each iteration.  It can be turned on from the command line using the
1517:    -tao_monitor option

1519:    Collective on tao

1521:    Input Parameters:
1522: +  tao - the Tao context
1523: -  ctx - `PetscViewer` context or NULL

1525:    Options Database Keys:
1526: .  -tao_monitor - turn on default monitoring

1528:    Level: advanced

1530: .seealso: `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1531: @*/
1532: PetscErrorCode TaoMonitorDefault(Tao tao, void *ctx)
1533: {
1534:   PetscInt    its, tabs;
1535:   PetscReal   fct, gnorm;
1536:   PetscViewer viewer = (PetscViewer)ctx;

1540:   its   = tao->niter;
1541:   fct   = tao->fc;
1542:   gnorm = tao->residual;
1543:   PetscViewerASCIIGetTab(viewer, &tabs);
1544:   PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);
1545:   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1546:     PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix);
1547:     tao->header_printed = PETSC_TRUE;
1548:   }
1549:   PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its);
1550:   PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct);
1551:   if (gnorm >= PETSC_INFINITY) {
1552:     PetscViewerASCIIPrintf(viewer, "  Residual: Inf \n");
1553:   } else {
1554:     PetscViewerASCIIPrintf(viewer, "  Residual: %g \n", (double)gnorm);
1555:   }
1556:   PetscViewerASCIISetTab(viewer, tabs);
1557:   return 0;
1558: }

1560: /*@
1561:    TaoDefaultGMonitor - Default routine for monitoring progress of the
1562:    Tao solvers (default) with extra detail on the globalization method.
1563:    This monitor prints the function value and gradient norm at each
1564:    iteration, as well as the step size and trust radius. Note that the
1565:    step size and trust radius may be the same for some algorithms.
1566:    It can be turned on from the command line using the
1567:    -tao_gmonitor option

1569:    Collective on tao

1571:    Input Parameters:
1572: +  tao - the Tao context
1573: -  ctx - `PetscViewer` context or NULL

1575:    Options Database Keys:
1576: .  -tao_gmonitor - turn on monitoring with globalization information

1578:    Level: advanced

1580: .seealso: `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1581: @*/
1582: PetscErrorCode TaoDefaultGMonitor(Tao tao, void *ctx)
1583: {
1584:   PetscInt    its, tabs;
1585:   PetscReal   fct, gnorm, stp, tr;
1586:   PetscViewer viewer = (PetscViewer)ctx;

1590:   its   = tao->niter;
1591:   fct   = tao->fc;
1592:   gnorm = tao->residual;
1593:   stp   = tao->step;
1594:   tr    = tao->trust;
1595:   PetscViewerASCIIGetTab(viewer, &tabs);
1596:   PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);
1597:   if (its == 0 && ((PetscObject)tao)->prefix && !tao->header_printed) {
1598:     PetscViewerASCIIPrintf(viewer, "  Iteration information for %s solve.\n", ((PetscObject)tao)->prefix);
1599:     tao->header_printed = PETSC_TRUE;
1600:   }
1601:   PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " TAO,", its);
1602:   PetscViewerASCIIPrintf(viewer, "  Function value: %g,", (double)fct);
1603:   if (gnorm >= PETSC_INFINITY) {
1604:     PetscViewerASCIIPrintf(viewer, "  Residual: Inf,");
1605:   } else {
1606:     PetscViewerASCIIPrintf(viewer, "  Residual: %g,", (double)gnorm);
1607:   }
1608:   PetscViewerASCIIPrintf(viewer, "  Step: %g,  Trust: %g\n", (double)stp, (double)tr);
1609:   PetscViewerASCIISetTab(viewer, tabs);
1610:   return 0;
1611: }

1613: /*@
1614:    TaoDefaultSMonitor - Default routine for monitoring progress of the
1615:    solver. Same as `TaoMonitorDefault()` except
1616:    it prints fewer digits of the residual as the residual gets smaller.
1617:    This is because the later digits are meaningless and are often
1618:    different on different machines; by using this routine different
1619:    machines will usually generate the same output. It can be turned on
1620:    by using the -tao_smonitor option

1622:    Collective on tao

1624:    Input Parameters:
1625: +  tao - the Tao context
1626: -  ctx - PetscViewer context of type ASCII

1628:    Options Database Keys:
1629: .  -tao_smonitor - turn on default short monitoring

1631:    Level: advanced

1633: .seealso: `TaoMonitorDefault()`, `TaoSetMonitor()`
1634: @*/
1635: PetscErrorCode TaoDefaultSMonitor(Tao tao, void *ctx)
1636: {
1637:   PetscInt    its, tabs;
1638:   PetscReal   fct, gnorm;
1639:   PetscViewer viewer = (PetscViewer)ctx;

1643:   its   = tao->niter;
1644:   fct   = tao->fc;
1645:   gnorm = tao->residual;
1646:   PetscViewerASCIIGetTab(viewer, &tabs);
1647:   PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);
1648:   PetscViewerASCIIPrintf(viewer, "iter = %3" PetscInt_FMT ",", its);
1649:   PetscViewerASCIIPrintf(viewer, " Function value %g,", (double)fct);
1650:   if (gnorm >= PETSC_INFINITY) {
1651:     PetscViewerASCIIPrintf(viewer, " Residual: Inf \n");
1652:   } else if (gnorm > 1.e-6) {
1653:     PetscViewerASCIIPrintf(viewer, " Residual: %g \n", (double)gnorm);
1654:   } else if (gnorm > 1.e-11) {
1655:     PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-6 \n");
1656:   } else {
1657:     PetscViewerASCIIPrintf(viewer, " Residual: < 1.0e-11 \n");
1658:   }
1659:   PetscViewerASCIISetTab(viewer, tabs);
1660:   return 0;
1661: }

1663: /*@
1664:    TaoDefaultCMonitor - same as `TaoMonitorDefault()` except
1665:    it prints the norm of the constraints function. It can be turned on
1666:    from the command line using the -tao_cmonitor option

1668:    Collective on tao

1670:    Input Parameters:
1671: +  tao - the Tao context
1672: -  ctx - `PetscViewer` context or NULL

1674:    Options Database Keys:
1675: .  -tao_cmonitor - monitor the constraints

1677:    Level: advanced

1679: .seealso: `TaoMonitorDefault()`, `TaoSetMonitor()`
1680: @*/
1681: PetscErrorCode TaoDefaultCMonitor(Tao tao, void *ctx)
1682: {
1683:   PetscInt    its, tabs;
1684:   PetscReal   fct, gnorm;
1685:   PetscViewer viewer = (PetscViewer)ctx;

1689:   its   = tao->niter;
1690:   fct   = tao->fc;
1691:   gnorm = tao->residual;
1692:   PetscViewerASCIIGetTab(viewer, &tabs);
1693:   PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);
1694:   PetscViewerASCIIPrintf(viewer, "iter = %" PetscInt_FMT ",", its);
1695:   PetscViewerASCIIPrintf(viewer, " Function value: %g,", (double)fct);
1696:   PetscViewerASCIIPrintf(viewer, "  Residual: %g ", (double)gnorm);
1697:   PetscViewerASCIIPrintf(viewer, "  Constraint: %g \n", (double)tao->cnorm);
1698:   PetscViewerASCIISetTab(viewer, tabs);
1699:   return 0;
1700: }

1702: /*@C
1703:    TaoSolutionMonitor - Views the solution at each iteration
1704:    It can be turned on from the command line using the
1705:    -tao_view_solution option

1707:    Collective on tao

1709:    Input Parameters:
1710: +  tao - the Tao context
1711: -  ctx - `PetscViewer` context or NULL

1713:    Options Database Keys:
1714: .  -tao_view_solution - view the solution

1716:    Level: advanced

1718: .seealso: `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1719: @*/
1720: PetscErrorCode TaoSolutionMonitor(Tao tao, void *ctx)
1721: {
1722:   PetscViewer viewer = (PetscViewer)ctx;

1726:   VecView(tao->solution, viewer);
1727:   return 0;
1728: }

1730: /*@C
1731:    TaoGradientMonitor - Views the gradient at each iteration
1732:    It can be turned on from the command line using the
1733:    -tao_view_gradient option

1735:    Collective on tao

1737:    Input Parameters:
1738: +  tao - the Tao context
1739: -  ctx - `PetscViewer` context or NULL

1741:    Options Database Keys:
1742: .  -tao_view_gradient - view the gradient at each iteration

1744:    Level: advanced

1746: .seealso: `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1747: @*/
1748: PetscErrorCode TaoGradientMonitor(Tao tao, void *ctx)
1749: {
1750:   PetscViewer viewer = (PetscViewer)ctx;

1754:   VecView(tao->gradient, viewer);
1755:   return 0;
1756: }

1758: /*@C
1759:    TaoStepDirectionMonitor - Views the step-direction at each iteration

1761:    Collective on tao

1763:    Input Parameters:
1764: +  tao - the Tao context
1765: -  ctx - `PetscViewer` context or NULL

1767:    Options Database Keys:
1768: .  -tao_view_gradient - view the gradient at each iteration

1770:    Level: advanced

1772: .seealso: `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1773: @*/
1774: PetscErrorCode TaoStepDirectionMonitor(Tao tao, void *ctx)
1775: {
1776:   PetscViewer viewer = (PetscViewer)ctx;

1780:   VecView(tao->stepdirection, viewer);
1781:   return 0;
1782: }

1784: /*@C
1785:    TaoDrawSolutionMonitor - Plots the solution at each iteration
1786:    It can be turned on from the command line using the
1787:    -tao_draw_solution option

1789:    Collective on tao

1791:    Input Parameters:
1792: +  tao - the Tao context
1793: -  ctx - `TaoMonitorDraw` context

1795:    Options Database Keys:
1796: .  -tao_draw_solution - draw the solution at each iteration

1798:    Level: advanced

1800: .seealso: `TaoSolutionMonitor()`, `TaoSetMonitor()`, `TaoDrawGradientMonitor`, `TaoMonitorDraw`
1801: @*/
1802: PetscErrorCode TaoDrawSolutionMonitor(Tao tao, void *ctx)
1803: {
1804:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

1807:   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) return 0;
1808:   VecView(tao->solution, ictx->viewer);
1809:   return 0;
1810: }

1812: /*@C
1813:    TaoDrawGradientMonitor - Plots the gradient at each iteration
1814:    It can be turned on from the command line using the
1815:    -tao_draw_gradient option

1817:    Collective on tao

1819:    Input Parameters:
1820: +  tao - the Tao context
1821: -  ctx - `PetscViewer` context

1823:    Options Database Keys:
1824: .  -tao_draw_gradient - draw the gradient at each iteration

1826:    Level: advanced

1828: .seealso: `TaoGradientMonitor()`, `TaoSetMonitor()`, `TaoDrawSolutionMonitor`
1829: @*/
1830: PetscErrorCode TaoDrawGradientMonitor(Tao tao, void *ctx)
1831: {
1832:   TaoMonitorDrawCtx ictx = (TaoMonitorDrawCtx)ctx;

1835:   if (!(((ictx->howoften > 0) && (!(tao->niter % ictx->howoften))) || ((ictx->howoften == -1) && tao->reason))) return 0;
1836:   VecView(tao->gradient, ictx->viewer);
1837:   return 0;
1838: }

1840: /*@C
1841:    TaoDrawStepMonitor - Plots the step direction at each iteration

1843:    Collective on tao

1845:    Input Parameters:
1846: +  tao - the Tao context
1847: -  ctx - PetscViewer context

1849:    Options Database Keys:
1850: .  -tao_draw_step - draw the step direction at each iteration

1852:    Level: advanced

1854: .seealso: `TaoSetMonitor()`, `TaoDrawSolutionMonitor`
1855: @*/
1856: PetscErrorCode TaoDrawStepMonitor(Tao tao, void *ctx)
1857: {
1858:   PetscViewer viewer = (PetscViewer)ctx;

1862:   VecView(tao->stepdirection, viewer);
1863:   return 0;
1864: }

1866: /*@C
1867:    TaoResidualMonitor - Views the least-squares residual at each iteration

1869:    Collective on tao

1871:    Input Parameters:
1872: +  tao - the Tao context
1873: -  ctx - `PetscViewer` context or NULL

1875:    Options Database Keys:
1876: .  -tao_view_ls_residual - view the least-squares residual at each iteration

1878:    Level: advanced

1880: .seealso: `TaoDefaultSMonitor()`, `TaoSetMonitor()`
1881: @*/
1882: PetscErrorCode TaoResidualMonitor(Tao tao, void *ctx)
1883: {
1884:   PetscViewer viewer = (PetscViewer)ctx;

1888:   VecView(tao->ls_res, viewer);
1889:   return 0;
1890: }

1892: /*@
1893:    TaoDefaultConvergenceTest - Determines whether the solver should continue iterating
1894:    or terminate.

1896:    Collective on tao

1898:    Input Parameters:
1899: +  tao - the Tao context
1900: -  dummy - unused dummy context

1902:    Output Parameter:
1903: .  reason - for terminating

1905:    Notes:
1906:    This routine checks the residual in the optimality conditions, the
1907:    relative residual in the optimity conditions, the number of function
1908:    evaluations, and the function value to test convergence.  Some
1909:    solvers may use different convergence routines.

1911:    Level: developer

1913: .seealso: `TaoSetTolerances()`, `TaoGetConvergedReason()`, `TaoSetConvergedReason()`
1914: @*/

1916: PetscErrorCode TaoDefaultConvergenceTest(Tao tao, void *dummy)
1917: {
1918:   PetscInt           niter = tao->niter, nfuncs = PetscMax(tao->nfuncs, tao->nfuncgrads);
1919:   PetscInt           max_funcs = tao->max_funcs;
1920:   PetscReal          gnorm = tao->residual, gnorm0 = tao->gnorm0;
1921:   PetscReal          f = tao->fc, steptol = tao->steptol, trradius = tao->step;
1922:   PetscReal          gatol = tao->gatol, grtol = tao->grtol, gttol = tao->gttol;
1923:   PetscReal          catol = tao->catol, crtol = tao->crtol;
1924:   PetscReal          fmin = tao->fmin, cnorm = tao->cnorm;
1925:   TaoConvergedReason reason = tao->reason;

1928:   if (reason != TAO_CONTINUE_ITERATING) return 0;

1930:   if (PetscIsInfOrNanReal(f)) {
1931:     PetscInfo(tao, "Failed to converged, function value is Inf or NaN\n");
1932:     reason = TAO_DIVERGED_NAN;
1933:   } else if (f <= fmin && cnorm <= catol) {
1934:     PetscInfo(tao, "Converged due to function value %g < minimum function value %g\n", (double)f, (double)fmin);
1935:     reason = TAO_CONVERGED_MINF;
1936:   } else if (gnorm <= gatol && cnorm <= catol) {
1937:     PetscInfo(tao, "Converged due to residual norm ||g(X)||=%g < %g\n", (double)gnorm, (double)gatol);
1938:     reason = TAO_CONVERGED_GATOL;
1939:   } else if (f != 0 && PetscAbsReal(gnorm / f) <= grtol && cnorm <= crtol) {
1940:     PetscInfo(tao, "Converged due to residual ||g(X)||/|f(X)| =%g < %g\n", (double)(gnorm / f), (double)grtol);
1941:     reason = TAO_CONVERGED_GRTOL;
1942:   } else if (gnorm0 != 0 && ((gttol == 0 && gnorm == 0) || gnorm / gnorm0 < gttol) && cnorm <= crtol) {
1943:     PetscInfo(tao, "Converged due to relative residual norm ||g(X)||/||g(X0)|| = %g < %g\n", (double)(gnorm / gnorm0), (double)gttol);
1944:     reason = TAO_CONVERGED_GTTOL;
1945:   } else if (max_funcs >= 0 && nfuncs > max_funcs) {
1946:     PetscInfo(tao, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", nfuncs, max_funcs);
1947:     reason = TAO_DIVERGED_MAXFCN;
1948:   } else if (tao->lsflag != 0) {
1949:     PetscInfo(tao, "Tao Line Search failure.\n");
1950:     reason = TAO_DIVERGED_LS_FAILURE;
1951:   } else if (trradius < steptol && niter > 0) {
1952:     PetscInfo(tao, "Trust region/step size too small: %g < %g\n", (double)trradius, (double)steptol);
1953:     reason = TAO_CONVERGED_STEPTOL;
1954:   } else if (niter >= tao->max_it) {
1955:     PetscInfo(tao, "Exceeded maximum number of iterations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", niter, tao->max_it);
1956:     reason = TAO_DIVERGED_MAXITS;
1957:   } else {
1958:     reason = TAO_CONTINUE_ITERATING;
1959:   }
1960:   tao->reason = reason;
1961:   return 0;
1962: }

1964: /*@C
1965:    TaoSetOptionsPrefix - Sets the prefix used for searching for all
1966:    Tao options in the database.

1968:    Logically Collective on tao

1970:    Input Parameters:
1971: +  tao - the Tao context
1972: -  prefix - the prefix string to prepend to all Tao option requests

1974:    Notes:
1975:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1976:    The first character of all runtime options is AUTOMATICALLY the hyphen.

1978:    For example, to distinguish between the runtime options for two
1979:    different Tao solvers, one could call
1980: .vb
1981:       TaoSetOptionsPrefix(tao1,"sys1_")
1982:       TaoSetOptionsPrefix(tao2,"sys2_")
1983: .ve

1985:    This would enable use of different options for each system, such as
1986: .vb
1987:       -sys1_tao_method blmvm -sys1_tao_grtol 1.e-3
1988:       -sys2_tao_method lmvm  -sys2_tao_grtol 1.e-4
1989: .ve

1991:    Level: advanced

1993: .seealso: `TaoSetFromOptions()`, `TaoAppendOptionsPrefix()`, `TaoGetOptionsPrefix()`
1994: @*/

1996: PetscErrorCode TaoSetOptionsPrefix(Tao tao, const char p[])
1997: {
1999:   PetscObjectSetOptionsPrefix((PetscObject)tao, p);
2000:   if (tao->linesearch) TaoLineSearchSetOptionsPrefix(tao->linesearch, p);
2001:   if (tao->ksp) KSPSetOptionsPrefix(tao->ksp, p);
2002:   return 0;
2003: }

2005: /*@C
2006:    TaoAppendOptionsPrefix - Appends to the prefix used for searching for all
2007:    Tao options in the database.

2009:    Logically Collective on tao

2011:    Input Parameters:
2012: +  tao - the Tao solver context
2013: -  prefix - the prefix string to prepend to all Tao option requests

2015:    Note:
2016:    A hyphen (-) must NOT be given at the beginning of the prefix name.
2017:    The first character of all runtime options is automatically the hyphen.

2019:    Level: advanced

2021: .seealso: `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoGetOptionsPrefix()`
2022: @*/
2023: PetscErrorCode TaoAppendOptionsPrefix(Tao tao, const char p[])
2024: {
2026:   PetscObjectAppendOptionsPrefix((PetscObject)tao, p);
2027:   if (tao->linesearch) PetscObjectAppendOptionsPrefix((PetscObject)tao->linesearch, p);
2028:   if (tao->ksp) KSPAppendOptionsPrefix(tao->ksp, p);
2029:   return 0;
2030: }

2032: /*@C
2033:   TaoGetOptionsPrefix - Gets the prefix used for searching for all
2034:   Tao options in the database

2036:   Not Collective

2038:   Input Parameters:
2039: . tao - the Tao context

2041:   Output Parameters:
2042: . prefix - pointer to the prefix string used is returned

2044:   Fortran Note:
2045:     On the fortran side, the user should pass in a string 'prefix' of
2046:   sufficient length to hold the prefix.

2048:   Level: advanced

2050: .seealso: `TaoSetFromOptions()`, `TaoSetOptionsPrefix()`, `TaoAppendOptionsPrefix()`
2051: @*/
2052: PetscErrorCode TaoGetOptionsPrefix(Tao tao, const char *p[])
2053: {
2055:   PetscObjectGetOptionsPrefix((PetscObject)tao, p);
2056:   return 0;
2057: }

2059: /*@C
2060:    TaoSetType - Sets the method for the unconstrained minimization solver.

2062:    Collective on tao

2064:    Input Parameters:
2065: +  solver - the Tao solver context
2066: -  type - a known method

2068:    Options Database Key:
2069: .  -tao_type <type> - Sets the method; use -help for a list
2070:    of available methods (for instance, "-tao_type lmvm" or "-tao_type tron")

2072:    Available methods include:
2073: +    `TAONLS` - nls Newton's method with line search for unconstrained minimization
2074: .    `TAONTR` - ntr Newton's method with trust region for unconstrained minimization
2075: .    `TAONTL` - ntl Newton's method with trust region, line search for unconstrained minimization
2076: .    `TAOLMVM` - lmvm Limited memory variable metric method for unconstrained minimization
2077: .    `TAOCG` - cg Nonlinear conjugate gradient method for unconstrained minimization
2078: .    `TAONM` - nm Nelder-Mead algorithm for derivate-free unconstrained minimization
2079: .    `TAOTRON` - tron Newton Trust Region method for bound constrained minimization
2080: .    `TAOGPCG` - gpcg Newton Trust Region method for quadratic bound constrained minimization
2081: .    `TAOBLMVM` - blmvm Limited memory variable metric method for bound constrained minimization
2082: .    `TAOLCL` - lcl Linearly constrained Lagrangian method for pde-constrained minimization
2083: -    `TAOPOUNDERS` - pounders Model-based algorithm for nonlinear least squares

2085:   Level: intermediate

2087: .seealso: `Tao`, `TaoCreate()`, `TaoGetType()`, `TaoType`

2089: @*/
2090: PetscErrorCode TaoSetType(Tao tao, TaoType type)
2091: {
2092:   PetscErrorCode (*create_xxx)(Tao);
2093:   PetscBool issame;


2097:   PetscObjectTypeCompare((PetscObject)tao, type, &issame);
2098:   if (issame) return 0;

2100:   PetscFunctionListFind(TaoList, type, (void (**)(void)) & create_xxx);

2103:   /* Destroy the existing solver information */
2104:   PetscTryTypeMethod(tao, destroy);
2105:   KSPDestroy(&tao->ksp);
2106:   TaoLineSearchDestroy(&tao->linesearch);
2107:   tao->ops->setup          = NULL;
2108:   tao->ops->solve          = NULL;
2109:   tao->ops->view           = NULL;
2110:   tao->ops->setfromoptions = NULL;
2111:   tao->ops->destroy        = NULL;

2113:   tao->setupcalled = PETSC_FALSE;

2115:   (*create_xxx)(tao);
2116:   PetscObjectChangeTypeName((PetscObject)tao, type);
2117:   return 0;
2118: }

2120: /*MC
2121:    TaoRegister - Adds a method to the Tao package for unconstrained minimization.

2123:    Synopsis:
2124:    TaoRegister(char *name_solver,char *path,char *name_Create,PetscErrorCode (*routine_Create)(Tao))

2126:    Not collective

2128:    Input Parameters:
2129: +  sname - name of a new user-defined solver
2130: -  func - routine to Create method context

2132:    Note:
2133:    `TaoRegister()` may be called multiple times to add several user-defined solvers.

2135:    Sample usage:
2136: .vb
2137:    TaoRegister("my_solver",MySolverCreate);
2138: .ve

2140:    Then, your solver can be chosen with the procedural interface via
2141: $     TaoSetType(tao,"my_solver")
2142:    or at runtime via the option
2143: $     -tao_type my_solver

2145:    Level: advanced

2147: .seealso: `Tao`, `TaoSetType()`, `TaoRegisterAll()`, `TaoRegisterDestroy()`
2148: M*/
2149: PetscErrorCode TaoRegister(const char sname[], PetscErrorCode (*func)(Tao))
2150: {
2151:   TaoInitializePackage();
2152:   PetscFunctionListAdd(&TaoList, sname, (void (*)(void))func);
2153:   return 0;
2154: }

2156: /*@C
2157:    TaoRegisterDestroy - Frees the list of minimization solvers that were
2158:    registered by `TaoRegisterDynamic()`.

2160:    Not Collective

2162:    Level: advanced

2164: .seealso: `TaoRegisterAll()`, `TaoRegister()`
2165: @*/
2166: PetscErrorCode TaoRegisterDestroy(void)
2167: {
2168:   PetscFunctionListDestroy(&TaoList);
2169:   TaoRegisterAllCalled = PETSC_FALSE;
2170:   return 0;
2171: }

2173: /*@
2174:    TaoGetIterationNumber - Gets the number of Tao iterations completed
2175:    at this time.

2177:    Not Collective

2179:    Input Parameter:
2180: .  tao - Tao context

2182:    Output Parameter:
2183: .  iter - iteration number

2185:    Notes:
2186:    For example, during the computation of iteration 2 this would return 1.

2188:    Level: intermediate

2190: .seealso: `TaoGetLinearSolveIterations()`, `TaoGetResidualNorm()`, `TaoGetObjective()`
2191: @*/
2192: PetscErrorCode TaoGetIterationNumber(Tao tao, PetscInt *iter)
2193: {
2196:   *iter = tao->niter;
2197:   return 0;
2198: }

2200: /*@
2201:    TaoGetResidualNorm - Gets the current value of the norm of the residual
2202:    at this time.

2204:    Not Collective

2206:    Input Parameter:
2207: .  tao - Tao context

2209:    Output Parameter:
2210: .  value - the current value

2212:    Level: intermediate

2214:    Developer Note: 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: `TaoGetLinearSolveIterations()`, `TaoGetIterationNumber()`, `TaoGetObjective()`
2218: @*/
2219: PetscErrorCode TaoGetResidualNorm(Tao tao, PetscReal *value)
2220: {
2223:   *value = tao->residual;
2224:   return 0;
2225: }

2227: /*@
2228:    TaoSetIterationNumber - Sets the current iteration number.

2230:    Logically Collective on tao

2232:    Input Parameters:
2233: +  tao - Tao context
2234: -  iter - iteration number

2236:    Level: developer

2238: .seealso: `TaoGetLinearSolveIterations()`
2239: @*/
2240: PetscErrorCode TaoSetIterationNumber(Tao tao, PetscInt iter)
2241: {
2244:   PetscObjectSAWsTakeAccess((PetscObject)tao);
2245:   tao->niter = iter;
2246:   PetscObjectSAWsGrantAccess((PetscObject)tao);
2247:   return 0;
2248: }

2250: /*@
2251:    TaoGetTotalIterationNumber - Gets the total number of Tao iterations
2252:    completed. This number keeps accumulating if multiple solves
2253:    are called with the Tao object.

2255:    Not Collective

2257:    Input Parameter:
2258: .  tao - Tao context

2260:    Output Parameter:
2261: .  iter - iteration number

2263:    Notes:
2264:    The total iteration count is updated after each solve, if there is a current
2265:    TaoSolve() in progress then those iterations are not yet counted.

2267:    Level: intermediate

2269: .seealso: `TaoGetLinearSolveIterations()`
2270: @*/
2271: PetscErrorCode TaoGetTotalIterationNumber(Tao tao, PetscInt *iter)
2272: {
2275:   *iter = tao->ntotalits;
2276:   return 0;
2277: }

2279: /*@
2280:    TaoSetTotalIterationNumber - Sets the current total iteration number.

2282:    Logically Collective on tao

2284:    Input Parameters:
2285: +  tao - Tao context
2286: -  iter - iteration number

2288:    Level: developer

2290: .seealso: `TaoGetLinearSolveIterations()`
2291: @*/
2292: PetscErrorCode TaoSetTotalIterationNumber(Tao tao, PetscInt iter)
2293: {
2296:   PetscObjectSAWsTakeAccess((PetscObject)tao);
2297:   tao->ntotalits = iter;
2298:   PetscObjectSAWsGrantAccess((PetscObject)tao);
2299:   return 0;
2300: }

2302: /*@
2303:   TaoSetConvergedReason - Sets the termination flag on a Tao object

2305:   Logically Collective on tao

2307:   Input Parameters:
2308: + tao - the Tao context
2309: - reason - one of
2310: $     `TAO_CONVERGED_ATOL` (2),
2311: $     `TAO_CONVERGED_RTOL` (3),
2312: $     `TAO_CONVERGED_STEPTOL` (4),
2313: $     `TAO_CONVERGED_MINF` (5),
2314: $     `TAO_CONVERGED_USER` (6),
2315: $     `TAO_DIVERGED_MAXITS` (-2),
2316: $     `TAO_DIVERGED_NAN` (-4),
2317: $     `TAO_DIVERGED_MAXFCN` (-5),
2318: $     `TAO_DIVERGED_LS_FAILURE` (-6),
2319: $     `TAO_DIVERGED_TR_REDUCTION` (-7),
2320: $     `TAO_DIVERGED_USER` (-8),
2321: $     `TAO_CONTINUE_ITERATING` (0)

2323:    Level: intermediate

2325: @*/
2326: PetscErrorCode TaoSetConvergedReason(Tao tao, TaoConvergedReason reason)
2327: {
2330:   tao->reason = reason;
2331:   return 0;
2332: }

2334: /*@
2335:    TaoGetConvergedReason - Gets the reason the Tao iteration was stopped.

2337:    Not Collective

2339:    Input Parameter:
2340: .  tao - the Tao solver context

2342:    Output Parameter:
2343: .  reason - one of
2344: $  `TAO_CONVERGED_GATOL` (3)           ||g(X)|| < gatol
2345: $  `TAO_CONVERGED_GRTOL` (4)           ||g(X)|| / f(X)  < grtol
2346: $  `TAO_CONVERGED_GTTOL` (5)           ||g(X)|| / ||g(X0)|| < gttol
2347: $  `TAO_CONVERGED_STEPTOL` (6)         step size small
2348: $  `TAO_CONVERGED_MINF` (7)            F < F_min
2349: $  `TAO_CONVERGED_USER` (8)            User defined
2350: $  `TAO_DIVERGED_MAXITS` (-2)          its > maxits
2351: $  `TAO_DIVERGED_NAN` (-4)             Numerical problems
2352: $  `TAO_DIVERGED_MAXFCN` (-5)          fevals > max_funcsals
2353: $  `TAO_DIVERGED_LS_FAILURE` (-6)      line search failure
2354: $  `TAO_DIVERGED_TR_REDUCTION` (-7)    trust region failure
2355: $  `TAO_DIVERGED_USER` (-8)             (user defined)
2356: $  `TAO_CONTINUE_ITERATING` (0)

2358:    where
2359: +  X - current solution
2360: .  X0 - initial guess
2361: .  f(X) - current function value
2362: .  f(X*) - true solution (estimated)
2363: .  g(X) - current gradient
2364: .  its - current iterate number
2365: .  maxits - maximum number of iterates
2366: .  fevals - number of function evaluations
2367: -  max_funcsals - maximum number of function evaluations

2369:    Level: intermediate

2371: .seealso: `TaoSetConvergenceTest()`, `TaoSetTolerances()`

2373: @*/
2374: PetscErrorCode TaoGetConvergedReason(Tao tao, TaoConvergedReason *reason)
2375: {
2378:   *reason = tao->reason;
2379:   return 0;
2380: }

2382: /*@
2383:    TaoGetSolutionStatus - Get the current iterate, objective value,
2384:    residual, infeasibility, and termination

2386:    Not Collective

2388:    Input Parameter:
2389: .  tao - the Tao context

2391:    Output Parameters:
2392: +  iterate - the current iterate number (>=0)
2393: .  f - the current function value
2394: .  gnorm - the square of the gradient norm, duality gap, or other measure indicating distance from optimality.
2395: .  cnorm - the infeasibility of the current solution with regard to the constraints.
2396: .  xdiff - the step length or trust region radius of the most recent iterate.
2397: -  reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`

2399:    Level: intermediate

2401:    Notes:
2402:    Tao returns the values set by the solvers in the routine `TaoMonitor()`.

2404:    If any of the output arguments are set to NULL, no corresponding value will be returned.

2406: .seealso: `TaoMonitor()`, `TaoGetConvergedReason()`
2407: @*/
2408: PetscErrorCode TaoGetSolutionStatus(Tao tao, PetscInt *its, PetscReal *f, PetscReal *gnorm, PetscReal *cnorm, PetscReal *xdiff, TaoConvergedReason *reason)
2409: {
2411:   if (its) *its = tao->niter;
2412:   if (f) *f = tao->fc;
2413:   if (gnorm) *gnorm = tao->residual;
2414:   if (cnorm) *cnorm = tao->cnorm;
2415:   if (reason) *reason = tao->reason;
2416:   if (xdiff) *xdiff = tao->step;
2417:   return 0;
2418: }

2420: /*@C
2421:    TaoGetType - Gets the current Tao algorithm.

2423:    Not Collective

2425:    Input Parameter:
2426: .  tao - the Tao solver context

2428:    Output Parameter:
2429: .  type - Tao method

2431:    Level: intermediate

2433: .seealso: `Tao`, `TaoType`, `TaoSetType()`
2434: @*/
2435: PetscErrorCode TaoGetType(Tao tao, TaoType *type)
2436: {
2439:   *type = ((PetscObject)tao)->type_name;
2440:   return 0;
2441: }

2443: /*@C
2444:   TaoMonitor - Monitor the solver and the current solution.  This
2445:   routine will record the iteration number and residual statistics,
2446:   call any monitors specified by the user, and calls the convergence-check routine.

2448:    Input Parameters:
2449: +  tao - the Tao context
2450: .  its - the current iterate number (>=0)
2451: .  f - the current objective function value
2452: .  res - the gradient norm, square root of the duality gap, or other measure indicating distince from optimality.  This measure will be recorded and
2453:           used for some termination tests.
2454: .  cnorm - the infeasibility of the current solution with regard to the constraints.
2455: -  steplength - multiple of the step direction added to the previous iterate.

2457:    Output Parameters:
2458: .  reason - The termination reason, which can equal `TAO_CONTINUE_ITERATING`

2460:    Options Database Key:
2461: .  -tao_monitor - Use the default monitor, which prints statistics to standard output

2463:    Level: developer

2465: .seealso `Tao`, `TaoGetConvergedReason()`, `TaoMonitorDefault()`, `TaoSetMonitor()`
2466: @*/
2467: PetscErrorCode TaoMonitor(Tao tao, PetscInt its, PetscReal f, PetscReal res, PetscReal cnorm, PetscReal steplength)
2468: {
2469:   PetscInt i;

2472:   tao->fc       = f;
2473:   tao->residual = res;
2474:   tao->cnorm    = cnorm;
2475:   tao->step     = steplength;
2476:   if (!its) {
2477:     tao->cnorm0 = cnorm;
2478:     tao->gnorm0 = res;
2479:   }
2481:   for (i = 0; i < tao->numbermonitors; i++) (*tao->monitor[i])(tao, tao->monitorcontext[i]);
2482:   return 0;
2483: }

2485: /*@
2486:    TaoSetConvergenceHistory - Sets the array used to hold the convergence history.

2488:    Logically Collective on tao

2490:    Input Parameters:
2491: +  tao - the Tao solver context
2492: .  obj   - array to hold objective value history
2493: .  resid - array to hold residual history
2494: .  cnorm - array to hold constraint violation history
2495: .  lits - integer array holds the number of linear iterations for each Tao iteration
2496: .  na  - size of obj, resid, and cnorm
2497: -  reset - `PETSC_TRUE` indicates each new minimization resets the history counter to zero,
2498:            else it continues storing new values for new minimizations after the old ones

2500:    Notes:
2501:    If set, Tao will fill the given arrays with the indicated
2502:    information at each iteration.  If 'obj','resid','cnorm','lits' are
2503:    *all* NULL then space (using size na, or 1000 if na is `PETSC_DECIDE` or
2504:    `PETSC_DEFAULT`) is allocated for the history.
2505:    If not all are NULL, then only the non-NULL information categories
2506:    will be stored, the others will be ignored.

2508:    Any convergence information after iteration number 'na' will not be stored.

2510:    This routine is useful, e.g., when running a code for purposes
2511:    of accurate performance monitoring, when no I/O should be done
2512:    during the section of code that is being timed.

2514:    Level: intermediate

2516: .seealso: `TaoGetConvergenceHistory()`

2518: @*/
2519: PetscErrorCode TaoSetConvergenceHistory(Tao tao, PetscReal obj[], PetscReal resid[], PetscReal cnorm[], PetscInt lits[], PetscInt na, PetscBool reset)
2520: {

2527:   if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
2528:   if (!obj && !resid && !cnorm && !lits) {
2529:     PetscCalloc4(na, &obj, na, &resid, na, &cnorm, na, &lits);
2530:     tao->hist_malloc = PETSC_TRUE;
2531:   }

2533:   tao->hist_obj   = obj;
2534:   tao->hist_resid = resid;
2535:   tao->hist_cnorm = cnorm;
2536:   tao->hist_lits  = lits;
2537:   tao->hist_max   = na;
2538:   tao->hist_reset = reset;
2539:   tao->hist_len   = 0;
2540:   return 0;
2541: }

2543: /*@C
2544:    TaoGetConvergenceHistory - Gets the arrays used that hold the convergence history.

2546:    Collective on tao

2548:    Input Parameter:
2549: .  tao - the Tao context

2551:    Output Parameters:
2552: +  obj   - array used to hold objective value history
2553: .  resid - array used to hold residual history
2554: .  cnorm - array used to hold constraint violation history
2555: .  lits  - integer array used to hold linear solver iteration count
2556: -  nhist  - size of obj, resid, cnorm, and lits

2558:    Notes:
2559:     This routine must be preceded by calls to `TaoSetConvergenceHistory()`
2560:     and `TaoSolve()`, otherwise it returns useless information.

2562:     The calling sequence for this routine in Fortran is
2563: $   call TaoGetConvergenceHistory(Tao tao, PetscInt nhist, PetscErrorCode ierr)

2565:    This routine is useful, e.g., when running a code for purposes
2566:    of accurate performance monitoring, when no I/O should be done
2567:    during the section of code that is being timed.

2569:    Level: advanced

2571: .seealso: `Tao`, `TaoSolve()`, `TaoSetConvergenceHistory()`

2573: @*/
2574: PetscErrorCode TaoGetConvergenceHistory(Tao tao, PetscReal **obj, PetscReal **resid, PetscReal **cnorm, PetscInt **lits, PetscInt *nhist)
2575: {
2577:   if (obj) *obj = tao->hist_obj;
2578:   if (cnorm) *cnorm = tao->hist_cnorm;
2579:   if (resid) *resid = tao->hist_resid;
2580:   if (nhist) *nhist = tao->hist_len;
2581:   return 0;
2582: }

2584: /*@
2585:    TaoSetApplicationContext - Sets the optional user-defined context for
2586:    a solver.

2588:    Logically Collective on tao

2590:    Input Parameters:
2591: +  tao  - the Tao context
2592: -  usrP - optional user context

2594:    Level: intermediate

2596: .seealso: `Tao`, `TaoGetApplicationContext()`, `TaoSetApplicationContext()`
2597: @*/
2598: PetscErrorCode TaoSetApplicationContext(Tao tao, void *usrP)
2599: {
2601:   tao->user = usrP;
2602:   return 0;
2603: }

2605: /*@
2606:    TaoGetApplicationContext - Gets the user-defined context for a
2607:    Tao solvers.

2609:    Not Collective

2611:    Input Parameter:
2612: .  tao  - Tao context

2614:    Output Parameter:
2615: .  usrP - user context

2617:    Level: intermediate

2619: .seealso: `TaoSetApplicationContext()`
2620: @*/
2621: PetscErrorCode TaoGetApplicationContext(Tao tao, void *usrP)
2622: {
2625:   *(void **)usrP = tao->user;
2626:   return 0;
2627: }

2629: /*@
2630:    TaoSetGradientNorm - Sets the matrix used to define the norm that measures the size of the gradient.

2632:    Collective on tao

2634:    Input Parameters:
2635: +  tao  - the Tao context
2636: -  M    - matrix that defines the norm

2638:    Level: beginner

2640: .seealso: `Tao`, `TaoGetGradientNorm()`, `TaoGradientNorm()`
2641: @*/
2642: PetscErrorCode TaoSetGradientNorm(Tao tao, Mat M)
2643: {
2646:   PetscObjectReference((PetscObject)M);
2647:   MatDestroy(&tao->gradient_norm);
2648:   VecDestroy(&tao->gradient_norm_tmp);
2649:   tao->gradient_norm = M;
2650:   MatCreateVecs(M, NULL, &tao->gradient_norm_tmp);
2651:   return 0;
2652: }

2654: /*@
2655:    TaoGetGradientNorm - Returns the matrix used to define the norm used for measuring the size of the gradient.

2657:    Not Collective

2659:    Input Parameter:
2660: .  tao  - Tao context

2662:    Output Parameter:
2663: .  M - gradient norm

2665:    Level: beginner

2667: .seealso: `Tao`, `TaoSetGradientNorm()`, `TaoGradientNorm()`
2668: @*/
2669: PetscErrorCode TaoGetGradientNorm(Tao tao, Mat *M)
2670: {
2673:   *M = tao->gradient_norm;
2674:   return 0;
2675: }

2677: /*@C
2678:    TaoGradientNorm - Compute the norm with respect to the norm the user has set.

2680:    Collective on tao

2682:    Input Parameters:
2683: +  tao      - the Tao context
2684: .  gradient - the gradient to be computed
2685: -  norm     - the norm type

2687:    Output Parameter:
2688: .  gnorm    - the gradient norm

2690:    Level: developer

2692: .seealso: `Tao`, `TaoSetGradientNorm()`, `TaoGetGradientNorm()`
2693: @*/
2694: PetscErrorCode TaoGradientNorm(Tao tao, Vec gradient, NormType type, PetscReal *gnorm)
2695: {
2700:   if (tao->gradient_norm) {
2701:     PetscScalar gnorms;

2704:     MatMult(tao->gradient_norm, gradient, tao->gradient_norm_tmp);
2705:     VecDot(gradient, tao->gradient_norm_tmp, &gnorms);
2706:     *gnorm = PetscRealPart(PetscSqrtScalar(gnorms));
2707:   } else {
2708:     VecNorm(gradient, type, gnorm);
2709:   }
2710:   return 0;
2711: }

2713: /*@C
2714:    TaoMonitorDrawCtxCreate - Creates the monitor context `TaoMonitorDrawSolution()`

2716:    Collective on tao

2718:    Output Patameter:
2719: .    ctx - the monitor context

2721:    Options Database:
2722: .   -tao_draw_solution_initial - show initial guess as well as current solution

2724:    Level: intermediate

2726: .seealso: `Tao`, `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawCtx()`
2727: @*/
2728: PetscErrorCode TaoMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TaoMonitorDrawCtx *ctx)
2729: {
2730:   PetscNew(ctx);
2731:   PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer);
2732:   PetscViewerSetFromOptions((*ctx)->viewer);
2733:   (*ctx)->howoften = howoften;
2734:   return 0;
2735: }

2737: /*@C
2738:    TaoMonitorDrawCtxDestroy - Destroys the monitor context for `TaoMonitorDrawSolution()`

2740:    Collective on tao

2742:    Input Parameters:
2743: .    ctx - the monitor context

2745:    Level: intermediate

2747: .seealso: `TaoMonitorSet()`, `TaoMonitorDefault()`, `VecView()`, `TaoMonitorDrawSolution()`
2748: @*/
2749: PetscErrorCode TaoMonitorDrawCtxDestroy(TaoMonitorDrawCtx *ictx)
2750: {
2751:   PetscViewerDestroy(&(*ictx)->viewer);
2752:   PetscFree(*ictx);
2753:   return 0;
2754: }