Actual source code: linesearch.c

  1: #include <petsc/private/linesearchimpl.h>

  3: PetscBool         SNESLineSearchRegisterAllCalled = PETSC_FALSE;
  4: PetscFunctionList SNESLineSearchList              = NULL;

  6: PetscClassId  SNESLINESEARCH_CLASSID;
  7: PetscLogEvent SNESLINESEARCH_Apply;

  9: /*@
 10:    SNESLineSearchMonitorCancel - Clears all the monitor functions for a `SNESLineSearch` object.

 12:    Logically Collective on ls

 14:    Input Parameters:
 15: .  ls - the `SNESLineSearch` context

 17:    Options Database Key:
 18: .  -snes_linesearch_monitor_cancel - cancels all monitors that have been hardwired
 19:     into a code by calls to `SNESLineSearchMonitorSet()`, but does not cancel those
 20:     set via the options database

 22:    Notes:
 23:    There is no way to clear one specific monitor from a `SNESLineSearch` object.

 25:    This does not clear the monitor set with `SNESLineSearchSetDefaultMonitor()` use `SNESLineSearchSetDefaultMonitor`(ls,NULL) to cancel
 26:    that one.

 28:    Level: advanced

 30: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorSet()`
 31: @*/
 32: PetscErrorCode SNESLineSearchMonitorCancel(SNESLineSearch ls)
 33: {
 34:   PetscInt i;

 37:   for (i = 0; i < ls->numbermonitors; i++) {
 38:     if (ls->monitordestroy[i]) (*ls->monitordestroy[i])(&ls->monitorcontext[i]);
 39:   }
 40:   ls->numbermonitors = 0;
 41:   return 0;
 42: }

 44: /*@
 45:    SNESLineSearchMonitor - runs the user provided monitor routines, if they exist

 47:    Collective on ls

 49:    Input Parameters:
 50: .  ls - the linesearch object

 52:    Note:
 53:    This routine is called by the SNES implementations.
 54:    It does not typically need to be called by the user.

 56:    Level: developer

 58: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorSet()`
 59: @*/
 60: PetscErrorCode SNESLineSearchMonitor(SNESLineSearch ls)
 61: {
 62:   PetscInt i, n = ls->numbermonitors;

 64:   for (i = 0; i < n; i++) (*ls->monitorftns[i])(ls, ls->monitorcontext[i]);
 65:   return 0;
 66: }

 68: /*@C
 69:    SNESLineSearchMonitorSet - Sets an ADDITIONAL function that is to be used at every
 70:    iteration of the nonlinear solver to display the iteration's
 71:    progress.

 73:    Logically Collective on ls

 75:    Input Parameters:
 76: +  ls - the `SNESLineSearch` context
 77: .  f - the monitor function
 78: .  mctx - [optional] user-defined context for private data for the
 79:           monitor routine (use NULL if no context is desired)
 80: -  monitordestroy - [optional] routine that frees monitor context
 81:           (may be NULL)

 83:    Note:
 84:    Several different monitoring routines may be set by calling
 85:    `SNESLineSearchMonitorSet()` multiple times; all will be called in the
 86:    order in which they were set.

 88:    Fortran Note:
 89:    Only a single monitor function can be set for each `SNESLineSearch` object

 91:    Level: intermediate

 93: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorCancel()`
 94: @*/
 95: PetscErrorCode SNESLineSearchMonitorSet(SNESLineSearch ls, PetscErrorCode (*f)(SNESLineSearch, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
 96: {
 97:   PetscInt  i;
 98:   PetscBool identical;

101:   for (i = 0; i < ls->numbermonitors; i++) {
102:     PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))ls->monitorftns[i], ls->monitorcontext[i], ls->monitordestroy[i], &identical);
103:     if (identical) return 0;
104:   }
106:   ls->monitorftns[ls->numbermonitors]      = f;
107:   ls->monitordestroy[ls->numbermonitors]   = monitordestroy;
108:   ls->monitorcontext[ls->numbermonitors++] = (void *)mctx;
109:   return 0;
110: }

112: /*@C
113:    SNESLineSearchMonitorSolutionUpdate - Monitors each update of the function value the linesearch tries

115:    Collective on ls

117:    Input Parameters:
118: +  ls - the `SNES` linesearch object
119: -  vf - the context for the monitor, in this case it is an `PetscViewerAndFormat`

121:    Level: intermediate

123: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESMonitorSet()`, `SNESMonitorSolution()`
124: @*/
125: PetscErrorCode SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls, PetscViewerAndFormat *vf)
126: {
127:   PetscViewer viewer = vf->viewer;
128:   Vec         Y, W, G;

130:   SNESLineSearchGetVecs(ls, NULL, NULL, &Y, &W, &G);
131:   PetscViewerPushFormat(viewer, vf->format);
132:   PetscViewerASCIIPrintf(viewer, "LineSearch attempted update to solution \n");
133:   VecView(Y, viewer);
134:   PetscViewerASCIIPrintf(viewer, "LineSearch attempted new solution \n");
135:   VecView(W, viewer);
136:   PetscViewerASCIIPrintf(viewer, "LineSearch attempted updated function value\n");
137:   VecView(G, viewer);
138:   PetscViewerPopFormat(viewer);
139:   return 0;
140: }

