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 Parameter:
 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:   Level: advanced

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

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

 30: .seealso: [](ch_snes), `SNES`, `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 Parameter:
 51: . ls - the line search object

 53:   Level: developer

 55:   Note:
 56:   This routine is called by the `SNESLineSearch` implementations.
 57:   It does not typically need to be called by the user.

 59: .seealso: [](ch_snes), `SNES`, `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: /*@
 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 monitor routine (use `NULL` if no context is desired)
 81: - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence

 83:   Calling sequence of `f`:
 84: + ls   - the `SNESLineSearch` context
 85: - mctx - [optional] user-defined context for private data for the monitor routine

 87:   Level: intermediate

 89:   Note:
 90:   Several different monitoring routines may be set by calling
 91:   `SNESLineSearchMonitorSet()` multiple times; all will be called in the
 92:   order in which they were set.

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

 97: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorCancel()`, `PetscCtxDestroyFn`
 98: @*/
 99: PetscErrorCode SNESLineSearchMonitorSet(SNESLineSearch ls, PetscErrorCode (*f)(SNESLineSearch ls, PetscCtx mctx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy)
100: {
101:   PetscFunctionBegin;
103:   for (PetscInt i = 0; i < ls->numbermonitors; i++) {
104:     PetscBool identical;

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

116: /*@
117:   SNESLineSearchMonitorSolutionUpdate - Monitors each update of the function value the line search tries

119:   Collective

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

125:   Options Database Key:
126: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine

128:   Level: developer

130:   This is not normally called directly but is passed to `SNESLineSearchMonitorSet()`

132: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorSet()`, `SNESMonitorSolution()`
133: @*/
134: PetscErrorCode SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls, PetscViewerAndFormat *vf)
135: {
136:   PetscViewer viewer = vf->viewer;
137:   Vec         Y, W, G;

139:   PetscFunctionBegin;
140:   PetscCall(SNESLineSearchGetVecs(ls, NULL, NULL, &Y, &W, &G));
141:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
142:   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted update to solution \n"));
143:   PetscCall(VecView(Y, viewer));
144:   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted new solution \n"));
145:   PetscCall(VecView(W, viewer));
146:   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted updated function value\n"));
147:   PetscCall(VecView(G, viewer));
148:   PetscCall(PetscViewerPopFormat(viewer));
149:   PetscFunctionReturn(PETSC_SUCCESS);
150: }

152: /*@
153:   SNESLineSearchCreate - Creates a `SNESLineSearch` context.

155:   Logically Collective

157:   Input Parameter:
158: . comm - MPI communicator for the line search (typically from the associated `SNES` context).

160:   Output Parameter:
161: . outlinesearch - the new line search context

163:   Level: developer

165:   Note:
166:   The preferred calling sequence is to use `SNESGetLineSearch()` to acquire the `SNESLineSearch` instance
167:   already associated with the `SNES`.

169: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `LineSearchDestroy()`, `SNESGetLineSearch()`
170: @*/
171: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
172: {
173:   SNESLineSearch linesearch;

175:   PetscFunctionBegin;
176:   PetscAssertPointer(outlinesearch, 2);
177:   PetscCall(SNESInitializePackage());

179:   PetscCall(PetscHeaderCreate(linesearch, SNESLINESEARCH_CLASSID, "SNESLineSearch", "Linesearch", "SNESLineSearch", comm, SNESLineSearchDestroy, SNESLineSearchView));
180:   linesearch->vec_sol_new  = NULL;
181:   linesearch->vec_func_new = NULL;
182:   linesearch->vec_sol      = NULL;
183:   linesearch->vec_func     = NULL;
184:   linesearch->vec_update   = NULL;

186:   linesearch->lambda       = 1.0;
187:   linesearch->fnorm        = 1.0;
188:   linesearch->ynorm        = 1.0;
189:   linesearch->xnorm        = 1.0;
190:   linesearch->reason       = SNES_LINESEARCH_SUCCEEDED;
191:   linesearch->norms        = PETSC_TRUE;
192:   linesearch->keeplambda   = PETSC_FALSE;
193:   linesearch->damping      = 1.0;
194:   linesearch->maxlambda    = 1.0;
195:   linesearch->minlambda    = 1e-12;
196:   linesearch->rtol         = 1e-8;
197:   linesearch->atol         = 1e-15;
198:   linesearch->ltol         = 1e-8;
199:   linesearch->precheckctx  = NULL;
200:   linesearch->postcheckctx = NULL;
201:   linesearch->max_it       = 1;
202:   linesearch->setupcalled  = PETSC_FALSE;
203:   linesearch->monitor      = NULL;
204:   *outlinesearch           = linesearch;
205:   PetscFunctionReturn(PETSC_SUCCESS);
206: }

208: /*@
209:   SNESLineSearchSetUp - Prepares the line search for being applied by allocating
210:   any required vectors.

212:   Collective

214:   Input Parameter:
215: . linesearch - The `SNESLineSearch` instance.

217:   Level: advanced

219:   Note:
220:   For most cases, this needn't be called by users or outside of `SNESLineSearchApply()`.
221:   The only current case where this is called outside of this is for the VI
222:   solvers, which modify the solution and work vectors before the first call
223:   of `SNESLineSearchApply()`, requiring the `SNESLineSearch` work vectors to be
224:   allocated upfront.

226: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchReset()`
227: @*/
228: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
229: {
230:   PetscFunctionBegin;
231:   if (!((PetscObject)linesearch)->type_name) PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHNONE));
232:   if (!linesearch->setupcalled) {
233:     if (!linesearch->vec_sol_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new));
234:     if (!linesearch->vec_func_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new));
235:     PetscTryTypeMethod(linesearch, setup);
236:     if (!linesearch->ops->snesfunc) PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunction));
237:     linesearch->lambda      = linesearch->damping;
238:     linesearch->setupcalled = PETSC_TRUE;
239:   }
240:   PetscFunctionReturn(PETSC_SUCCESS);
241: }

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

246:   Collective

248:   Input Parameter:
249: . linesearch - The `SNESLineSearch` instance.

251:   Level: developer

253:   Note:
254:   Usually only called by `SNESReset()`

256: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetUp()`
257: @*/
258: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
259: {
260:   PetscFunctionBegin;
261:   PetscTryTypeMethod(linesearch, reset);

263:   PetscCall(VecDestroy(&linesearch->vec_sol_new));
264:   PetscCall(VecDestroy(&linesearch->vec_func_new));

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

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

273: /*@
274:   SNESLineSearchSetFunction - Sets the function evaluation used by the `SNES` line search
275:   `

277:   Input Parameters:
278: + linesearch - the `SNESLineSearch` context
279: - func       - function evaluation routine, this is usually the function provided with `SNESSetFunction()`

