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

 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;

 36:   PetscFunctionBegin;
 38:   for (i = 0; i < ls->numbermonitors; i++) {
 39:     if (ls->monitordestroy[i]) PetscCall((*ls->monitordestroy[i])(&ls->monitorcontext[i]));
 40:   }
 41:   ls->numbermonitors = 0;
 42:   PetscFunctionReturn(PETSC_SUCCESS);
 43: }

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

 48:    Collective

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

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

 57:    Level: developer

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

 65:   PetscFunctionBegin;
 66:   for (i = 0; i < n; i++) PetscCall((*ls->monitorftns[i])(ls, ls->monitorcontext[i]));
 67:   PetscFunctionReturn(PETSC_SUCCESS);
 68: }

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

 75:    Logically Collective

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

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

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

 93:    Level: intermediate

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

102:   PetscFunctionBegin;
104:   for (i = 0; i < ls->numbermonitors; i++) {
105:     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))ls->monitorftns[i], ls->monitorcontext[i], ls->monitordestroy[i], &identical));
106:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
107:   }
108:   PetscCheck(ls->numbermonitors < MAXSNESLSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
109:   ls->monitorftns[ls->numbermonitors]      = f;
110:   ls->monitordestroy[ls->numbermonitors]   = monitordestroy;
111:   ls->monitorcontext[ls->numbermonitors++] = (void *)mctx;
112:   PetscFunctionReturn(PETSC_SUCCESS);
113: }

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

118:    Collective

120:    Input Parameters:
121: +  ls - the `SNES` linesearch object
122: -  vf - the context for the monitor, in this case it is an `PetscViewerAndFormat`

124:    Level: intermediate

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

133:   PetscFunctionBegin;
134:   PetscCall(SNESLineSearchGetVecs(ls, NULL, NULL, &Y, &W, &G));
135:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
136:   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted update to solution \n"));
137:   PetscCall(VecView(Y, viewer));
138:   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted new solution \n"));
139:   PetscCall(VecView(W, viewer));
140:   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted updated function value\n"));
141:   PetscCall(VecView(G, viewer));
142:   PetscCall(PetscViewerPopFormat(viewer));
143:   PetscFunctionReturn(PETSC_SUCCESS);
144: }

146: /*@
147:    SNESLineSearchCreate - Creates the line search context.

149:    Logically Collective

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

154:    Output Parameters:
155: .  outlinesearch - the new linesearch context

157:    Level: developer

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

163: .seealso: `SNESLineSearch`, `LineSearchDestroy()`, `SNESGetLineSearch()`
164: @*/
165: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
166: {
167:   SNESLineSearch linesearch;

169:   PetscFunctionBegin;
171:   PetscCall(SNESInitializePackage());
172:   *outlinesearch = NULL;

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

176:   linesearch->vec_sol_new  = NULL;
177:   linesearch->vec_func_new = NULL;
178:   linesearch->vec_sol      = NULL;
179:   linesearch->vec_func     = NULL;
180:   linesearch->vec_update   = NULL;

182:   linesearch->lambda       = 1.0;
183:   linesearch->fnorm        = 1.0;
184:   linesearch->ynorm        = 1.0;
185:   linesearch->xnorm        = 1.0;
186:   linesearch->result       = SNES_LINESEARCH_SUCCEEDED;
187:   linesearch->norms        = PETSC_TRUE;
188:   linesearch->keeplambda   = PETSC_FALSE;
189:   linesearch->damping      = 1.0;
190:   linesearch->maxstep      = 1e8;
191:   linesearch->steptol      = 1e-12;
192:   linesearch->rtol         = 1e-8;
193:   linesearch->atol         = 1e-15;
194:   linesearch->ltol         = 1e-8;
195:   linesearch->precheckctx  = NULL;
196:   linesearch->postcheckctx = NULL;
197:   linesearch->max_its      = 1;
198:   linesearch->setupcalled  = PETSC_FALSE;
199:   linesearch->monitor      = NULL;
200:   *outlinesearch           = linesearch;
201:   PetscFunctionReturn(PETSC_SUCCESS);
202: }

204: /*@
205:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
206:    any required vectors.

208:    Collective

210:    Input Parameters:
211: .  linesearch - The `SNESLineSearch` instance.

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

220:    Level: advanced

222: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchReset()`
223: @*/

225: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
226: {
227:   PetscFunctionBegin;
228:   if (!((PetscObject)linesearch)->type_name) PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC));
229:   if (!linesearch->setupcalled) {
230:     if (!linesearch->vec_sol_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new));
231:     if (!linesearch->vec_func_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new));
232:     if (linesearch->ops->setup) PetscUseTypeMethod(linesearch, setup);
233:     if (!linesearch->ops->snesfunc) PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunction));
234:     linesearch->lambda      = linesearch->damping;
235:     linesearch->setupcalled = PETSC_TRUE;
236:   }
237:   PetscFunctionReturn(PETSC_SUCCESS);
238: }

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

243:    Collective

245:    Input Parameters:
246: .  linesearch - The `SNESLineSearch` instance.

248:    Note:
249:     Usually only called by `SNESReset()`

251:    Level: developer