142: /*@
143:    SNESLineSearchCreate - Creates the line search context.

145:    Logically Collective

147:    Input Parameters:
148: .  comm - MPI communicator for the line search (typically from the associated `SNES` context).

150:    Output Parameters:
151: .  outlinesearch - the new linesearch context

153:    Level: developer

155:    Note:
156:    The preferred calling sequence for users is to use `SNESGetLineSearch()` to acquire the `SNESLineSearch` instance
157:    already associated with the `SNES`.

159: .seealso: `SNESLineSearch`, `LineSearchDestroy()`, `SNESGetLineSearch()`
160: @*/
161: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
162: {
163:   SNESLineSearch linesearch;

166:   SNESInitializePackage();
167:   *outlinesearch = NULL;

169:   PetscHeaderCreate(linesearch, SNESLINESEARCH_CLASSID, "SNESLineSearch", "Linesearch", "SNESLineSearch", comm, SNESLineSearchDestroy, SNESLineSearchView);

171:   linesearch->vec_sol_new  = NULL;
172:   linesearch->vec_func_new = NULL;
173:   linesearch->vec_sol      = NULL;
174:   linesearch->vec_func     = NULL;
175:   linesearch->vec_update   = NULL;

177:   linesearch->lambda       = 1.0;
178:   linesearch->fnorm        = 1.0;
179:   linesearch->ynorm        = 1.0;
180:   linesearch->xnorm        = 1.0;
181:   linesearch->result       = SNES_LINESEARCH_SUCCEEDED;
182:   linesearch->norms        = PETSC_TRUE;
183:   linesearch->keeplambda   = PETSC_FALSE;
184:   linesearch->damping      = 1.0;
185:   linesearch->maxstep      = 1e8;
186:   linesearch->steptol      = 1e-12;
187:   linesearch->rtol         = 1e-8;
188:   linesearch->atol         = 1e-15;
189:   linesearch->ltol         = 1e-8;
190:   linesearch->precheckctx  = NULL;
191:   linesearch->postcheckctx = NULL;
192:   linesearch->max_its      = 1;
193:   linesearch->setupcalled  = PETSC_FALSE;
194:   linesearch->monitor      = NULL;
195:   *outlinesearch           = linesearch;
196:   return 0;
197: }

199: /*@
200:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
201:    any required vectors.

203:    Collective on linesearch

205:    Input Parameters:
206: .  linesearch - The `SNESLineSearch` instance.

208:    Note:
209:    For most cases, this needn't be called by users or outside of `SNESLineSearchApply()`.
210:    The only current case where this is called outside of this is for the VI
211:    solvers, which modify the solution and work vectors before the first call
212:    of `SNESLineSearchApply()`, requiring the `SNESLineSearch` work vectors to be
213:    allocated upfront.

215:    Level: advanced

217: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchReset()`
218: @*/

220: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
221: {
222:   if (!((PetscObject)linesearch)->type_name) SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);
223:   if (!linesearch->setupcalled) {
224:     if (!linesearch->vec_sol_new) VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
225:     if (!linesearch->vec_func_new) VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
226:     if (linesearch->ops->setup) PetscUseTypeMethod(linesearch, setup);
227:     if (!linesearch->ops->snesfunc) SNESLineSearchSetFunction(linesearch, SNESComputeFunction);
228:     linesearch->lambda      = linesearch->damping;
229:     linesearch->setupcalled = PETSC_TRUE;
230:   }
231:   return 0;
232: }

234: /*@
235:    SNESLineSearchReset - Undoes the `SNESLineSearchSetUp()` and deletes any `Vec`s or `Mat`s allocated by the line search.

237:    Collective on linesearch

239:    Input Parameters:
240: .  linesearch - The `SNESLineSearch` instance.

242:    Note:
243:     Usually only called by `SNESReset()`

245:    Level: developer

247: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetUp()`
248: @*/

250: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
251: {
252:   if (linesearch->ops->reset) PetscUseTypeMethod(linesearch, reset);

254:   VecDestroy(&linesearch->vec_sol_new);
255:   VecDestroy(&linesearch->vec_func_new);

257:   VecDestroyVecs(linesearch->nwork, &linesearch->work);

259:   linesearch->nwork       = 0;
260:   linesearch->setupcalled = PETSC_FALSE;
261:   return 0;
262: }

264: /*@C
265:    SNESLineSearchSetFunction - Sets the function evaluation used by the `SNES` line search
266: `
267:    Input Parameters:
268: .  linesearch - the `SNESLineSearch` context
269: +  func       - function evaluation routine, this is usually the function provided with `SNESSetFunction()`

271:    Level: developer

273: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESSetFunction()`
274: @*/
275: PetscErrorCode SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES, Vec, Vec))
276: {
278:   linesearch->ops->snesfunc = func;
279:   return 0;
280: }

282: /*@C
283:    SNESLineSearchSetPreCheck - Sets a user function that is called after the initial search direction has been computed but
284:          before the line search routine has been applied. Allows the user to adjust the result of (usually a linear solve) that
285:          determined the search direction.

287:    Logically Collective on linesearch

289:    Input Parameters:
290: +  linesearch - the `SNESLineSearch` context
291: .  func - [optional] function evaluation routine, see `SNESLineSearchPreCheck()` for the calling sequence
292: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

294:    Level: intermediate

296:    Note:
297:    Use `SNESLineSearchSetPostCheck()` to change the step after the line search.
298:    search is complete.

300:    Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.

302: .seealso: `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
303:           `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()

305: @*/
306: PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void *ctx)
307: {
309:   if (func) linesearch->ops->precheck = func;
310:   if (ctx) linesearch->precheckctx = ctx;
311:   return 0;
312: }

314: /*@C
315:    SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.

317:    Input Parameter:
318: .  linesearch - the `SNESLineSearch` context

320:    Output Parameters:
321: +  func       - [optional] function evaluation routine, see `SNESLineSearchPreCheck` for calling sequence
322: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

324:    Level: intermediate

326: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
327: @*/
328: PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void **ctx)
329: {
331:   if (func) *func = linesearch->ops->precheck;
332:   if (ctx) *ctx = linesearch->precheckctx;
333:   return 0;
334: }

336: /*@C
337:    SNESLineSearchSetPostCheck - Sets a user function that is called after the line search has been applied to determine the step
338:        direction and length. Allows the user a chance to change or override the decision of the line search routine

340:    Logically Collective linesearch

342:    Input Parameters:
343: +  linesearch - the `SNESLineSearch` context
344: .  func - [optional] function evaluation routine, see `SNESLineSearchPostCheck`  for the calling sequence
345: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

347:    Level: intermediate

349:    Notes:
350:    Use `SNESLineSearchSetPreCheck()` to change the step before the line search.
351:    search is complete.

353:    Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.

355: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
356:           `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()
357: @*/
358: PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void *ctx)
359: {
361:   if (func) linesearch->ops->postcheck = func;
362:   if (ctx) linesearch->postcheckctx = ctx;
363:   return 0;
364: }