281:   Calling sequence of `func`:
282: + snes - the `SNES` with which the `SNESLineSearch` context is associated with
283: . x    - the input vector
284: - f    - the computed value of the function

286:   Level: developer

288:   Note:
289:   By default the `SNESLineSearch` uses the function provided by `SNESSetFunction()` so this is rarely needed

291: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESSetFunction()`
292: @*/
293: PetscErrorCode SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES snes, Vec x, Vec f))
294: {
295:   PetscFunctionBegin;
297:   linesearch->ops->snesfunc = func;
298:   PetscFunctionReturn(PETSC_SUCCESS);
299: }

301: /*@
302:   SNESLineSearchSetPreCheck - Sets a function that is called after the initial search direction has been computed but
303:   before the line search routine has been applied. Allows adjusting the result of (usually a linear solve) that
304:   determined the search direction.

306:   Logically Collective

308:   Input Parameters:
309: + linesearch - the `SNESLineSearch` context
310: . func       - [optional] function evaluation routine
311: - ctx        - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)

313:   Calling sequence of `func`:
314: + ls        - the `SNESLineSearch` context
315: . x         - the current solution
316: . d         - the current search direction
317: . changed_d - indicates if the search direction has been changed
318: - ctx       - the context passed to `SNESLineSearchSetPreCheck()`

320:   Level: intermediate

322:   Note:
323:   Use `SNESLineSearchSetPostCheck()` to change the step after the line search is complete.

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

327: .seealso: [](ch_snes), `SNES`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
328:           `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()`
329: @*/
330: PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, PetscBool *changed_d, PetscCtx ctx), PetscCtx ctx)
331: {
332:   PetscFunctionBegin;
334:   if (func) linesearch->ops->precheck = func;
335:   if (ctx) linesearch->precheckctx = ctx;
336:   PetscFunctionReturn(PETSC_SUCCESS);
337: }

339: /*@
340:   SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.

342:   Input Parameter:
343: . linesearch - the `SNESLineSearch` context

345:   Output Parameters:
346: + func - [optional] function evaluation routine,  for calling sequence see `SNESLineSearchSetPreCheck()`
347: - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)

349:   Level: intermediate

351: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
352: @*/
353: PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), PetscCtxRt ctx)
354: {
355:   PetscFunctionBegin;
357:   if (func) *func = linesearch->ops->precheck;
358:   if (ctx) *(void **)ctx = linesearch->precheckctx;
359:   PetscFunctionReturn(PETSC_SUCCESS);
360: }

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

366:   Logically Collective

368:   Input Parameters:
369: + linesearch - the `SNESLineSearch` context
370: . func       - [optional] function evaluation routine
371: - ctx        - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)

373:   Calling sequence of `func`:
374: + ls        - the `SNESLineSearch` context
375: . x         - the current solution
376: . d         - the current search direction
377: . w         - $ w = x + lambda*d $ for some lambda
378: . changed_d - indicates if the search direction `d` has been changed
379: . changed_w - indicates `w` has been changed
380: - ctx       - the context passed to `SNESLineSearchSetPreCheck()`

382:   Level: intermediate

384:   Notes:
385:   Use `SNESLineSearchSetPreCheck()` to change the step before the line search is completed.
386:   The calling sequence of the callback does not contain the current scaling factor. To access the value, use `SNESLineSearchGetLambda()`.

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

390: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
391:           `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()`
392: @*/
393: PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, Vec w, PetscBool *changed_d, PetscBool *changed_w, PetscCtx ctx), PetscCtx ctx)
394: {
395:   PetscFunctionBegin;
397:   if (func) linesearch->ops->postcheck = func;
398:   if (ctx) linesearch->postcheckctx = ctx;
399:   PetscFunctionReturn(PETSC_SUCCESS);
400: }

402: /*@
403:   SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.

405:   Input Parameter:
406: . linesearch - the `SNESLineSearch` context

408:   Output Parameters:
409: + func - [optional] function evaluation routine, see for the calling sequence `SNESLineSearchSetPostCheck()`
410: - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)

412:   Level: intermediate

414: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
415: @*/
416: PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), PetscCtxRt ctx)
417: {
418:   PetscFunctionBegin;
420:   if (func) *func = linesearch->ops->postcheck;
421:   if (ctx) *(void **)ctx = linesearch->postcheckctx;
422:   PetscFunctionReturn(PETSC_SUCCESS);
423: }

425: /*@
426:   SNESLineSearchPreCheck - Prepares the line search for being applied.

428:   Logically Collective

430:   Input Parameters:
431: + linesearch - The line search instance
432: . X          - The current solution
433: - Y          - The step direction

435:   Output Parameter:
436: . changed - Indicator that the precheck routine has changed `Y`

438:   Level: advanced

440:   Note:
441:   This calls any function provided with `SNESLineSearchSetPreCheck()` and is called automatically inside the line search routines

443:   Developer Note:
444:   The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided

446: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
447:           `SNESLineSearchGetPostCheck()`
448: @*/
449: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed)
450: {
451:   PetscFunctionBegin;
452:   *changed = PETSC_FALSE;
453:   if (linesearch->ops->precheck) {
454:     PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
456:   }
457:   PetscFunctionReturn(PETSC_SUCCESS);
458: }

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

463:   Logically Collective

465:   Input Parameters:
466: + linesearch - The line search context
467: . X          - The last solution
468: . Y          - The step direction
469: - W          - The updated solution, `W = X - lambda * Y` for some lambda

471:   Output Parameters:
472: + changed_Y - Indicator if the direction `Y` has been changed.
473: - changed_W - Indicator if the new candidate solution `W` has been changed.

475:   Level: developer

477:   Note:
478:   This calls any function provided with `SNESLineSearchSetPostCheck()` and is called automatically inside the line search routines

480:   Developer Note:
481:   The use of `PetscObjectGetState()` would eliminate the need for the `changed_Y` and `changed_W` arguments to be provided

483: .seealso: [](ch_snes), `SNES`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
484: @*/
485: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W)
486: {
487:   PetscFunctionBegin;
488:   *changed_Y = PETSC_FALSE;
489:   *changed_W = PETSC_FALSE;
490:   if (linesearch->ops->postcheck) {
491:     PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
494:   }
495:   PetscFunctionReturn(PETSC_SUCCESS);
496: }

498: /*@
499:   SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration {cite}`hindmarsh1996time`

501:   Logically Collective

503:   Input Parameters:
504: + linesearch - the line search context
505: . X          - base state for this step
506: - ctx        - context for this function

508:   Input/Output Parameter:
509: . Y - correction, possibly modified

511:   Output Parameter:
512: . changed - flag indicating that `Y` was modified

514:   Options Database Keys:
515: + -snes_linesearch_precheck_picard (true|false) - activate this routine
516: - -snes_linesearch_precheck_picard_angle angle  - the angle to use

518:   Level: advanced

520:   Notes:
521:   This function should be passed to `SNESLineSearchSetPreCheck()`

523:   The justification for this method involves the linear convergence of a Picard iteration
524:   so the Picard linearization should be provided in place of the "Jacobian"  {cite}`hindmarsh1996time`. This correction
525:   is generally not useful when using a Newton linearization.

527:   Developer Note:
528:   The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided

530: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetPicard()`, `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
531: @*/
532: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, PetscCtx ctx)
533: {
534:   PetscReal   angle = *(PetscReal *)linesearch->precheckctx;
535:   Vec         Ylast;
536:   PetscScalar dot;
537:   PetscInt    iter;
538:   PetscReal   ynorm, ylastnorm, theta, angle_radians;
539:   SNES        snes;

541:   PetscFunctionBegin;
542:   PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
543:   PetscCall(PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast));
544:   if (!Ylast) {
545:     PetscCall(VecDuplicate(Y, &Ylast));
546:     PetscCall(PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast));
547:     PetscCall(PetscObjectDereference((PetscObject)Ylast));
548:   }
549:   PetscCall(SNESGetIterationNumber(snes, &iter));
550:   if (iter < 2) {
551:     PetscCall(VecCopy(Y, Ylast));
552:     *changed = PETSC_FALSE;
553:     PetscFunctionReturn(PETSC_SUCCESS);
554:   }

556:   PetscCall(VecDot(Y, Ylast, &dot));
557:   PetscCall(VecNorm(Y, NORM_2, &ynorm));
558:   PetscCall(VecNorm(Ylast, NORM_2, &ylastnorm));
559:   if (ynorm == 0. || ylastnorm == 0.) {
560:     *changed = PETSC_FALSE;
561:     PetscFunctionReturn(PETSC_SUCCESS);
562:   }
563:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
564:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
565:   angle_radians = angle * PETSC_PI / 180.;
566:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
567:     /* Modify the step Y */
568:     PetscReal alpha, ydiffnorm;
569:     PetscCall(VecAXPY(Ylast, -1.0, Y));
570:     PetscCall(VecNorm(Ylast, NORM_2, &ydiffnorm));
571:     alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
572:     PetscCall(VecCopy(Y, Ylast));
573:     PetscCall(VecScale(Y, alpha));
574:     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));
575:     *changed = PETSC_TRUE;
576:   } else {
577:     PetscCall(PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180 / PETSC_PI), (double)angle));
578:     PetscCall(VecCopy(Y, Ylast));
579:     *changed = PETSC_FALSE;
580:   }
581:   PetscFunctionReturn(PETSC_SUCCESS);
582: }

584: /*@
585:   SNESLineSearchApply - Computes the line-search update.

587:   Collective

589:   Input Parameter:
590: . linesearch - The line search context

592:   Input/Output Parameters:
593: + X     - The current solution, on output the new solution
594: . F     - The current function value, on output the new function value at the solution value `X`
595: . fnorm - The current norm of `F`, on output the new norm of `F`
596: - Y     - The current search direction, on output the direction determined by the line search, i.e. `Xnew = Xold - lambda*Y`

598:   Options Database Keys:
599: + -snes_linesearch_type (none|bt|secant|cp|nleqerr|bisection|shell) - Line search type, see `SNESLineSearchType`
600: . -snes_linesearch_monitor [:filename]                              - Print progress of line searches
601: . -snes_linesearch_damping damping                                  - The line search damping parameter, default is 1.0 (no damping)
602: . -snes_linesearch_norms (true|false)                               - Turn on/off the line search norms computation (`SNESLineSearchSetComputeNorms()`)
603: . -snes_linesearch_keeplambda (true|false)                          - Keep the previous `lambda` as the initial guess
604: - -snes_linesearch_max_it it                                        - The number of iterations for iterative line searches

606:   Level: advanced

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

616:   In certain situations `SNESLineSearchApply()` may directly set a `SNESConvergedReason` in the `SNES` object so one should always check
617:   this value immediately after the call to `SNESLineSearchApply()`.

619: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchGetLambda()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
620:           `SNESLineSearchType`, `SNESLineSearchSetType()`
621: @*/
622: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y)
623: {
624:   PetscFunctionBegin;

630:   linesearch->reason = SNES_LINESEARCH_SUCCEEDED;

632:   linesearch->vec_sol    = X;
633:   linesearch->vec_update = Y;
634:   linesearch->vec_func   = F;

636:   PetscCall(SNESLineSearchSetUp(linesearch));

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

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

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

645:   PetscUseTypeMethod(linesearch, apply);

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

649:   if (fnorm) *fnorm = linesearch->fnorm;
650:   PetscFunctionReturn(PETSC_SUCCESS);
651: }

653: /*@
654:   SNESLineSearchDestroy - Destroys the line search instance.

656:   Collective

658:   Input Parameter:
659: . linesearch - The line search context

661:   Level: developer

663:   Note:
664:   The line search in `SNES` is automatically called on `SNESDestroy()` so this call is rarely needed

666: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
667: @*/
668: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch)
669: {
670:   PetscFunctionBegin;
671:   if (!*linesearch) PetscFunctionReturn(PETSC_SUCCESS);
673:   if (--((PetscObject)*linesearch)->refct > 0) {
674:     *linesearch = NULL;
675:     PetscFunctionReturn(PETSC_SUCCESS);
676:   }
677:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*linesearch));
678:   PetscCall(SNESLineSearchReset(*linesearch));
679:   PetscTryTypeMethod(*linesearch, destroy);
680:   PetscCall(PetscViewerDestroy(&(*linesearch)->monitor));
681:   PetscCall(SNESLineSearchMonitorCancel(*linesearch));
682:   PetscCall(PetscHeaderDestroy(linesearch));
683:   PetscFunctionReturn(PETSC_SUCCESS);
684: }

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

689:   Logically Collective

691:   Input Parameters:
692: + linesearch - the line search object
693: - viewer     - an `PETSCVIEWERASCII` `PetscViewer` or `NULL` to turn off monitor

695:   Options Database Key:
696: . -snes_linesearch_monitor [:filename] - enables the monitor

698:   Level: intermediate

700:   Developer Notes:
701:   This monitor is implemented differently than the other line search monitors that are set with
702:   `SNESLineSearchMonitorSet()` since it is called in many locations of the line search routines to display aspects of the
703:   line search that are not visible to the other monitors.

705: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PETSCVIEWERASCII`, `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`,
706:           `SNESLineSearchMonitorSetFromOptions()`
707: @*/
708: PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
709: {
710:   PetscFunctionBegin;
711:   PetscCall(PetscViewerDestroy(&linesearch->monitor));
712:   linesearch->monitor = viewer;
713:   PetscFunctionReturn(PETSC_SUCCESS);
714: }