253: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetUp()`
254: @*/

256: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
257: {
258:   PetscFunctionBegin;
259:   if (linesearch->ops->reset) PetscUseTypeMethod(linesearch, reset);

261:   PetscCall(VecDestroy(&linesearch->vec_sol_new));
262:   PetscCall(VecDestroy(&linesearch->vec_func_new));

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

266:   linesearch->nwork       = 0;
267:   linesearch->setupcalled = PETSC_FALSE;
268:   PetscFunctionReturn(PETSC_SUCCESS);
269: }

271: /*@C
272:    SNESLineSearchSetFunction - Sets the function evaluation used by the `SNES` line search
273: `
274:    Input Parameters:
275: .  linesearch - the `SNESLineSearch` context
276: +  func       - function evaluation routine, this is usually the function provided with `SNESSetFunction()`

278:    Level: developer

280: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESSetFunction()`
281: @*/
282: PetscErrorCode SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES, Vec, Vec))
283: {
284:   PetscFunctionBegin;
286:   linesearch->ops->snesfunc = func;
287:   PetscFunctionReturn(PETSC_SUCCESS);
288: }

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

295:    Logically Collective

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

302:    Level: intermediate

304:    Note:
305:    Use `SNESLineSearchSetPostCheck()` to change the step after the line search.
306:    search is complete.

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

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

313: @*/
314: PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void *ctx)
315: {
316:   PetscFunctionBegin;
318:   if (func) linesearch->ops->precheck = func;
319:   if (ctx) linesearch->precheckctx = ctx;
320:   PetscFunctionReturn(PETSC_SUCCESS);
321: }

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

326:    Input Parameter:
327: .  linesearch - the `SNESLineSearch` context

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

333:    Level: intermediate

335: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
336: @*/
337: PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void **ctx)
338: {
339:   PetscFunctionBegin;
341:   if (func) *func = linesearch->ops->precheck;
342:   if (ctx) *ctx = linesearch->precheckctx;
343:   PetscFunctionReturn(PETSC_SUCCESS);
344: }

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

350:    Logically Collective linesearch

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

357:    Level: intermediate

359:    Notes:
360:    Use `SNESLineSearchSetPreCheck()` to change the step before the line search.
361:    search is complete.

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

365: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
366:           `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()
367: @*/
368: PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void *ctx)
369: {
370:   PetscFunctionBegin;
372:   if (func) linesearch->ops->postcheck = func;
373:   if (ctx) linesearch->postcheckctx = ctx;
374:   PetscFunctionReturn(PETSC_SUCCESS);
375: }

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

380:    Input Parameter:
381: .  linesearch - the `SNESLineSearch` context

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

387:    Level: intermediate

389: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
390: @*/
391: PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void **ctx)
392: {
393:   PetscFunctionBegin;
395:   if (func) *func = linesearch->ops->postcheck;
396:   if (ctx) *ctx = linesearch->postcheckctx;
397:   PetscFunctionReturn(PETSC_SUCCESS);
398: }

400: /*@
401:    SNESLineSearchPreCheck - Prepares the line search for being applied.

403:    Logically Collective

405:    Input Parameters:
406: +  linesearch - The linesearch instance.
407: .  X - The current solution
408: -  Y - The step direction

410:    Output Parameters:
411: .  changed - Indicator that the precheck routine has changed anything

413:    Level: advanced

415:    Note:
416:    This calls any function provided with `SNESLineSearchSetPreCheck()`

418: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
419:           `SNESLineSearchGetPostCheck()``
420: @*/
421: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed)
422: {
423:   PetscFunctionBegin;
424:   *changed = PETSC_FALSE;
425:   if (linesearch->ops->precheck) {
426:     PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
428:   }
429:   PetscFunctionReturn(PETSC_SUCCESS);
430: }

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

435:    Logically Collective

437:    Input Parameters:
438: +  linesearch - The linesearch context
439: .  X - The last solution
440: .  Y - The step direction
441: -  W - The updated solution, W = X + lambda*Y for some lambda

443:    Output Parameters:
444: +  changed_Y - Indicator if the direction Y has been changed.
445: -  changed_W - Indicator if the new candidate solution W has been changed.

447:    Note:
448:    This calls any function provided with `SNESLineSearchSetPreCheck()`

450:    Level: developer