366: /*@C
367:    SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.

369:    Input Parameter:
370: .  linesearch - the `SNESLineSearch` context

372:    Output Parameters:
373: +  func - [optional] function evaluation routine, see for the calling sequence `SNESLineSearchPostCheck`
374: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

376:    Level: intermediate

378: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
379: @*/
380: PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void **ctx)
381: {
383:   if (func) *func = linesearch->ops->postcheck;
384:   if (ctx) *ctx = linesearch->postcheckctx;
385:   return 0;
386: }

388: /*@
389:    SNESLineSearchPreCheck - Prepares the line search for being applied.

391:    Logically Collective on linesearch

393:    Input Parameters:
394: +  linesearch - The linesearch instance.
395: .  X - The current solution
396: -  Y - The step direction

398:    Output Parameters:
399: .  changed - Indicator that the precheck routine has changed anything

401:    Level: advanced

403:    Note:
404:    This calls any function provided with `SNESLineSearchSetPreCheck()`

406: .seealso: `SNESLineSearch`,  `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
407:           `SNESLineSearchGetPostCheck()``
408: @*/
409: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed)
410: {
411:   *changed = PETSC_FALSE;
412:   if (linesearch->ops->precheck) {
413:     PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
415:   }
416:   return 0;
417: }

419: /*@
420:    SNESLineSearchPostCheck - Hook to modify step direction or updated solution after a successful linesearch

422:    Logically Collective on linesearch

424:    Input Parameters:
425: +  linesearch - The linesearch context
426: .  X - The last solution
427: .  Y - The step direction
428: -  W - The updated solution, W = X + lambda*Y for some lambda

430:    Output Parameters:
431: +  changed_Y - Indicator if the direction Y has been changed.
432: -  changed_W - Indicator if the new candidate solution W has been changed.

434:    Note:
435:    This calls any function provided with `SNESLineSearchSetPreCheck()`

437:    Level: developer

439: .seealso: `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
440: @*/
441: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W)
442: {
443:   *changed_Y = PETSC_FALSE;
444:   *changed_W = PETSC_FALSE;
445:   if (linesearch->ops->postcheck) {
446:     PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
449:   }
450:   return 0;
451: }

453: /*@C
454:    SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration

456:    Logically Collective on linesearch

458:    Input Parameters:
459: +  linesearch - linesearch context
460: .  X - base state for this step
461: -  ctx - context for this function

463:    Input/Output Parameter:
464: .  Y - correction, possibly modified

466:    Output Parameter:
467: .  changed - flag indicating that Y was modified

469:    Options Database Key:
470: +  -snes_linesearch_precheck_picard - activate this routine
471: -  -snes_linesearch_precheck_picard_angle - angle

473:    Level: advanced

475:    Notes:
476:    This function should be passed to `SNESLineSearchSetPreCheck()`

478:    The justification for this method involves the linear convergence of a Picard iteration
479:    so the Picard linearization should be provided in place of the "Jacobian". This correction
480:    is generally not useful when using a Newton linearization.

482:    Reference:
483:  . - * - Hindmarsh and Payne (1996) Time step limits for stable solutions of the ice sheet equation, Annals of Glaciology.

485: .seealso: `SNESLineSearch`, `SNESSetPicard()`, `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`
486: @*/
487: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, void *ctx)
488: {
489:   PetscReal   angle = *(PetscReal *)linesearch->precheckctx;
490:   Vec         Ylast;
491:   PetscScalar dot;
492:   PetscInt    iter;
493:   PetscReal   ynorm, ylastnorm, theta, angle_radians;
494:   SNES        snes;

496:   SNESLineSearchGetSNES(linesearch, &snes);
497:   PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast);
498:   if (!Ylast) {
499:     VecDuplicate(Y, &Ylast);
500:     PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast);
501:     PetscObjectDereference((PetscObject)Ylast);
502:   }
503:   SNESGetIterationNumber(snes, &iter);
504:   if (iter < 2) {
505:     VecCopy(Y, Ylast);
506:     *changed = PETSC_FALSE;
507:     return 0;
508:   }

510:   VecDot(Y, Ylast, &dot);
511:   VecNorm(Y, NORM_2, &ynorm);
512:   VecNorm(Ylast, NORM_2, &ylastnorm);
513:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
514:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
515:   angle_radians = angle * PETSC_PI / 180.;
516:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
517:     /* Modify the step Y */
518:     PetscReal alpha, ydiffnorm;
519:     VecAXPY(Ylast, -1.0, Y);
520:     VecNorm(Ylast, NORM_2, &ydiffnorm);
521:     alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
522:     VecCopy(Y, Ylast);
523:     VecScale(Y, alpha);
524:     PetscInfo(snes, "Angle %14.12e degrees less than threshold %14.12e, corrected step by alpha=%14.12e\n", (double)(theta * 180. / PETSC_PI), (double)angle, (double)alpha);
525:     *changed = PETSC_TRUE;
526:   } else {
527:     PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180. / PETSC_PI), (double)angle);
528:     VecCopy(Y, Ylast);
529:     *changed = PETSC_FALSE;
530:   }
531:   return 0;
532: }