716: /*@
717:   SNESLineSearchGetDefaultMonitor - Gets the `PetscViewer` instance for the default line search monitor that is turned on with `SNESLineSearchSetDefaultMonitor()`

719:   Logically Collective

721:   Input Parameter:
722: . linesearch - the line search context

724:   Output Parameter:
725: . monitor - monitor context

727:   Level: intermediate

729: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
730: @*/
731: PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
732: {
733:   PetscFunctionBegin;
735:   *monitor = linesearch->monitor;
736:   PetscFunctionReturn(PETSC_SUCCESS);
737: }

739: /*@
740:   SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated in the options database

742:   Collective

744:   Input Parameters:
745: + ls           - `SNESLineSearch` object to monitor
746: . name         - the monitor type
747: . help         - message indicating what monitoring is done
748: . manual       - manual page for the monitor
749: . monitor      - the monitor function, must use `PetscViewerAndFormat` as its context
750: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNESLineSearch` or `PetscViewer`

752:   Calling sequence of `monitor`:
753: + ls - `SNESLineSearch` object being monitored
754: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used

756:   Calling sequence of `monitorsetup`:
757: + ls - `SNESLineSearch` object being monitored
758: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used

760:   Level: advanced

762: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetMonitor()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
763:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
764:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
765:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
766:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
767:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
768:           `PetscOptionsFList()`, `PetscOptionsEList()`
769: @*/
770: PetscErrorCode SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNESLineSearch ls, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(SNESLineSearch ls, PetscViewerAndFormat *vf))
771: {
772:   PetscViewer       viewer;
773:   PetscViewerFormat format;
774:   PetscBool         flg;

776:   PetscFunctionBegin;
777:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg));
778:   if (flg) {
779:     PetscViewerAndFormat *vf;
780:     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
781:     PetscCall(PetscViewerDestroy(&viewer));
782:     if (monitorsetup) PetscCall((*monitorsetup)(ls, vf));
783:     PetscCall(SNESLineSearchMonitorSet(ls, (PetscErrorCode (*)(SNESLineSearch, PetscCtx))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
784:   }
785:   PetscFunctionReturn(PETSC_SUCCESS);
786: }

788: /*@
789:   SNESLineSearchSetFromOptions - Sets options for the line search

791:   Logically Collective

793:   Input Parameter:
794: . linesearch - a `SNESLineSearch` line search context

796:   Options Database Keys:
797: + -snes_linesearch_type (none|bt|secant|cp|nleqerr|bisection|shell) - Line search type, see `SNESLineSearchType`
798: . -snes_linesearch_order order                                      - 1, 2, 3. Most types only support certain orders (`bt` supports 1, 2 or 3)
799: . -snes_linesearch_norms (true|false)                               - Turn on/off the line search norms for the `none` line search type (`SNESLineSearchSetComputeNorms()`)
800: . -snes_linesearch_minlambda minlambda                              - The minimum `lambda`
801: . -snes_linesearch_maxlambda maxlambda                              - The maximum `lambda`
802: . -snes_linesearch_rtol rtol                                        - Relative tolerance for iterative line searches
803: . -snes_linesearch_atol atol                                        - Absolute tolerance for iterative line searches
804: . -snes_linesearch_ltol ltol                                        - Change in `lambda` tolerance for iterative line searches
805: . -snes_linesearch_max_it max_it                                    - The number of iterations for iterative line searches
806: . -snes_linesearch_monitor [:filename]                              - Print progress of line searches
807: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - View each update tried by line search routine
808: . -snes_linesearch_damping damping                                  - The line search damping parameter
809: . -snes_linesearch_keeplambda (true|false)                          - Keep the previous `lambda` as the initial guess.
810: . -snes_linesearch_precheck_picard (true|false)                     - Use precheck that speeds up convergence of picard method
811: - -snes_linesearch_precheck_picard_angle angle                      - Angle used in Picard precheck method

813:   Level: intermediate

815: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
816:           `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
817: @*/
818: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
819: {
820:   const char *deft = SNESLINESEARCHNONE;
821:   char        type[256];
822:   PetscBool   flg, set;
823:   PetscViewer viewer;

825:   PetscFunctionBegin;
826:   PetscCall(SNESLineSearchRegisterAll());

828:   PetscObjectOptionsBegin((PetscObject)linesearch);
829:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
830:   PetscCall(PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg));
831:   if (flg) {
832:     PetscCall(SNESLineSearchSetType(linesearch, type));
833:   } else if (!((PetscObject)linesearch)->type_name) {
834:     PetscCall(SNESLineSearchSetType(linesearch, deft));
835:   }

837:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set));
838:   if (set) PetscCall(SNESLineSearchSetDefaultMonitor(linesearch, viewer));
839:   PetscCall(SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL));