452: .seealso: `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
453: @*/
454: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W)
455: {
456:   PetscFunctionBegin;
457:   *changed_Y = PETSC_FALSE;
458:   *changed_W = PETSC_FALSE;
459:   if (linesearch->ops->postcheck) {
460:     PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
463:   }
464:   PetscFunctionReturn(PETSC_SUCCESS);
465: }

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

470:    Logically Collective

472:    Input Parameters:
473: +  linesearch - linesearch context
474: .  X - base state for this step
475: -  ctx - context for this function

477:    Input/Output Parameter:
478: .  Y - correction, possibly modified

480:    Output Parameter:
481: .  changed - flag indicating that Y was modified

483:    Options Database Key:
484: +  -snes_linesearch_precheck_picard - activate this routine
485: -  -snes_linesearch_precheck_picard_angle - angle

487:    Level: advanced

489:    Notes:
490:    This function should be passed to `SNESLineSearchSetPreCheck()`

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

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

499: .seealso: `SNESLineSearch`, `SNESSetPicard()`, `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`
500: @*/
501: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, void *ctx)
502: {
503:   PetscReal   angle = *(PetscReal *)linesearch->precheckctx;
504:   Vec         Ylast;
505:   PetscScalar dot;
506:   PetscInt    iter;
507:   PetscReal   ynorm, ylastnorm, theta, angle_radians;
508:   SNES        snes;

510:   PetscFunctionBegin;
511:   PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
512:   PetscCall(PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast));
513:   if (!Ylast) {
514:     PetscCall(VecDuplicate(Y, &Ylast));
515:     PetscCall(PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast));
516:     PetscCall(PetscObjectDereference((PetscObject)Ylast));
517:   }
518:   PetscCall(SNESGetIterationNumber(snes, &iter));
519:   if (iter < 2) {
520:     PetscCall(VecCopy(Y, Ylast));
521:     *changed = PETSC_FALSE;
522:     PetscFunctionReturn(PETSC_SUCCESS);
523:   }

525:   PetscCall(VecDot(Y, Ylast, &dot));
526:   PetscCall(VecNorm(Y, NORM_2, &ynorm));
527:   PetscCall(VecNorm(Ylast, NORM_2, &ylastnorm));
528:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
529:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
530:   angle_radians = angle * PETSC_PI / 180.;
531:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
532:     /* Modify the step Y */
533:     PetscReal alpha, ydiffnorm;
534:     PetscCall(VecAXPY(Ylast, -1.0, Y));
535:     PetscCall(VecNorm(Ylast, NORM_2, &ydiffnorm));
536:     alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
537:     PetscCall(VecCopy(Y, Ylast));
538:     PetscCall(VecScale(Y, alpha));
539:     PetscCall(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));
540:     *changed = PETSC_TRUE;
541:   } else {
542:     PetscCall(PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180. / PETSC_PI), (double)angle));
543:     PetscCall(VecCopy(Y, Ylast));
544:     *changed = PETSC_FALSE;
545:   }
546:   PetscFunctionReturn(PETSC_SUCCESS);
547: }

549: /*@
550:    SNESLineSearchApply - Computes the line-search update.

552:    Collective

554:    Input Parameters:
555: +  linesearch - The linesearch context
556: -  Y - The search direction

558:    Input/Output Parameters:
559: +  X - The current solution, on output the new solution
560: .  F - The current function, on output the new function
561: -  fnorm - The current norm, on output the new function norm

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

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

579:    Level: Intermediate

581: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
582:           `SNESLineSearchType`, `SNESLineSearchSetType()`
583: @*/
584: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y)
585: {
586:   PetscFunctionBegin;

592:   linesearch->result = SNES_LINESEARCH_SUCCEEDED;

594:   linesearch->vec_sol    = X;
595:   linesearch->vec_update = Y;
596:   linesearch->vec_func   = F;

598:   PetscCall(SNESLineSearchSetUp(linesearch));

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

602:   if (fnorm) linesearch->fnorm = *fnorm;
603:   else PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm));

605:   PetscCall(PetscLogEventBegin(SNESLINESEARCH_Apply, linesearch, X, F, Y));

607:   PetscUseTypeMethod(linesearch, apply);

609:   PetscCall(PetscLogEventEnd(SNESLINESEARCH_Apply, linesearch, X, F, Y));

611:   if (fnorm) *fnorm = linesearch->fnorm;
612:   PetscFunctionReturn(PETSC_SUCCESS);
613: }

615: /*@
616:    SNESLineSearchDestroy - Destroys the line search instance.

618:    Collective

620:    Input Parameters:
621: .  linesearch - The linesearch context

623:    Level: developer

625: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
626: @*/
627: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch)
628: {
629:   PetscFunctionBegin;
630:   if (!*linesearch) PetscFunctionReturn(PETSC_SUCCESS);
632:   if (--((PetscObject)(*linesearch))->refct > 0) {
633:     *linesearch = NULL;
634:     PetscFunctionReturn(PETSC_SUCCESS);
635:   }
636:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*linesearch));
637:   PetscCall(SNESLineSearchReset(*linesearch));
638:   PetscTryTypeMethod(*linesearch, destroy);
639:   PetscCall(PetscViewerDestroy(&(*linesearch)->monitor));
640:   PetscCall(SNESLineSearchMonitorCancel((*linesearch)));
641:   PetscCall(PetscHeaderDestroy(linesearch));
642:   PetscFunctionReturn(PETSC_SUCCESS);
643: }

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

648:    Logically Collective

650:    Input Parameters:
651: +  linesearch - the linesearch object
652: -  viewer - an `PETSCVIEWERASCII` `PetscViewer` or NULL to turn off monitor

654:    Options Database Key:
655: .   -snes_linesearch_monitor [:filename] - enables the monitor

657:    Level: intermediate

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

664: .seealso: `SNESLineSearch`, `PETSCVIEWERASCII`, `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`,
665:           `SNESLineSearchMonitorSetFromOptions()`
666: @*/
667: PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
668: {
669:   PetscFunctionBegin;
670:   if (viewer) PetscCall(PetscObjectReference((PetscObject)viewer));
671:   PetscCall(PetscViewerDestroy(&linesearch->monitor));
672:   linesearch->monitor = viewer;
673:   PetscFunctionReturn(PETSC_SUCCESS);
674: }

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

679:    Logically Collective

681:    Input Parameter:
682: .  linesearch - linesearch context

684:    Output Parameter:
685: .  monitor - monitor context

687:    Level: intermediate

689: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
690: @*/
691: PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
692: {
693:   PetscFunctionBegin;
695:   *monitor = linesearch->monitor;
696:   PetscFunctionReturn(PETSC_SUCCESS);
697: }

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

702:    Collective

704:    Input Parameters:
705: +  ls - `SNESLineSearch` object you wish to monitor
706: .  name - the monitor type one is seeking
707: .  help - message indicating what monitoring is done
708: .  manual - manual page for the monitor
709: .  monitor - the monitor function
710: -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNESLineSearch` or `PetscViewer`