534: /*@
535:    SNESLineSearchApply - Computes the line-search update.

537:    Collective on linesearch

539:    Input Parameters:
540: +  linesearch - The linesearch context
541: -  Y - The search direction

543:    Input/Output Parameters:
544: +  X - The current solution, on output the new solution
545: .  F - The current function, on output the new function
546: -  fnorm - The current norm, on output the new function norm

548:    Options Database Keys:
549: + -snes_linesearch_type - basic (or equivalently none), bt, l2, cp, nleqerr, shell
550: . -snes_linesearch_monitor [:filename] - Print progress of line searches
551: . -snes_linesearch_damping - The linesearch damping parameter, default is 1.0 (no damping)
552: . -snes_linesearch_norms   - Turn on/off the linesearch norms computation (SNESLineSearchSetComputeNorms())
553: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
554: - -snes_linesearch_max_it - The number of iterations for iterative line searches

556:    Notes:
557:    This is typically called from within a `SNESSolve()` implementation in order to
558:    help with convergence of the nonlinear method.  Various `SNES` types use line searches
559:    in different ways, but the overarching theme is that a line search is used to determine
560:    an optimal damping parameter of a step at each iteration of the method.  Each
561:    application of the line search may invoke `SNESComputeFunction()` several times, and
562:    therefore may be fairly expensive.

564:    Level: Intermediate

566: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
567:           `SNESLineSearchType`, `SNESLineSearchSetType()`
568: @*/
569: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y)
570: {

576:   linesearch->result = SNES_LINESEARCH_SUCCEEDED;

578:   linesearch->vec_sol    = X;
579:   linesearch->vec_update = Y;
580:   linesearch->vec_func   = F;

582:   SNESLineSearchSetUp(linesearch);

584:   if (!linesearch->keeplambda) linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */

586:   if (fnorm) linesearch->fnorm = *fnorm;
587:   else VecNorm(F, NORM_2, &linesearch->fnorm);

589:   PetscLogEventBegin(SNESLINESEARCH_Apply, linesearch, X, F, Y);

591:   PetscUseTypeMethod(linesearch, apply);

593:   PetscLogEventEnd(SNESLINESEARCH_Apply, linesearch, X, F, Y);

595:   if (fnorm) *fnorm = linesearch->fnorm;
596:   return 0;
597: }

599: /*@
600:    SNESLineSearchDestroy - Destroys the line search instance.

602:    Collective on linesearch

604:    Input Parameters:
605: .  linesearch - The linesearch context

607:    Level: developer

609: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
610: @*/
611: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch)
612: {
613:   if (!*linesearch) return 0;
615:   if (--((PetscObject)(*linesearch))->refct > 0) {
616:     *linesearch = NULL;
617:     return 0;
618:   }
619:   PetscObjectSAWsViewOff((PetscObject)*linesearch);
620:   SNESLineSearchReset(*linesearch);
621:   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
622:   PetscViewerDestroy(&(*linesearch)->monitor);
623:   SNESLineSearchMonitorCancel((*linesearch));
624:   PetscHeaderDestroy(linesearch);
625:   return 0;
626: }

628: /*@
629:    SNESLineSearchSetDefaultMonitor - Turns on/off printing useful information and debugging output about the line search.

631:    Logically Collective on linesearch

633:    Input Parameters:
634: +  linesearch - the linesearch object
635: -  viewer - an `PETSCVIEWERASCII` `PetscViewer` or NULL to turn off monitor

637:    Options Database Key:
638: .   -snes_linesearch_monitor [:filename] - enables the monitor

640:    Level: intermediate

642:    Developer Note:
643:    This monitor is implemented differently than the other line search monitors that are set with
644:    `SNESLineSearchMonitorSet()` since it is called in many locations of the line search routines to display aspects of the
645:    line search that are not visible to the other monitors.

647: .seealso: `SNESLineSearch`, `PETSCVIEWERASCII`, `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`,
648:           `SNESLineSearchMonitorSetFromOptions()`
649: @*/
650: PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
651: {
652:   if (viewer) PetscObjectReference((PetscObject)viewer);
653:   PetscViewerDestroy(&linesearch->monitor);
654:   linesearch->monitor = viewer;
655:   return 0;
656: }

658: /*@
659:    SNESLineSearchGetDefaultMonitor - Gets the `PetscViewer` instance for the line search monitor.

661:    Logically Collective on linsearch

663:    Input Parameter:
664: .  linesearch - linesearch context

666:    Output Parameter:
667: .  monitor - monitor context

669:    Level: intermediate

671: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
672: @*/
673: PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
674: {
676:   *monitor = linesearch->monitor;
677:   return 0;
678: }

680: /*@C
681:    SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user

683:    Collective on ls

685:    Input Parameters:
686: +  ls - `SNESLineSearch` object you wish to monitor
687: .  name - the monitor type one is seeking
688: .  help - message indicating what monitoring is done
689: .  manual - manual page for the monitor
690: .  monitor - the monitor function
691: -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNESLineSearch` or `PetscViewer`

693:    Level: developer

695: .seealso: `SNESLineSearch`, `SNESLineSearchSetMonitor()`, `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
696:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
697:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
698:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
699:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
700:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
701:           `PetscOptionsFList()`, `PetscOptionsEList()`
702: @*/
703: PetscErrorCode SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNESLineSearch, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(SNESLineSearch, PetscViewerAndFormat *))
704: {
705:   PetscViewer       viewer;
706:   PetscViewerFormat format;
707:   PetscBool         flg;

709:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg);
710:   if (flg) {
711:     PetscViewerAndFormat *vf;
712:     PetscViewerAndFormatCreate(viewer, format, &vf);
713:     PetscObjectDereference((PetscObject)viewer);
714:     if (monitorsetup) (*monitorsetup)(ls, vf);
715:     SNESLineSearchMonitorSet(ls, (PetscErrorCode(*)(SNESLineSearch, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
716:   }
717:   return 0;
718: }

720: /*@
721:    SNESLineSearchSetFromOptions - Sets options for the line search

723:    Logically Collective on linesearch

725:    Input Parameter:
726: .  linesearch - linesearch context

728:    Options Database Keys:
729: + -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
730: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
731: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch typem (`SNESLineSearchSetComputeNorms()`)
732: . -snes_linesearch_minlambda - The minimum step length
733: . -snes_linesearch_maxstep - The maximum step size
734: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
735: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
736: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
737: . -snes_linesearch_max_it - The number of iterations for iterative line searches
738: . -snes_linesearch_monitor [:filename] - Print progress of line searches
739: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
740: . -snes_linesearch_damping - The linesearch damping parameter
741: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
742: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
743: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method

745:    Level: intermediate

747: .seealso: `SNESLineSearch`, `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
748:           `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
749: @*/
750: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
751: {
752:   const char *deft = SNESLINESEARCHBASIC;
753:   char        type[256];
754:   PetscBool   flg, set;
755:   PetscViewer viewer;

757:   SNESLineSearchRegisterAll();

759:   PetscObjectOptionsBegin((PetscObject)linesearch);
760:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
761:   PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg);
762:   if (flg) {
763:     SNESLineSearchSetType(linesearch, type);
764:   } else if (!((PetscObject)linesearch)->type_name) {
765:     SNESLineSearchSetType(linesearch, deft);
766:   }

768:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set);
769:   if (set) {
770:     SNESLineSearchSetDefaultMonitor(linesearch, viewer);
771:     PetscViewerDestroy(&viewer);
772:   }
773:   SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL);