841:   /* tolerances */
842:   PetscCall(PetscOptionsReal("-snes_linesearch_minlambda", "Minimum lambda", "SNESLineSearchSetTolerances", linesearch->minlambda, &linesearch->minlambda, NULL));
843:   PetscCall(PetscOptionsReal("-snes_linesearch_maxlambda", "Maximum lambda", "SNESLineSearchSetTolerances", linesearch->maxlambda, &linesearch->maxlambda, NULL));
844:   PetscCall(PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL));
845:   PetscCall(PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL));
846:   PetscCall(PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL));
847:   PetscCall(PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_it, &linesearch->max_it, NULL));

849:   /* deprecated options */
850:   PetscCall(PetscOptionsDeprecated("-snes_linesearch_maxstep", "-snes_linesearch_maxlambda", "3.24.0", NULL));

852:   /* damping parameters */
853:   PetscCall(PetscOptionsReal("-snes_linesearch_damping", "Line search damping (and depending on chosen line search initial lambda guess)", "SNESLineSearchSetDamping", linesearch->damping, &linesearch->damping, NULL));

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

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

863:       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));
864:       PetscCall(SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle));
865:     } else {
866:       PetscCall(SNESLineSearchSetPreCheck(linesearch, NULL, NULL));
867:     }
868:   }
869:   PetscCall(PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL));
870:   PetscCall(PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL));

872:   PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);

874:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject));
875:   PetscOptionsEnd();
876:   PetscFunctionReturn(PETSC_SUCCESS);
877: }