712:    Level: developer

714: .seealso: `SNESLineSearch`, `SNESLineSearchSetMonitor()`, `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
715:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
716:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
717:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
718:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
719:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
720:           `PetscOptionsFList()`, `PetscOptionsEList()`
721: @*/
722: PetscErrorCode SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNESLineSearch, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(SNESLineSearch, PetscViewerAndFormat *))
723: {
724:   PetscViewer       viewer;
725:   PetscViewerFormat format;
726:   PetscBool         flg;

728:   PetscFunctionBegin;
729:   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg));
730:   if (flg) {
731:     PetscViewerAndFormat *vf;
732:     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
733:     PetscCall(PetscObjectDereference((PetscObject)viewer));
734:     if (monitorsetup) PetscCall((*monitorsetup)(ls, vf));
735:     PetscCall(SNESLineSearchMonitorSet(ls, (PetscErrorCode(*)(SNESLineSearch, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
736:   }
737:   PetscFunctionReturn(PETSC_SUCCESS);
738: }

740: /*@
741:    SNESLineSearchSetFromOptions - Sets options for the line search

743:    Logically Collective

745:    Input Parameter:
746: .  linesearch - linesearch context

748:    Options Database Keys:
749: + -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
750: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
751: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch typem (`SNESLineSearchSetComputeNorms()`)
752: . -snes_linesearch_minlambda - The minimum step length
753: . -snes_linesearch_maxstep - The maximum step size
754: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
755: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
756: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
757: . -snes_linesearch_max_it - The number of iterations for iterative line searches
758: . -snes_linesearch_monitor [:filename] - Print progress of line searches
759: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
760: . -snes_linesearch_damping - The linesearch damping parameter
761: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
762: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
763: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method

765:    Level: intermediate

767: .seealso: `SNESLineSearch`, `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
768:           `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
769: @*/
770: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
771: {
772:   const char *deft = SNESLINESEARCHBASIC;
773:   char        type[256];
774:   PetscBool   flg, set;
775:   PetscViewer viewer;

777:   PetscFunctionBegin;
778:   PetscCall(SNESLineSearchRegisterAll());

780:   PetscObjectOptionsBegin((PetscObject)linesearch);
781:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
782:   PetscCall(PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg));
783:   if (flg) {
784:     PetscCall(SNESLineSearchSetType(linesearch, type));
785:   } else if (!((PetscObject)linesearch)->type_name) {
786:     PetscCall(SNESLineSearchSetType(linesearch, deft));
787:   }

789:   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set));
790:   if (set) {
791:     PetscCall(SNESLineSearchSetDefaultMonitor(linesearch, viewer));
792:     PetscCall(PetscViewerDestroy(&viewer));
793:   }
794:   PetscCall(SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL));

796:   /* tolerances */
797:   PetscCall(PetscOptionsReal("-snes_linesearch_minlambda", "Minimum step length", "SNESLineSearchSetTolerances", linesearch->steptol, &linesearch->steptol, NULL));
798:   PetscCall(PetscOptionsReal("-snes_linesearch_maxstep", "Maximum step size", "SNESLineSearchSetTolerances", linesearch->maxstep, &linesearch->maxstep, NULL));
799:   PetscCall(PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL));
800:   PetscCall(PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL));
801:   PetscCall(PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL));
802:   PetscCall(PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_its, &linesearch->max_its, NULL));

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

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

809:   /* precheck */
810:   PetscCall(PetscOptionsBool("-snes_linesearch_precheck_picard", "Use a correction that sometimes improves convergence of Picard iteration", "SNESLineSearchPreCheckPicard", flg, &flg, &set));
811:   if (set) {
812:     if (flg) {
813:       linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */

815:       PetscCall(PetscOptionsReal("-snes_linesearch_precheck_picard_angle", "Maximum angle at which to activate the correction", "none", linesearch->precheck_picard_angle, &linesearch->precheck_picard_angle, NULL));
816:       PetscCall(SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle));
817:     } else {
818:       PetscCall(SNESLineSearchSetPreCheck(linesearch, NULL, NULL));
819:     }
820:   }
821:   PetscCall(PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL));
822:   PetscCall(PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL));

824:   PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);

826:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject));
827:   PetscOptionsEnd();
828:   PetscFunctionReturn(PETSC_SUCCESS);
829: }

831: /*@
832:    SNESLineSearchView - Prints useful information about the line search

834:    Input Parameters:
835: .  linesearch - linesearch context

837:    Logically Collective

839:    Level: intermediate

841: .seealso: `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`
842: @*/
843: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
844: {
845:   PetscBool iascii;

847:   PetscFunctionBegin;
849:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer));
851:   PetscCheckSameComm(linesearch, 1, viewer, 2);

853:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
854:   if (iascii) {
855:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer));
856:     PetscCall(PetscViewerASCIIPushTab(viewer));
857:     PetscTryTypeMethod(linesearch, view, viewer);
858:     PetscCall(PetscViewerASCIIPopTab(viewer));
859:     PetscCall(PetscViewerASCIIPrintf(viewer, "  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep, (double)linesearch->steptol));
860:     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol));
861:     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT "\n", linesearch->max_its));
862:     if (linesearch->ops->precheck) {
863:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
864:         PetscCall(PetscViewerASCIIPrintf(viewer, "  using precheck step to speed up Picard convergence\n"));
865:       } else {
866:         PetscCall(PetscViewerASCIIPrintf(viewer, "  using user-defined precheck step\n"));
867:       }
868:     }
869:     if (linesearch->ops->postcheck) PetscCall(PetscViewerASCIIPrintf(viewer, "  using user-defined postcheck step\n"));
870:   }
871:   PetscFunctionReturn(PETSC_SUCCESS);
872: }

874: /*@C
875:    SNESLineSearchGetType - Gets the linesearch type

877:    Logically Collective

879:    Input Parameters:
880: .  linesearch - linesearch context

882:    Output Parameters:
883: -  type - The type of line search, or NULL if not set

885:    Level: intermediate

887: .seealso: `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
888: @*/
889: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
890: {
891:   PetscFunctionBegin;
894:   *type = ((PetscObject)linesearch)->type_name;
895:   PetscFunctionReturn(PETSC_SUCCESS);
896: }