775:   /* tolerances */
776:   PetscOptionsReal("-snes_linesearch_minlambda", "Minimum step length", "SNESLineSearchSetTolerances", linesearch->steptol, &linesearch->steptol, NULL);
777:   PetscOptionsReal("-snes_linesearch_maxstep", "Maximum step size", "SNESLineSearchSetTolerances", linesearch->maxstep, &linesearch->maxstep, NULL);
778:   PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL);
779:   PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL);
780:   PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL);
781:   PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_its, &linesearch->max_its, NULL);

783:   /* damping parameters */
784:   PetscOptionsReal("-snes_linesearch_damping", "Line search damping and initial step guess", "SNESLineSearchSetDamping", linesearch->damping, &linesearch->damping, NULL);

786:   PetscOptionsBool("-snes_linesearch_keeplambda", "Use previous lambda as damping", "SNESLineSearchSetKeepLambda", linesearch->keeplambda, &linesearch->keeplambda, NULL);

788:   /* precheck */
789:   PetscOptionsBool("-snes_linesearch_precheck_picard", "Use a correction that sometimes improves convergence of Picard iteration", "SNESLineSearchPreCheckPicard", flg, &flg, &set);
790:   if (set) {
791:     if (flg) {
792:       linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */

794:       PetscOptionsReal("-snes_linesearch_precheck_picard_angle", "Maximum angle at which to activate the correction", "none", linesearch->precheck_picard_angle, &linesearch->precheck_picard_angle, NULL);
795:       SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle);
796:     } else {
797:       SNESLineSearchSetPreCheck(linesearch, NULL, NULL);
798:     }
799:   }
800:   PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL);
801:   PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL);

803:   PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);

805:   PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject);
806:   PetscOptionsEnd();
807:   return 0;
808: }

810: /*@
811:    SNESLineSearchView - Prints useful information about the line search

813:    Input Parameters:
814: .  linesearch - linesearch context

816:    Logically Collective on linesearch

818:    Level: intermediate

820: .seealso: `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`
821: @*/
822: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
823: {
824:   PetscBool iascii;

827:   if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer);

831:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
832:   if (iascii) {
833:     PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer);
834:     PetscViewerASCIIPushTab(viewer);
835:     PetscTryTypeMethod(linesearch, view, viewer);
836:     PetscViewerASCIIPopTab(viewer);
837:     PetscViewerASCIIPrintf(viewer, "  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep, (double)linesearch->steptol);
838:     PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol);
839:     PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT "\n", linesearch->max_its);
840:     if (linesearch->ops->precheck) {
841:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
842:         PetscViewerASCIIPrintf(viewer, "  using precheck step to speed up Picard convergence\n");
843:       } else {
844:         PetscViewerASCIIPrintf(viewer, "  using user-defined precheck step\n");
845:       }
846:     }
847:     if (linesearch->ops->postcheck) PetscViewerASCIIPrintf(viewer, "  using user-defined postcheck step\n");
848:   }
849:   return 0;
850: }

852: /*@C
853:    SNESLineSearchGetType - Gets the linesearch type

855:    Logically Collective on linesearch

857:    Input Parameters:
858: .  linesearch - linesearch context

860:    Output Parameters:
861: -  type - The type of line search, or NULL if not set

863:    Level: intermediate

865: .seealso: `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
866: @*/
867: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
868: {
871:   *type = ((PetscObject)linesearch)->type_name;
872:   return 0;
873: }

875: /*@C
876:    SNESLineSearchSetType - Sets the linesearch type

878:    Logically Collective on linesearch

880:    Input Parameters:
881: +  linesearch - linesearch context
882: -  type - The type of line search to be used

884:    Available Types:
885: +  `SNESLINESEARCHBASIC` - (or equivalently `SNESLINESEARCHNONE`) Simple damping line search, defaults to using the full Newton step
886: .  `SNESLINESEARCHBT` - Backtracking line search over the L2 norm of the function
887: .  `SNESLINESEARCHL2` - Secant line search over the L2 norm of the function
888: .  `SNESLINESEARCHCP` - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
889: .  `SNESLINESEARCHNLEQERR` - Affine-covariant error-oriented linesearch
890: -  `SNESLINESEARCHSHELL` - User provided `SNESLineSearch` implementation

892:    Options Database:
893: .  -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell

895:    Level: intermediate

897: .seealso:  `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`
898: @*/
899: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
900: {
901:   PetscBool match;
902:   PetscErrorCode (*r)(SNESLineSearch);


907:   PetscObjectTypeCompare((PetscObject)linesearch, type, &match);
908:   if (match) return 0;

910:   PetscFunctionListFind(SNESLineSearchList, type, &r);
912:   /* Destroy the previous private linesearch context */
913:   if (linesearch->ops->destroy) {
914:     (*(linesearch)->ops->destroy)(linesearch);
915:     linesearch->ops->destroy = NULL;
916:   }
917:   /* Reinitialize function pointers in SNESLineSearchOps structure */
918:   linesearch->ops->apply          = NULL;
919:   linesearch->ops->view           = NULL;
920:   linesearch->ops->setfromoptions = NULL;
921:   linesearch->ops->destroy        = NULL;

923:   PetscObjectChangeTypeName((PetscObject)linesearch, type);
924:   (*r)(linesearch);
925:   return 0;
926: }