879: /*@
880:   SNESLineSearchView - Prints useful information about the line search

882:   Logically Collective

884:   Input Parameters:
885: + linesearch - line search context
886: - viewer     - the `PetscViewer` to display the line search information to

888:   Level: intermediate

890: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`
891: @*/
892: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
893: {
894:   PetscBool isascii;

896:   PetscFunctionBegin;
898:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer));
900:   PetscCheckSameComm(linesearch, 1, viewer, 2);

902:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
903:   if (isascii) {
904:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer));
905:     PetscCall(PetscViewerASCIIPushTab(viewer));
906:     PetscTryTypeMethod(linesearch, view, viewer);
907:     PetscCall(PetscViewerASCIIPopTab(viewer));
908:     PetscCall(PetscViewerASCIIPrintf(viewer, "  maxlambda=%e, minlambda=%e\n", (double)linesearch->maxlambda, (double)linesearch->minlambda));
909:     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol));
910:     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT "\n", linesearch->max_it));
911:     if (linesearch->ops->precheck) {
912:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
913:         PetscCall(PetscViewerASCIIPrintf(viewer, "  using precheck step to speed up Picard convergence\n"));
914:       } else {
915:         PetscCall(PetscViewerASCIIPrintf(viewer, "  using user-defined precheck step\n"));
916:       }
917:     }
918:     if (linesearch->ops->postcheck) PetscCall(PetscViewerASCIIPrintf(viewer, "  using user-defined postcheck step\n"));
919:   }
920:   PetscFunctionReturn(PETSC_SUCCESS);
921: }

923: /*@
924:   SNESLineSearchGetType - Gets the `SNESLinesearchType` of a `SNESLineSearch`

926:   Logically Collective

928:   Input Parameter:
929: . linesearch - the line search context

931:   Output Parameter:
932: . type - The type of line search, or `NULL` if not set

934:   Level: intermediate

936:   Note:
937:   `type` should not be retained for later use as it will be an invalid pointer if the `SNESLineSearchType` of `linesearch` is changed.

939: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`,
940:           `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
941: @*/
942: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
943: {
944:   PetscFunctionBegin;
946:   PetscAssertPointer(type, 2);
947:   *type = ((PetscObject)linesearch)->type_name;
948:   PetscFunctionReturn(PETSC_SUCCESS);
949: }

951: /*@
952:   SNESLineSearchSetType - Sets the `SNESLinesearchType` of a `SNESLineSearch` object to indicate the line search algorithm that should be used by a given `SNES` solver

954:   Logically Collective

956:   Input Parameters:
957: + linesearch - the line search context
958: - type       - The type of line search to be used, see `SNESLineSearchType`

960:   Options Database Key:
961: . -snes_linesearch_type (none|bt|secant|cp|nleqerr|bisection|shell) - Line search type to use, see `SNESLineSearchType`

963:   Level: intermediate

965:   Note:
966:   The `SNESLineSearch` object is generally obtained with `SNESGetLineSearch()`

968: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`,
969:           `SNESGetLineSearch()`
970: @*/
971: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
972: {
973:   PetscBool match;
974:   PetscErrorCode (*r)(SNESLineSearch);

976:   PetscFunctionBegin;
978:   PetscAssertPointer(type, 2);

980:   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, type, &match));
981:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

983:   PetscCall(PetscFunctionListFind(SNESLineSearchList, type, &r));
984:   PetscCheck(r, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Line Search type %s", type);
985:   /* Destroy the previous private line search context */
986:   PetscTryTypeMethod(linesearch, destroy);
987:   linesearch->ops->destroy = NULL;
988:   /* Reinitialize function pointers in SNESLineSearchOps structure */
989:   linesearch->ops->apply          = NULL;
990:   linesearch->ops->view           = NULL;
991:   linesearch->ops->setfromoptions = NULL;
992:   linesearch->ops->destroy        = NULL;

994:   PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch, type));
995:   PetscCall((*r)(linesearch));
996:   PetscFunctionReturn(PETSC_SUCCESS);
997: }

999: /*@
1000:   SNESLineSearchSetSNES - Sets the `SNES` for the line search for function evaluation.

1002:   Input Parameters:
1003: + linesearch - the line search context
1004: - snes       - The `SNES` instance

1006:   Level: developer

1008:   Note:
1009:   This happens automatically when the line search is obtained/created with
1010:   `SNESGetLineSearch()`.  This routine is therefore mainly called within `SNES`
1011:   implementations.

1013: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`
1014: @*/
1015: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
1016: {
1017:   PetscFunctionBegin;
1020:   linesearch->snes = snes;
1021:   PetscFunctionReturn(PETSC_SUCCESS);
1022: }

1024: /*@
1025:   SNESLineSearchGetSNES - Gets the `SNES` instance associated with the line search.

1027:   Not Collective

1029:   Input Parameter:
1030: . linesearch - the line search context

1032:   Output Parameter:
1033: . snes - The `SNES` instance

1035:   Level: developer

1037: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESType`, `SNESLineSearchSetVecs()`
1038: @*/
1039: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
1040: {
1041:   PetscFunctionBegin;
1043:   PetscAssertPointer(snes, 2);
1044:   *snes = linesearch->snes;
1045:   PetscFunctionReturn(PETSC_SUCCESS);
1046: }

1048: /*@
1049:   SNESLineSearchGetLambda - Gets the last line search `lambda` used

1051:   Not Collective

1053:   Input Parameter:
1054: . linesearch - the line search context

1056:   Output Parameter:
1057: . lambda - The last `lambda` (scaling of the solution update) computed during `SNESLineSearchApply()`

1059:   Level: advanced

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

1067: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1068: @*/
1069: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1070: {
1071:   PetscFunctionBegin;
1073:   PetscAssertPointer(lambda, 2);
1074:   *lambda = linesearch->lambda;
1075:   PetscFunctionReturn(PETSC_SUCCESS);
1076: }

1078: /*@
1079:   SNESLineSearchSetLambda - Sets the line search `lambda` (scaling of the solution update)

1081:   Input Parameters:
1082: + linesearch - line search context
1083: - lambda     - The `lambda` to use

1085:   Level: developer

1087:   Notes:
1088:   This routine is typically used within implementations of `SNESLineSearchApply()`
1089:   to set the final `lambda`.  This routine (and `SNESLineSearchGetLambda()`) were
1090:   added to facilitate Quasi-Newton methods that use the previous `lambda`
1091:   as an inner scaling parameter.

1093:   For `SNESLINESEARCHNONE` use `SNESLineSearchSetDamping()`, not this function.

1095: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetLambda()`, `SNESLineSearchSetDamping()`
1096: @*/
1097: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1098: {
1099:   PetscFunctionBegin;
1101:   linesearch->lambda = lambda;
1102:   PetscFunctionReturn(PETSC_SUCCESS);
1103: }