898: /*@C
899:    SNESLineSearchSetType - Sets the linesearch type

901:    Logically Collective

903:    Input Parameters:
904: +  linesearch - linesearch context
905: -  type - The type of line search to be used

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

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

918:    Level: intermediate

920: .seealso:  `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`
921: @*/
922: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
923: {
924:   PetscBool match;
925:   PetscErrorCode (*r)(SNESLineSearch);

927:   PetscFunctionBegin;

931:   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, type, &match));
932:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

934:   PetscCall(PetscFunctionListFind(SNESLineSearchList, type, &r));
935:   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Line Search type %s", type);
936:   /* Destroy the previous private linesearch context */
937:   if (linesearch->ops->destroy) {
938:     PetscCall((*(linesearch)->ops->destroy)(linesearch));
939:     linesearch->ops->destroy = NULL;
940:   }
941:   /* Reinitialize function pointers in SNESLineSearchOps structure */
942:   linesearch->ops->apply          = NULL;
943:   linesearch->ops->view           = NULL;
944:   linesearch->ops->setfromoptions = NULL;
945:   linesearch->ops->destroy        = NULL;

947:   PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch, type));
948:   PetscCall((*r)(linesearch));
949:   PetscFunctionReturn(PETSC_SUCCESS);
950: }

952: /*@
953:    SNESLineSearchSetSNES - Sets the `SNES` for the linesearch for function evaluation.

955:    Input Parameters:
956: +  linesearch - linesearch context
957: -  snes - The snes instance

959:    Level: developer

961:    Note:
962:    This happens automatically when the line search is obtained/created with
963:    `SNESGetLineSearch()`.  This routine is therefore mainly called within `SNES`
964:    implementations.

966:    Level: developer

968: .seealso: `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
969: @*/
970: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
971: {
972:   PetscFunctionBegin;
975:   linesearch->snes = snes;
976:   PetscFunctionReturn(PETSC_SUCCESS);
977: }

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

985:    Not Collective

987:    Input Parameters:
988: .  linesearch - linesearch context

990:    Output Parameters:
991: .  snes - The snes instance

993:    Level: developer

995: .seealso: `SNESLineSearch`, `SNESType`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
996: @*/
997: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
998: {
999:   PetscFunctionBegin;
1002:   *snes = linesearch->snes;
1003:   PetscFunctionReturn(PETSC_SUCCESS);
1004: }

1006: /*@
1007:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

1009:    Not Collective

1011:    Input Parameters:
1012: .  linesearch - linesearch context

1014:    Output Parameters:
1015: .  lambda - The last steplength computed during `SNESLineSearchApply()`

1017:    Level: advanced

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

1025: .seealso: `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1026: @*/
1027: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1028: {
1029:   PetscFunctionBegin;
1032:   *lambda = linesearch->lambda;
1033:   PetscFunctionReturn(PETSC_SUCCESS);
1034: }

1036: /*@
1037:    SNESLineSearchSetLambda - Sets the linesearch steplength

1039:    Input Parameters:
1040: +  linesearch - linesearch context
1041: -  lambda - The last steplength.

1043:    Note:
1044:    This routine is typically used within implementations of `SNESLineSearchApply()`
1045:    to set the final steplength.  This routine (and `SNESLineSearchGetLambda()`) were
1046:    added in order to facilitate Quasi-Newton methods that use the previous steplength
1047:    as an inner scaling parameter.

1049:    Level: advanced

1051: .seealso: `SNESLineSearch`, `SNESLineSearchGetLambda()`
1052: @*/
1053: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1054: {
1055:   PetscFunctionBegin;
1057:   linesearch->lambda = lambda;
1058:   PetscFunctionReturn(PETSC_SUCCESS);
1059: }