928: /*@
929:    SNESLineSearchSetSNES - Sets the `SNES` for the linesearch for function evaluation.

931:    Input Parameters:
932: +  linesearch - linesearch context
933: -  snes - The snes instance

935:    Level: developer

937:    Note:
938:    This happens automatically when the line search is obtained/created with
939:    `SNESGetLineSearch()`.  This routine is therefore mainly called within `SNES`
940:    implementations.

942:    Level: developer

944: .seealso: `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
945: @*/
946: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
947: {
950:   linesearch->snes = snes;
951:   return 0;
952: }

954: /*@
955:    SNESLineSearchGetSNES - Gets the `SNES` instance associated with the line search.
956:    Having an associated `SNES` is necessary because most line search implementations must be able to
957:    evaluate the function using `SNESComputeFunction()` for the associated `SNES`.  This routine
958:    is used in the line search implementations when one must get this associated `SNES` instance.

960:    Not Collective

962:    Input Parameters:
963: .  linesearch - linesearch context

965:    Output Parameters:
966: .  snes - The snes instance

968:    Level: developer

970: .seealso: `SNESLineSearch`, `SNESType`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
971: @*/
972: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
973: {
976:   *snes = linesearch->snes;
977:   return 0;
978: }

980: /*@
981:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

983:    Not Collective

985:    Input Parameters:
986: .  linesearch - linesearch context

988:    Output Parameters:
989: .  lambda - The last steplength computed during `SNESLineSearchApply()`

991:    Level: advanced

993:    Note:
994:    This is useful in methods where the solver is ill-scaled and
995:    requires some adaptive notion of the difference in scale between the
996:    solution and the function.  For instance, `SNESQN` may be scaled by the
997:    line search lambda using the argument -snes_qn_scaling ls.

999: .seealso: `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1000: @*/
1001: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1002: {
1005:   *lambda = linesearch->lambda;
1006:   return 0;
1007: }

1009: /*@
1010:    SNESLineSearchSetLambda - Sets the linesearch steplength

1012:    Input Parameters:
1013: +  linesearch - linesearch context
1014: -  lambda - The last steplength.

1016:    Note:
1017:    This routine is typically used within implementations of `SNESLineSearchApply()`
1018:    to set the final steplength.  This routine (and `SNESLineSearchGetLambda()`) were
1019:    added in order to facilitate Quasi-Newton methods that use the previous steplength
1020:    as an inner scaling parameter.

1022:    Level: advanced

1024: .seealso: `SNESLineSearch`, `SNESLineSearchGetLambda()`
1025: @*/
1026: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1027: {
1029:   linesearch->lambda = lambda;
1030:   return 0;
1031: }

1033: /*@
1034:    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
1035:    tolerances for the relative and absolute change in the function norm, the change
1036:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1037:    and the maximum number of iterations the line search procedure may take.

1039:    Not Collective

1041:    Input Parameter:
1042: .  linesearch - linesearch context

1044:    Output Parameters:
1045: +  steptol - The minimum steplength
1046: .  maxstep - The maximum steplength
1047: .  rtol    - The relative tolerance for iterative line searches
1048: .  atol    - The absolute tolerance for iterative line searches
1049: .  ltol    - The change in lambda tolerance for iterative line searches
1050: -  max_it  - The maximum number of iterations of the line search

1052:    Level: intermediate

1054:    Note:
1055:    Different line searches may implement these parameters slightly differently as
1056:    the type requires.

1058: .seealso: `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1059: @*/
1060: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *steptol, PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1061: {
1063:   if (steptol) {
1065:     *steptol = linesearch->steptol;
1066:   }
1067:   if (maxstep) {
1069:     *maxstep = linesearch->maxstep;
1070:   }
1071:   if (rtol) {
1073:     *rtol = linesearch->rtol;
1074:   }
1075:   if (atol) {
1077:     *atol = linesearch->atol;
1078:   }
1079:   if (ltol) {
1081:     *ltol = linesearch->ltol;
1082:   }
1083:   if (max_its) {
1085:     *max_its = linesearch->max_its;
1086:   }
1087:   return 0;
1088: }

1090: /*@
1091:    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
1092:    tolerances for the relative and absolute change in the function norm, the change
1093:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1094:    and the maximum number of iterations the line search procedure may take.

1096:    Collective

1098:    Input Parameters:
1099: +  linesearch - linesearch context
1100: .  steptol - The minimum steplength
1101: .  maxstep - The maximum steplength
1102: .  rtol    - The relative tolerance for iterative line searches
1103: .  atol    - The absolute tolerance for iterative line searches
1104: .  ltol    - The change in lambda tolerance for iterative line searches
1105: -  max_it  - The maximum number of iterations of the line search

1107:    Note:
1108:    The user may choose to not set any of the tolerances using `PETSC_DEFAULT` in
1109:    place of an argument.

1111:    Level: intermediate

1113: .seealso: `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1114: @*/
1115: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal steptol, PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
1116: {

1125:   if (steptol != PETSC_DEFAULT) {
1127:     linesearch->steptol = steptol;
1128:   }

1130:   if (maxstep != PETSC_DEFAULT) {
1132:     linesearch->maxstep = maxstep;
1133:   }

1135:   if (rtol != PETSC_DEFAULT) {
1137:     linesearch->rtol = rtol;
1138:   }

1140:   if (atol != PETSC_DEFAULT) {
1142:     linesearch->atol = atol;
1143:   }

1145:   if (ltol != PETSC_DEFAULT) {
1147:     linesearch->ltol = ltol;
1148:   }

1150:   if (max_its != PETSC_DEFAULT) {
1152:     linesearch->max_its = max_its;
1153:   }
1154:   return 0;
1155: }

1157: /*@
1158:    SNESLineSearchGetDamping - Gets the line search damping parameter.

1160:    Input Parameters:
1161: .  linesearch - linesearch context

1163:    Output Parameters:
1164: .  damping - The damping parameter

1166:    Level: advanced

1168: .seealso: `SNESLineSearchGetStepTolerance()`, `SNESQN`
1169: @*/