1105: /*@
1106:   SNESLineSearchGetTolerances - Gets the tolerances for the line search.

1108:   Not Collective

1110:   Input Parameter:
1111: . linesearch - the line search context

1113:   Output Parameters:
1114: + minlambda - The minimum `lambda` allowed
1115: . maxlambda - The maximum `lambda` allowed
1116: . rtol      - The relative tolerance for iterative line searches
1117: . atol      - The absolute tolerance for iterative line searches
1118: . ltol      - The change in `lambda` tolerance for iterative line searches
1119: - max_it    - The maximum number of iterations of the line search

1121:   Level: intermediate

1123:   Note:
1124:   Different line searches may implement these parameters slightly differently as
1125:   the type requires.

1127: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1128: @*/
1129: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *minlambda, PetscReal *maxlambda, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_it)
1130: {
1131:   PetscFunctionBegin;
1133:   if (minlambda) {
1134:     PetscAssertPointer(minlambda, 2);
1135:     *minlambda = linesearch->minlambda;
1136:   }
1137:   if (maxlambda) {
1138:     PetscAssertPointer(maxlambda, 3);
1139:     *maxlambda = linesearch->maxlambda;
1140:   }
1141:   if (rtol) {
1142:     PetscAssertPointer(rtol, 4);
1143:     *rtol = linesearch->rtol;
1144:   }
1145:   if (atol) {
1146:     PetscAssertPointer(atol, 5);
1147:     *atol = linesearch->atol;
1148:   }
1149:   if (ltol) {
1150:     PetscAssertPointer(ltol, 6);
1151:     *ltol = linesearch->ltol;
1152:   }
1153:   if (max_it) {
1154:     PetscAssertPointer(max_it, 7);
1155:     *max_it = linesearch->max_it;
1156:   }
1157:   PetscFunctionReturn(PETSC_SUCCESS);
1158: }