1061: /*@
1062:    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
1063:    tolerances for the relative and absolute change in the function norm, the change
1064:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1065:    and the maximum number of iterations the line search procedure may take.

1067:    Not Collective

1069:    Input Parameter:
1070: .  linesearch - linesearch context

1072:    Output Parameters:
1073: +  steptol - The minimum steplength
1074: .  maxstep - The maximum steplength
1075: .  rtol    - The relative tolerance for iterative line searches
1076: .  atol    - The absolute tolerance for iterative line searches
1077: .  ltol    - The change in lambda tolerance for iterative line searches
1078: -  max_it  - The maximum number of iterations of the line search

1080:    Level: intermediate

1082:    Note:
1083:    Different line searches may implement these parameters slightly differently as
1084:    the type requires.

1086: .seealso: `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1087: @*/
1088: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *steptol, PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1089: {
1090:   PetscFunctionBegin;
1092:   if (steptol) {
1094:     *steptol = linesearch->steptol;
1095:   }
1096:   if (maxstep) {
1098:     *maxstep = linesearch->maxstep;
1099:   }
1100:   if (rtol) {
1102:     *rtol = linesearch->rtol;
1103:   }
1104:   if (atol) {
1106:     *atol = linesearch->atol;
1107:   }
1108:   if (ltol) {
1110:     *ltol = linesearch->ltol;
1111:   }
1112:   if (max_its) {
1114:     *max_its = linesearch->max_its;
1115:   }
1116:   PetscFunctionReturn(PETSC_SUCCESS);
1117: }