1171: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1172: {
1175:   *damping = linesearch->damping;
1176:   return 0;
1177: }

1179: /*@
1180:    SNESLineSearchSetDamping - Sets the line search damping parameter.

1182:    Input Parameters:
1183: +  linesearch - linesearch context
1184: -  damping - The damping parameter

1186:    Options Database Key:
1187: .   -snes_linesearch_damping <damping> - the damping value

1189:    Level: intermediate

1191:    Note:
1192:    The `SNESLINESEARCHNONE` line search merely takes the update step scaled by the damping parameter.
1193:    The use of the damping parameter in the l2 and cp line searches is much more subtle;
1194:    it is used as a starting point in calculating the secant step. However, the eventual
1195:    step may be of greater length than the damping parameter.  In the bt line search it is
1196:    used as the maximum possible step length, as the bt line search only backtracks.

1198: .seealso: `SNESLineSearch`, `SNESLineSearchGetDamping()`
1199: @*/
1200: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1201: {
1203:   linesearch->damping = damping;
1204:   return 0;
1205: }

1207: /*@
1208:    SNESLineSearchGetOrder - Gets the line search approximation order.

1210:    Input Parameter:
1211: .  linesearch - linesearch context

1213:    Output Parameter:
1214: .  order - The order

1216:    Possible Values for order:
1217: +  1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1218: .  2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1219: -  3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order

1221:    Level: intermediate

1223: .seealso: `SNESLineSearch`, `SNESLineSearchSetOrder()`
1224: @*/

1226: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1227: {
1230:   *order = linesearch->order;
1231:   return 0;
1232: }

1234: /*@
1235:    SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search

1237:    Input Parameters:
1238: +  linesearch - linesearch context
1239: -  order - The damping parameter

1241:    Level: intermediate

1243:    Possible Values for order:
1244: +  1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1245: .  2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1246: -  3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order

1248:    Notes:
1249:    Variable orders are supported by the following line searches:
1250: +  bt - cubic and quadratic
1251: -  cp - linear and quadratic

1253: .seealso: `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1254: @*/
1255: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1256: {
1258:   linesearch->order = order;
1259:   return 0;
1260: }

1262: /*@
1263:    SNESLineSearchGetNorms - Gets the norms for for X, Y, and F.

1265:    Not Collective

1267:    Input Parameter:
1268: .  linesearch - linesearch context

1270:    Output Parameters:
1271: +  xnorm - The norm of the current solution
1272: .  fnorm - The norm of the current function
1273: -  ynorm - The norm of the current update

1275:    Level: developer

1277: .seealso: `SNESLineSearch`, `SNESLineSearchSetNorms()` `SNESLineSearchGetVecs()`
1278: @*/
1279: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1280: {
1282:   if (xnorm) *xnorm = linesearch->xnorm;
1283:   if (fnorm) *fnorm = linesearch->fnorm;
1284:   if (ynorm) *ynorm = linesearch->ynorm;
1285:   return 0;
1286: }

1288: /*@
1289:    SNESLineSearchSetNorms - Gets the computed norms for for X, Y, and F.

1291:    Collective on linesearch

1293:    Input Parameters:
1294: +  linesearch - linesearch context
1295: .  xnorm - The norm of the current solution
1296: .  fnorm - The norm of the current function
1297: -  ynorm - The norm of the current update

1299:    Level: developer

1301: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1302: @*/
1303: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1304: {
1306:   linesearch->xnorm = xnorm;
1307:   linesearch->fnorm = fnorm;
1308:   linesearch->ynorm = ynorm;
1309:   return 0;
1310: }

1312: /*@
1313:    SNESLineSearchComputeNorms - Computes the norms of X, F, and Y.

1315:    Input Parameters:
1316: .  linesearch - linesearch context

1318:    Options Database Keys:
1319: .   -snes_linesearch_norms - turn norm computation on or off

1321:    Level: intermediate

1323: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1324: @*/
1325: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1326: {
1327:   SNES snes;

1329:   if (linesearch->norms) {
1330:     if (linesearch->ops->vinorm) {
1331:       SNESLineSearchGetSNES(linesearch, &snes);
1332:       VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1333:       VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1334:       (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
1335:     } else {
1336:       VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm);
1337:       VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1338:       VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1339:       VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm);
1340:       VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1341:       VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1342:     }
1343:   }
1344:   return 0;
1345: }

1347: /*@
1348:    SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.

1350:    Input Parameters:
1351: +  linesearch  - linesearch context
1352: -  flg  - indicates whether or not to compute norms

1354:    Options Database Keys:
1355: .   -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic (none) linesearch

1357:    Note:
1358:    This is most relevant to the `SNESLINESEARCHBASIC` (or equivalently `SNESLINESEARCHNONE`) line search type since most line searches have a stopping criteria involving the norm.

1360:    Level: intermediate

1362: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1363: @*/
1364: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1365: {
1366:   linesearch->norms = flg;
1367:   return 0;
1368: }

1370: /*@
1371:    SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context

1373:    Not Collective on but the vectors are parallel

1375:    Input Parameter:
1376: .  linesearch - linesearch context

1378:    Output Parameters:
1379: +  X - Solution vector
1380: .  F - Function vector
1381: .  Y - Search direction vector
1382: .  W - Solution work vector
1383: -  G - Function work vector

1385:    Notes:
1386:    At the beginning of a line search application, X should contain a
1387:    solution and the vector F the function computed at X.  At the end of the
1388:    line search application, X should contain the new solution, and F the
1389:    function evaluated at the new solution.

1391:    These vectors are owned by the `SNESLineSearch` and should not be destroyed by the caller

1393:    Level: advanced

1395: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1396: @*/
1397: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1398: {
1400:   if (X) {
1402:     *X = linesearch->vec_sol;
1403:   }
1404:   if (F) {
1406:     *F = linesearch->vec_func;
1407:   }
1408:   if (Y) {
1410:     *Y = linesearch->vec_update;
1411:   }
1412:   if (W) {
1414:     *W = linesearch->vec_sol_new;
1415:   }
1416:   if (G) {
1418:     *G = linesearch->vec_func_new;
1419:   }
1420:   return 0;
1421: }