1160: /*@
1161:   SNESLineSearchSetTolerances -  Sets the tolerances for the linesearch.

1163:   Collective

1165:   Input Parameters:
1166: + linesearch - The line search context
1167: . minlambda  - The minimum `lambda` allowed
1168: . maxlambda  - The maximum `lambda` allowed
1169: . rtol       - The relative tolerance for iterative line searches
1170: . atol       - The absolute tolerance for iterative line searches
1171: . ltol       - The change in `lambda` tolerance for iterative line searches
1172: - max_it     - The maximum number of iterations of the line search

1174:   Options Database Keys:
1175: + -snes_linesearch_minlambda - The minimum `lambda` allowed
1176: . -snes_linesearch_maxlambda - The maximum `lambda` allowed
1177: . -snes_linesearch_rtol      - Relative tolerance for iterative line searches
1178: . -snes_linesearch_atol      - Absolute tolerance for iterative line searches
1179: . -snes_linesearch_ltol      - Change in `lambda` tolerance for iterative line searches
1180: - -snes_linesearch_max_it    - The number of iterations for iterative line searches

1182:   Level: intermediate

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

1187: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1188: @*/
1189: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal minlambda, PetscReal maxlambda, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_it)
1190: {
1191:   PetscFunctionBegin;

1200:   if (minlambda != (PetscReal)PETSC_DEFAULT) {
1201:     PetscCheck(minlambda >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum lambda %14.12e must be non-negative", (double)minlambda);
1202:     PetscCheck(minlambda < maxlambda, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum lambda %14.12e must be smaller than maximum lambda %14.12e", (double)minlambda, (double)maxlambda);
1203:     linesearch->minlambda = minlambda;
1204:   }

1206:   if (maxlambda != (PetscReal)PETSC_DEFAULT) {
1207:     PetscCheck(maxlambda > 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum lambda %14.12e must be positive", (double)maxlambda);
1208:     linesearch->maxlambda = maxlambda;
1209:   }

1211:   if (rtol != (PetscReal)PETSC_DEFAULT) {
1212:     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);
1213:     linesearch->rtol = rtol;
1214:   }

1216:   if (atol != (PetscReal)PETSC_DEFAULT) {
1217:     PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %14.12e must be non-negative", (double)atol);
1218:     linesearch->atol = atol;
1219:   }

1221:   if (ltol != (PetscReal)PETSC_DEFAULT) {
1222:     PetscCheck(ltol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Lambda tolerance %14.12e must be non-negative", (double)ltol);
1223:     linesearch->ltol = ltol;
1224:   }

1226:   if (max_it != PETSC_DEFAULT) {
1227:     PetscCheck(max_it >= 0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", max_it);
1228:     linesearch->max_it = max_it;
1229:   }
1230:   PetscFunctionReturn(PETSC_SUCCESS);
1231: }

1233: /*@
1234:   SNESLineSearchGetDamping - Gets the line search damping parameter.

1236:   Input Parameter:
1237: . linesearch - The line search context

1239:   Output Parameter:
1240: . damping - The damping parameter

1242:   Level: advanced

1244: .seealso: [](ch_snes), `SNES`, `SNESLineSearchGetStepTolerance()`, `SNESQN`
1245: @*/
1246: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1247: {
1248:   PetscFunctionBegin;
1250:   PetscAssertPointer(damping, 2);
1251:   *damping = linesearch->damping;
1252:   PetscFunctionReturn(PETSC_SUCCESS);
1253: }

1255: /*@
1256:   SNESLineSearchSetDamping - Sets the line search damping parameter.

1258:   Input Parameters:
1259: + linesearch - the line search context
1260: - damping    - The damping parameter

1262:   Options Database Key:
1263: . -snes_linesearch_damping damping - the damping value

1265:   Level: intermediate

1267:   Note:
1268:   The `SNESLINESEARCHNONE` line search merely takes the update step scaled by the damping parameter.
1269:   The use of the damping parameter in the `SNESLINESEARCHSECANT` and `SNESLINESEARCHCP` line searches is much more subtle;
1270:   it is used as a starting point for the secant method. Depending on the choice for `maxlambda`,
1271:   the eventual `lambda` may be greater than the damping parameter however.
1272:   For `SNESLINESEARCHBISECTION` and `SNESLINESEARCHBT` the damping is instead used as the initial guess,
1273:   below which the line search will not go. Hence, it is the maximum possible value for `lambda`.

1275: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetDamping()`, `SNESLineSearchSetLambda()`
1276: @*/
1277: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1278: {
1279:   PetscFunctionBegin;
1281:   linesearch->damping = damping;
1282:   PetscFunctionReturn(PETSC_SUCCESS);
1283: }

1285: /*@
1286:   SNESLineSearchGetOrder - Gets the line search approximation order.

1288:   Input Parameter:
1289: . linesearch - The line search context

1291:   Output Parameter:
1292: . order - The order

1294:   Level: intermediate

1296: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetOrder()`
1297: @*/
1298: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1299: {
1300:   PetscFunctionBegin;
1302:   PetscAssertPointer(order, 2);
1303:   *order = linesearch->order;
1304:   PetscFunctionReturn(PETSC_SUCCESS);
1305: }

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

1310:   Input Parameters:
1311: + linesearch - The line search context
1312: - order      - The order

1314:   Level: intermediate

1316:   Values for `order`\:
1317: +  1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1318: .  2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1319: -  3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order

1321:   Options Database Key:
1322: . -snes_linesearch_order order - 1, 2, 3.  Most types only support certain orders (`SNESLINESEARCHBT` supports 2 or 3)

1324:   Note:
1325:   These orders are supported by `SNESLINESEARCHBT` and `SNESLINESEARCHCP`

1327: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1328: @*/
1329: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1330: {
1331:   PetscFunctionBegin;
1333:   linesearch->order = order;
1334:   PetscFunctionReturn(PETSC_SUCCESS);
1335: }

1337: /*@
1338:   SNESLineSearchGetNorms - Gets the norms for the current solution `X`, the current update `Y`, and the current function value `F`.

1340:   Not Collective

1342:   Input Parameter:
1343: . linesearch - The line search context

1345:   Output Parameters:
1346: + xnorm - The norm of the current solution
1347: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution.
1348: - ynorm - The norm of the current update (after scaling by the linesearch computed `lambda`)

1350:   Level: developer

1352:   Notes:
1353:   Some values may not be up-to-date at particular points in the code.

1355:   This, in combination with `SNESLineSearchSetNorms()`, allow the line search and the `SNESSolve_XXX()` to share
1356:   computed values.

1358: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1359: @*/
1360: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1361: {
1362:   PetscFunctionBegin;
1364:   if (xnorm) *xnorm = linesearch->xnorm;
1365:   if (fnorm) *fnorm = linesearch->fnorm;
1366:   if (ynorm) *ynorm = linesearch->ynorm;
1367:   PetscFunctionReturn(PETSC_SUCCESS);
1368: }

1370: /*@
1371:   SNESLineSearchSetNorms - Sets the computed norms for the current solution `X`, the current update `Y`, and the current function value `F`.

1373:   Collective

1375:   Input Parameters:
1376: + linesearch - The line search context
1377: . xnorm      - The norm of the current solution
1378: . fnorm      - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution
1379: - ynorm      - The norm of the current update (after scaling by the linesearch computed `lambda`)

1381:   Level: developer

1383:   Note:
1384:   This is called by the line search routines to store the values they have just computed

1386: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1387: @*/
1388: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1389: {
1390:   PetscFunctionBegin;
1392:   linesearch->xnorm = xnorm;
1393:   linesearch->fnorm = fnorm;
1394:   linesearch->ynorm = ynorm;
1395:   PetscFunctionReturn(PETSC_SUCCESS);
1396: }

1398: /*@
1399:   SNESLineSearchComputeNorms - Explicitly computes the norms of the current solution `X`, the current update `Y`, and the current function value `F`.

1401:   Input Parameter:
1402: . linesearch - the line search context

1404:   Options Database Key:
1405: . -snes_linesearch_norms (true|false) - turn norm computation on or off

1407:   Level: intermediate

1409:   Developer Note:
1410:   The options database key is misnamed. It should be `-snes_linesearch_compute_norms`

1412: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1413: @*/
1414: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1415: {
1416:   SNES snes;

1418:   PetscFunctionBegin;
1419:   if (linesearch->norms) {
1420:     if (linesearch->ops->vinorm) {
1421:       PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1422:       PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1423:       PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1424:       PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1425:     } else {
1426:       PetscCall(VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1427:       PetscCall(VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1428:       PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1429:       PetscCall(VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1430:       PetscCall(VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1431:       PetscCall(VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1432:     }
1433:   }
1434:   PetscFunctionReturn(PETSC_SUCCESS);
1435: }

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

1440:   Input Parameters:
1441: + linesearch - the line search context
1442: - flg        - indicates whether or not to compute norms

1444:   Options Database Key:
1445: . -snes_linesearch_norms (true|false) - Turns on/off computation of the norms for the `SNESLINESEARCHNONE` line search

1447:   Level: intermediate

1449:   Note:
1450:   This is most relevant to the `SNESLINESEARCHNONE` line search type since most line searches have a stopping criteria involving the norm.

1452:   Developer Note:
1453:   The options database key is misnamed. It should be `-snes_linesearch_compute_norms`

1455: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHNONE`
1456: @*/
1457: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1458: {
1459:   PetscFunctionBegin;
1460:   linesearch->norms = flg;
1461:   PetscFunctionReturn(PETSC_SUCCESS);
1462: }

1464: /*@
1465:   SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context

1467:   Not Collective but the vectors are parallel

1469:   Input Parameter:
1470: . linesearch - The line search context

1472:   Output Parameters:
1473: + X - Solution vector
1474: . F - Function vector
1475: . Y - Search direction vector
1476: . W - Solution work vector
1477: - G - Function work vector

1479:   Level: advanced

1481:   Notes:
1482:   At the beginning of a line search application, `X` should contain a
1483:   solution and the vector `F` the function computed at `X`.  At the end of the
1484:   line search application, `X` should contain the new solution, and `F` the
1485:   function evaluated at the new solution.

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

1489: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1490: @*/
1491: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1492: {
1493:   PetscFunctionBegin;
1495:   if (X) {
1496:     PetscAssertPointer(X, 2);
1497:     *X = linesearch->vec_sol;
1498:   }
1499:   if (F) {
1500:     PetscAssertPointer(F, 3);
1501:     *F = linesearch->vec_func;
1502:   }
1503:   if (Y) {
1504:     PetscAssertPointer(Y, 4);
1505:     *Y = linesearch->vec_update;
1506:   }
1507:   if (W) {
1508:     PetscAssertPointer(W, 5);
1509:     *W = linesearch->vec_sol_new;
1510:   }
1511:   if (G) {
1512:     PetscAssertPointer(G, 6);
1513:     *G = linesearch->vec_func_new;
1514:   }
1515:   PetscFunctionReturn(PETSC_SUCCESS);
1516: }

1518: /*@
1519:   SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context

1521:   Logically Collective

1523:   Input Parameters:
1524: + linesearch - The line search context
1525: . X          - Solution vector
1526: . F          - Function vector
1527: . Y          - Search direction vector
1528: . W          - Solution work vector
1529: - G          - Function work vector

1531:   Level: developer

1533: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1534: @*/
1535: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1536: {
1537:   PetscFunctionBegin;
1539:   if (X) {
1541:     linesearch->vec_sol = X;
1542:   }
1543:   if (F) {
1545:     linesearch->vec_func = F;
1546:   }
1547:   if (Y) {
1549:     linesearch->vec_update = Y;
1550:   }
1551:   if (W) {
1553:     linesearch->vec_sol_new = W;
1554:   }
1555:   if (G) {
1557:     linesearch->vec_func_new = G;
1558:   }
1559:   PetscFunctionReturn(PETSC_SUCCESS);
1560: }

1562: /*@
1563:   SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1564:   `SNESLineSearch` options in the database.

1566:   Logically Collective

1568:   Input Parameters:
1569: + linesearch - the `SNESLineSearch` context
1570: - prefix     - the prefix to prepend to all option names

1572:   Level: advanced

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

1578: .seealso: [](ch_snes), `SNES`, `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1579: @*/
1580: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1581: {
1582:   PetscFunctionBegin;
1584:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix));
1585:   PetscFunctionReturn(PETSC_SUCCESS);
1586: }

1588: /*@
1589:   SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1590:   SNESLineSearch options in the database.

1592:   Not Collective

1594:   Input Parameter:
1595: . linesearch - the `SNESLineSearch` context

1597:   Output Parameter:
1598: . prefix - pointer to the prefix string used

1600:   Level: advanced

1602: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1603: @*/
1604: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1605: {
1606:   PetscFunctionBegin;
1608:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix));
1609:   PetscFunctionReturn(PETSC_SUCCESS);
1610: }

1612: /*@
1613:   SNESLineSearchSetWorkVecs - Sets work vectors for the line search.

1615:   Input Parameters:
1616: + linesearch - the `SNESLineSearch` context
1617: - nwork      - the number of work vectors

1619:   Level: developer

1621:   Developer Note:
1622:   This is called from within the set up routines for each of the line search types `SNESLineSearchType`

1624: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetWorkVecs()`
1625: @*/
1626: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1627: {
1628:   PetscFunctionBegin;
1629:   PetscCheck(linesearch->vec_sol, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1630:   PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1631:   PetscFunctionReturn(PETSC_SUCCESS);
1632: }

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

1637:   Input Parameter:
1638: . linesearch - The line search context

1640:   Output Parameter:
1641: . reason - The success or failure status

1643:   Level: developer

1645:   Note:
1646:   This is typically called after `SNESLineSearchApply()` in order to determine if the line search failed
1647:   (and set into the `SNES` convergence accordingly).

1649: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1650: @*/
1651: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *reason)
1652: {
1653:   PetscFunctionBegin;
1655:   PetscAssertPointer(reason, 2);
1656:   *reason = linesearch->reason;
1657:   PetscFunctionReturn(PETSC_SUCCESS);
1658: }

1660: /*@
1661:   SNESLineSearchSetReason - Sets the success/failure reason of the line search application

1663:   Logically Collective; No Fortran Support

1665:   Input Parameters:
1666: + linesearch - The line search context
1667: - reason     - The success or failure reason

1669:   Level: developer

1671:   Notes:
1672:   This is typically called in a `SNESLineSearchType` implementation of `SNESLineSearchApply()` or a `SNESLINESEARCHSHELL` implementation to set
1673:   the success or failure of the line search method.

1675:   Do not call this from callbacks provided with `SNESSetFunction()`, instead perhaps use `SNESSetFunctionDomainError()`

1677: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`, `SNESSetFunctionDomainError()`, `SNESSetFunction()`
1678: @*/
1679: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason reason)
1680: {
1681:   PetscFunctionBegin;
1683:   linesearch->reason = reason;
1684:   PetscFunctionReturn(PETSC_SUCCESS);
1685: }

1687: // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
1688: /*@
1689:   SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.

1691:   Logically Collective

1693:   Input Parameters:
1694: + linesearch   - the linesearch object
1695: . projectfunc  - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1696: . normfunc     - function for computing the norm of an active set, see `SNESLineSearchVINormFn` for calling sequence
1697: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence

1699:   Level: advanced

1701:   Notes:
1702:   The VI solvers require projection of the solution to the feasible set.  `projectfunc` should implement this.

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

1707:   The VI solvers further require special evaluation of the directional derivative (when assuming that there exists some $G(x)$
1708:   for which the `SNESFunctionFn` $F(x) = grad G(x)$) such that it is only calculated on the inactive set.
1709:   This should be implemented by `dirderivfunc`.

1711: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`,
1712:           `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`, `SNESLineSearchVIDirDerivFn`
1713: @*/
1714: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn *projectfunc, SNESLineSearchVINormFn *normfunc, SNESLineSearchVIDirDerivFn *dirderivfunc)
1715: {
1716:   PetscFunctionBegin;
1718:   if (projectfunc) linesearch->ops->viproject = projectfunc;
1719:   if (normfunc) linesearch->ops->vinorm = normfunc;
1720:   if (dirderivfunc) linesearch->ops->vidirderiv = dirderivfunc;
1721:   PetscFunctionReturn(PETSC_SUCCESS);
1722: }

1724: /*@
1725:   SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.

1727:   Not Collective

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

1732:   Output Parameters:
1733: + projectfunc  - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1734: . normfunc     - function for computing the norm of an active set, see `SNESLineSearchVINormFn ` for calling sequence
1735: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence

1737:   Level: advanced

1739: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
1740:           `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`
1741: @*/
1742: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn **projectfunc, SNESLineSearchVINormFn **normfunc, SNESLineSearchVIDirDerivFn **dirderivfunc)
1743: {
1744:   PetscFunctionBegin;
1745:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
1746:   if (normfunc) *normfunc = linesearch->ops->vinorm;
1747:   if (dirderivfunc) *dirderivfunc = linesearch->ops->vidirderiv;
1748:   PetscFunctionReturn(PETSC_SUCCESS);
1749: }

1751: /*@
1752:   SNESLineSearchRegister - register a line search type `SNESLineSearchType`

1754:   Logically Collective, No Fortran Support

1756:   Input Parameters:
1757: + sname    - name of the `SNESLineSearchType()`
1758: - function - the creation function for that type

1760:   Calling sequence of `function`:
1761: . ls - the line search context

1763:   Level: advanced

1765: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1766: @*/
1767: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch ls))
1768: {
1769:   PetscFunctionBegin;
1770:   PetscCall(SNESInitializePackage());
1771:   PetscCall(PetscFunctionListAdd(&SNESLineSearchList, sname, function));
1772:   PetscFunctionReturn(PETSC_SUCCESS);
1773: }