1119: /*@
1120:    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
1121:    tolerances for the relative and absolute change in the function norm, the change
1122:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1123:    and the maximum number of iterations the line search procedure may take.

1125:    Collective

1127:    Input Parameters:
1128: +  linesearch - linesearch context
1129: .  steptol - The minimum steplength
1130: .  maxstep - The maximum steplength
1131: .  rtol    - The relative tolerance for iterative line searches
1132: .  atol    - The absolute tolerance for iterative line searches
1133: .  ltol    - The change in lambda tolerance for iterative line searches
1134: -  max_it  - The maximum number of iterations of the line search

1136:    Note:
1137:    The user may choose to not set any of the tolerances using `PETSC_DEFAULT` in
1138:    place of an argument.

1140:    Level: intermediate

1142: .seealso: `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1143: @*/
1144: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal steptol, PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
1145: {
1146:   PetscFunctionBegin;

1155:   if (steptol != PETSC_DEFAULT) {
1156:     PetscCheck(steptol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum step length %14.12e must be non-negative", (double)steptol);
1157:     linesearch->steptol = steptol;
1158:   }

1160:   if (maxstep != PETSC_DEFAULT) {
1161:     PetscCheck(maxstep >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum step length %14.12e must be non-negative", (double)maxstep);
1162:     linesearch->maxstep = maxstep;
1163:   }

1165:   if (rtol != PETSC_DEFAULT) {
1166:     PetscCheck(rtol >= 0.0 && rtol < 1.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %14.12e must be non-negative and less than 1.0", (double)rtol);
1167:     linesearch->rtol = rtol;
1168:   }

1170:   if (atol != PETSC_DEFAULT) {
1171:     PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %14.12e must be non-negative", (double)atol);
1172:     linesearch->atol = atol;
1173:   }

1175:   if (ltol != PETSC_DEFAULT) {
1176:     PetscCheck(ltol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Lambda tolerance %14.12e must be non-negative", (double)ltol);
1177:     linesearch->ltol = ltol;
1178:   }

1180:   if (max_its != PETSC_DEFAULT) {
1181:     PetscCheck(max_its >= 0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", max_its);
1182:     linesearch->max_its = max_its;
1183:   }
1184:   PetscFunctionReturn(PETSC_SUCCESS);
1185: }

1187: /*@
1188:    SNESLineSearchGetDamping - Gets the line search damping parameter.

1190:    Input Parameters:
1191: .  linesearch - linesearch context

1193:    Output Parameters:
1194: .  damping - The damping parameter

1196:    Level: advanced

1198: .seealso: `SNESLineSearchGetStepTolerance()`, `SNESQN`
1199: @*/

1201: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1202: {
1203:   PetscFunctionBegin;
1206:   *damping = linesearch->damping;
1207:   PetscFunctionReturn(PETSC_SUCCESS);
1208: }

1210: /*@
1211:    SNESLineSearchSetDamping - Sets the line search damping parameter.

1213:    Input Parameters:
1214: +  linesearch - linesearch context
1215: -  damping - The damping parameter

1217:    Options Database Key:
1218: .   -snes_linesearch_damping <damping> - the damping value

1220:    Level: intermediate

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

1229: .seealso: `SNESLineSearch`, `SNESLineSearchGetDamping()`
1230: @*/
1231: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1232: {
1233:   PetscFunctionBegin;
1235:   linesearch->damping = damping;
1236:   PetscFunctionReturn(PETSC_SUCCESS);
1237: }

1239: /*@
1240:    SNESLineSearchGetOrder - Gets the line search approximation order.

1242:    Input Parameter:
1243: .  linesearch - linesearch context

1245:    Output Parameter:
1246: .  order - The order

1248:    Possible Values for order:
1249: +  1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1250: .  2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1251: -  3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order

1253:    Level: intermediate

1255: .seealso: `SNESLineSearch`, `SNESLineSearchSetOrder()`
1256: @*/

1258: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1259: {
1260:   PetscFunctionBegin;
1263:   *order = linesearch->order;
1264:   PetscFunctionReturn(PETSC_SUCCESS);
1265: }

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

1270:    Input Parameters:
1271: +  linesearch - linesearch context
1272: -  order - The damping parameter

1274:    Level: intermediate

1276:    Possible Values for order:
1277: +  1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1278: .  2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1279: -  3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order

1281:    Notes:
1282:    Variable orders are supported by the following line searches:
1283: +  bt - cubic and quadratic
1284: -  cp - linear and quadratic

1286: .seealso: `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1287: @*/
1288: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1289: {
1290:   PetscFunctionBegin;
1292:   linesearch->order = order;
1293:   PetscFunctionReturn(PETSC_SUCCESS);
1294: }

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

1299:    Not Collective

1301:    Input Parameter:
1302: .  linesearch - linesearch context

1304:    Output Parameters:
1305: +  xnorm - The norm of the current solution
1306: .  fnorm - The norm of the current function
1307: -  ynorm - The norm of the current update

1309:    Level: developer

1311: .seealso: `SNESLineSearch`, `SNESLineSearchSetNorms()` `SNESLineSearchGetVecs()`
1312: @*/
1313: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1314: {
1315:   PetscFunctionBegin;
1317:   if (xnorm) *xnorm = linesearch->xnorm;
1318:   if (fnorm) *fnorm = linesearch->fnorm;
1319:   if (ynorm) *ynorm = linesearch->ynorm;
1320:   PetscFunctionReturn(PETSC_SUCCESS);
1321: }

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

1326:    Collective

1328:    Input Parameters:
1329: +  linesearch - linesearch context
1330: .  xnorm - The norm of the current solution
1331: .  fnorm - The norm of the current function
1332: -  ynorm - The norm of the current update

1334:    Level: developer

1336: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1337: @*/
1338: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1339: {
1340:   PetscFunctionBegin;
1342:   linesearch->xnorm = xnorm;
1343:   linesearch->fnorm = fnorm;
1344:   linesearch->ynorm = ynorm;
1345:   PetscFunctionReturn(PETSC_SUCCESS);
1346: }

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

1351:    Input Parameters:
1352: .  linesearch - linesearch context

1354:    Options Database Keys:
1355: .   -snes_linesearch_norms - turn norm computation on or off

1357:    Level: intermediate

1359: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1360: @*/
1361: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1362: {
1363:   SNES snes;

1365:   PetscFunctionBegin;
1366:   if (linesearch->norms) {
1367:     if (linesearch->ops->vinorm) {
1368:       PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1369:       PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1370:       PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1371:       PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1372:     } else {
1373:       PetscCall(VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1374:       PetscCall(VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1375:       PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1376:       PetscCall(VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1377:       PetscCall(VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1378:       PetscCall(VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1379:     }
1380:   }
1381:   PetscFunctionReturn(PETSC_SUCCESS);
1382: }

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

1387:    Input Parameters:
1388: +  linesearch  - linesearch context
1389: -  flg  - indicates whether or not to compute norms

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

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

1397:    Level: intermediate

1399: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1400: @*/
1401: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1402: {
1403:   PetscFunctionBegin;
1404:   linesearch->norms = flg;
1405:   PetscFunctionReturn(PETSC_SUCCESS);
1406: }

1408: /*@
1409:    SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context

1411:    Not Collective on but the vectors are parallel

1413:    Input Parameter:
1414: .  linesearch - linesearch context

1416:    Output Parameters:
1417: +  X - Solution vector
1418: .  F - Function vector
1419: .  Y - Search direction vector
1420: .  W - Solution work vector
1421: -  G - Function work vector

1423:    Notes:
1424:    At the beginning of a line search application, X should contain a
1425:    solution and the vector F the function computed at X.  At the end of the
1426:    line search application, X should contain the new solution, and F the
1427:    function evaluated at the new solution.

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

1431:    Level: advanced

1433: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1434: @*/
1435: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1436: {
1437:   PetscFunctionBegin;
1439:   if (X) {
1441:     *X = linesearch->vec_sol;
1442:   }
1443:   if (F) {
1445:     *F = linesearch->vec_func;
1446:   }
1447:   if (Y) {
1449:     *Y = linesearch->vec_update;
1450:   }
1451:   if (W) {
1453:     *W = linesearch->vec_sol_new;
1454:   }
1455:   if (G) {
1457:     *G = linesearch->vec_func_new;
1458:   }
1459:   PetscFunctionReturn(PETSC_SUCCESS);
1460: }

1462: /*@
1463:    SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context

1465:    Logically Collective

1467:    Input Parameters:
1468: +  linesearch - linesearch context
1469: .  X - Solution vector
1470: .  F - Function vector
1471: .  Y - Search direction vector
1472: .  W - Solution work vector
1473: -  G - Function work vector

1475:    Level: advanced

1477: .seealso: `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1478: @*/
1479: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1480: {
1481:   PetscFunctionBegin;
1483:   if (X) {
1485:     linesearch->vec_sol = X;
1486:   }
1487:   if (F) {
1489:     linesearch->vec_func = F;
1490:   }
1491:   if (Y) {
1493:     linesearch->vec_update = Y;
1494:   }
1495:   if (W) {
1497:     linesearch->vec_sol_new = W;
1498:   }
1499:   if (G) {
1501:     linesearch->vec_func_new = G;
1502:   }
1503:   PetscFunctionReturn(PETSC_SUCCESS);
1504: }

1506: /*@C
1507:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1508:    `SNESLineSearch` options in the database.

1510:    Logically Collective

1512:    Input Parameters:
1513: +  linesearch - the `SNESLineSearch` context
1514: -  prefix - the prefix to prepend to all option names

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

1520:    Level: advanced

1522: .seealso: `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1523: @*/
1524: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1525: {
1526:   PetscFunctionBegin;
1528:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix));
1529:   PetscFunctionReturn(PETSC_SUCCESS);
1530: }

1532: /*@C
1533:    SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1534:    SNESLineSearch options in the database.

1536:    Not Collective

1538:    Input Parameter:
1539: .  linesearch - the `SNESLineSearch` context

1541:    Output Parameter:
1542: .  prefix - pointer to the prefix string used

1544:    Fortran Note:
1545:    On the fortran side, the user should pass in a string 'prefix' of
1546:    sufficient length to hold the prefix.

1548:    Level: advanced

1550: .seealso: `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1551: @*/
1552: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1553: {
1554:   PetscFunctionBegin;
1556:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix));
1557:   PetscFunctionReturn(PETSC_SUCCESS);
1558: }

1560: /*@C
1561:    SNESLineSearchSetWorkVecs - Sets work vectors for the line search.

1563:    Input Parameters:
1564: +  linesearch - the `SNESLineSearch` context
1565: -  nwork - the number of work vectors

1567:    Level: developer

1569: .seealso: `SNESLineSearch`, `SNESSetWorkVecs()`
1570: @*/
1571: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1572: {
1573:   PetscFunctionBegin;
1574:   PetscCheck(linesearch->vec_sol, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1575:   PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1576:   PetscFunctionReturn(PETSC_SUCCESS);
1577: }

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

1582:    Input Parameters:
1583: .  linesearch - linesearch context

1585:    Output Parameters:
1586: .  result - The success or failure status

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

1592:    Level: developer

1594: .seealso: `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1595: @*/
1596: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1597: {
1598:   PetscFunctionBegin;
1601:   *result = linesearch->result;
1602:   PetscFunctionReturn(PETSC_SUCCESS);
1603: }

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

1608:    Input Parameters:
1609: +  linesearch - linesearch context
1610: -  result - The success or failure status

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

1616:    Level: developer

1618: .seealso: `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`
1619: @*/
1620: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1621: {
1622:   PetscFunctionBegin;
1624:   linesearch->result = result;
1625:   PetscFunctionReturn(PETSC_SUCCESS);
1626: }

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

1631:    Logically Collective

1633:    Input Parameters:
1634: +  snes - nonlinear context obtained from `SNESCreate()`
1635: .  projectfunc - function for projecting the function to the bounds
1636: -  normfunc - function for computing the norm of an active set

1638:    Calling sequence of projectfunc:
1639: .vb
1640:    projectfunc (SNES snes, Vec X)
1641: .ve

1643:     Input parameters for projectfunc:
1644: +   snes - nonlinear context
1645: -   X - current solution

1647:     Output parameter for projectfunc:
1648: .   X - Projected solution

1650:    Calling sequence of normfunc:
1651: .vb
1652:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
1653: .ve

1655:     Input parameters for normfunc:
1656: +   snes - nonlinear context
1657: .   X - current solution
1658: -   F - current residual

1660:     Output parameter for normfunc:
1661: .   fnorm - VI-specific norm of the function

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

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

1669:     Level: advanced

1671: .seealso: `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`
1672: @*/
1673: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
1674: {
1675:   PetscFunctionBegin;
1677:   if (projectfunc) linesearch->ops->viproject = projectfunc;
1678:   if (normfunc) linesearch->ops->vinorm = normfunc;
1679:   PetscFunctionReturn(PETSC_SUCCESS);
1680: }

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

1685:    Not Collective

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

1690:    Output Parameters:
1691: +  projectfunc - function for projecting the function to the bounds
1692: -  normfunc - function for computing the norm of an active set

1694:     Level: advanced

1696: .seealso: `SNESLineSearch`, `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`
1697: @*/
1698: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
1699: {
1700:   PetscFunctionBegin;
1701:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
1702:   if (normfunc) *normfunc = linesearch->ops->vinorm;
1703:   PetscFunctionReturn(PETSC_SUCCESS);
1704: }

1706: /*@C
1707:   SNESLineSearchRegister - register a line search method

1709:   Level: advanced

1711: .seealso: `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1712: @*/
1713: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch))
1714: {
1715:   PetscFunctionBegin;
1716:   PetscCall(SNESInitializePackage());
1717:   PetscCall(PetscFunctionListAdd(&SNESLineSearchList, sname, function));
1718:   PetscFunctionReturn(PETSC_SUCCESS);
1719: }