1423: /*@
1424:    SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context

1426:    Logically Collective on linesearch

1428:    Input Parameters:
1429: +  linesearch - linesearch context
1430: .  X - Solution vector
1431: .  F - Function vector
1432: .  Y - Search direction vector
1433: .  W - Solution work vector
1434: -  G - Function work vector

1436:    Level: advanced

1438: .seealso: `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1439: @*/
1440: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1441: {
1443:   if (X) {
1445:     linesearch->vec_sol = X;
1446:   }
1447:   if (F) {
1449:     linesearch->vec_func = F;
1450:   }
1451:   if (Y) {
1453:     linesearch->vec_update = Y;
1454:   }
1455:   if (W) {
1457:     linesearch->vec_sol_new = W;
1458:   }
1459:   if (G) {
1461:     linesearch->vec_func_new = G;
1462:   }
1463:   return 0;
1464: }

1466: /*@C
1467:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1468:    `SNESLineSearch` options in the database.

1470:    Logically Collective on linesearch

1472:    Input Parameters:
1473: +  linesearch - the `SNESLineSearch` context
1474: -  prefix - the prefix to prepend to all option names

1476:    Note:
1477:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1478:    The first character of all runtime options is AUTOMATICALLY the hyphen.

1480:    Level: advanced

1482: .seealso: `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1483: @*/
1484: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1485: {
1487:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix);
1488:   return 0;
1489: }

1491: /*@C
1492:    SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1493:    SNESLineSearch options in the database.

1495:    Not Collective

1497:    Input Parameter:
1498: .  linesearch - the `SNESLineSearch` context

1500:    Output Parameter:
1501: .  prefix - pointer to the prefix string used

1503:    Fortran Note:
1504:    On the fortran side, the user should pass in a string 'prefix' of
1505:    sufficient length to hold the prefix.

1507:    Level: advanced

1509: .seealso: `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1510: @*/
1511: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1512: {
1514:   PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix);
1515:   return 0;
1516: }

1518: /*@C
1519:    SNESLineSearchSetWorkVecs - Sets work vectors for the line search.

1521:    Input Parameters:
1522: +  linesearch - the `SNESLineSearch` context
1523: -  nwork - the number of work vectors

1525:    Level: developer

1527: .seealso: `SNESLineSearch`, `SNESSetWorkVecs()`
1528: @*/
1529: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1530: {
1531:   if (linesearch->vec_sol) {
1532:     VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
1533:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1534:   return 0;
1535: }

1537: /*@
1538:    SNESLineSearchGetReason - Gets the success/failure status of the last line search application

1540:    Input Parameters:
1541: .  linesearch - linesearch context

1543:    Output Parameters:
1544: .  result - The success or failure status

1546:    Note:
1547:    This is typically called after `SNESLineSearchApply()` in order to determine if the line-search failed
1548:    (and set the SNES convergence accordingly).

1550:    Level: developer

1552: .seealso: `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1553: @*/
1554: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1555: {
1558:   *result = linesearch->result;
1559:   return 0;
1560: }

1562: /*@
1563:    SNESLineSearchSetReason - Sets the success/failure status of the last line search application

1565:    Input Parameters:
1566: +  linesearch - linesearch context
1567: -  result - The success or failure status

1569:    Note:
1570:    This is typically called in a `SNESLineSearchApply()` or a `SNESLINESEARCHSHELL` implementation to set
1571:    the success or failure of the line search method.

1573:    Level: developer

1575: .seealso: `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`
1576: @*/
1577: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1578: {
1580:   linesearch->result = result;
1581:   return 0;
1582: }

1584: /*@C
1585:    SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.

1587:    Logically Collective on linesearch

1589:    Input Parameters:
1590: +  snes - nonlinear context obtained from `SNESCreate()`
1591: .  projectfunc - function for projecting the function to the bounds
1592: -  normfunc - function for computing the norm of an active set

1594:    Calling sequence of projectfunc:
1595: .vb
1596:    projectfunc (SNES snes, Vec X)
1597: .ve

1599:     Input parameters for projectfunc:
1600: +   snes - nonlinear context
1601: -   X - current solution

1603:     Output parameter for projectfunc:
1604: .   X - Projected solution

1606:    Calling sequence of normfunc:
1607: .vb
1608:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
1609: .ve

1611:     Input parameters for normfunc:
1612: +   snes - nonlinear context
1613: .   X - current solution
1614: -   F - current residual

1616:     Output parameter for normfunc:
1617: .   fnorm - VI-specific norm of the function

1619:     Note:
1620:     The VI solvers require projection of the solution to the feasible set.  projectfunc should implement this.

1622:     The VI solvers require special evaluation of the function norm such that the norm is only calculated
1623:     on the inactive set.  This should be implemented by normfunc.

1625:     Level: advanced

1627: .seealso: `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`
1628: @*/
1629: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
1630: {
1632:   if (projectfunc) linesearch->ops->viproject = projectfunc;
1633:   if (normfunc) linesearch->ops->vinorm = normfunc;
1634:   return 0;
1635: }

1637: /*@C
1638:    SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.

1640:    Not Collective

1642:    Input Parameter:
1643: .  linesearch - the line search context, obtain with `SNESGetLineSearch()`

1645:    Output Parameters:
1646: +  projectfunc - function for projecting the function to the bounds
1647: -  normfunc - function for computing the norm of an active set

1649:     Level: advanced

1651: .seealso: `SNESLineSearch`, `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`
1652: @*/
1653: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
1654: {
1655:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
1656:   if (normfunc) *normfunc = linesearch->ops->vinorm;
1657:   return 0;
1658: }

1660: /*@C
1661:   SNESLineSearchRegister - register a line search method

1663:   Level: advanced

1665: .seealso: `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1666: @*/
1667: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch))
1668: {
1669:   SNESInitializePackage();
1670:   PetscFunctionListAdd(&SNESLineSearchList, sname, function);
1671:   return 0;
1672: }