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 linesearch 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: /*@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 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, void *mctx), void *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: /*@C
117: SNESLineSearchMonitorSolutionUpdate - Monitors each update of the function value the linesearch 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->result = 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, SNESLINESEARCHBASIC));
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: /*@C
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: /*@C
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()`
330: @*/
331: PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, PetscBool *changed_d, void *ctx), void *ctx)
332: {
333: PetscFunctionBegin;
335: if (func) linesearch->ops->precheck = func;
336: if (ctx) linesearch->precheckctx = ctx;
337: PetscFunctionReturn(PETSC_SUCCESS);
338: }
340: /*@C
341: SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.
343: Input Parameter:
344: . linesearch - the `SNESLineSearch` context
346: Output Parameters:
347: + func - [optional] function evaluation routine, for calling sequence see `SNESLineSearchSetPreCheck()`
348: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
350: Level: intermediate
352: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
353: @*/
354: PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void **ctx)
355: {
356: PetscFunctionBegin;
358: if (func) *func = linesearch->ops->precheck;
359: if (ctx) *ctx = linesearch->precheckctx;
360: PetscFunctionReturn(PETSC_SUCCESS);
361: }
363: /*@C
364: SNESLineSearchSetPostCheck - Sets a user function that is called after the line search has been applied to determine the step
365: direction and length. Allows the user a chance to change or override the decision of the line search routine
367: Logically Collective
369: Input Parameters:
370: + linesearch - the `SNESLineSearch` context
371: . func - [optional] function evaluation routine
372: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
374: Calling sequence of `func`:
375: + ls - the `SNESLineSearch` context
376: . x - the current solution
377: . d - the current search direction
378: . w - $ w = x + lambda*d $ for some lambda
379: . changed_d - indicates if the search direction `d` has been changed
380: . changed_w - indicates `w` has been changed
381: - ctx - the context passed to `SNESLineSearchSetPreCheck()`
383: Level: intermediate
385: Notes:
386: Use `SNESLineSearchSetPreCheck()` to change the step before the line search is completed.
387: The calling sequence of the callback does not contain the current scaling factor. To access the value, use `SNESLineSearchGetLambda()`.
389: Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
391: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
392: `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()`
393: @*/
394: PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, Vec w, PetscBool *changed_d, PetscBool *changed_w, void *ctx), void *ctx)
395: {
396: PetscFunctionBegin;
398: if (func) linesearch->ops->postcheck = func;
399: if (ctx) linesearch->postcheckctx = ctx;
400: PetscFunctionReturn(PETSC_SUCCESS);
401: }
403: /*@C
404: SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.
406: Input Parameter:
407: . linesearch - the `SNESLineSearch` context
409: Output Parameters:
410: + func - [optional] function evaluation routine, see for the calling sequence `SNESLineSearchSetPostCheck()`
411: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
413: Level: intermediate
415: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
416: @*/
417: PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void **ctx)
418: {
419: PetscFunctionBegin;
421: if (func) *func = linesearch->ops->postcheck;
422: if (ctx) *ctx = linesearch->postcheckctx;
423: PetscFunctionReturn(PETSC_SUCCESS);
424: }
426: /*@
427: SNESLineSearchPreCheck - Prepares the line search for being applied.
429: Logically Collective
431: Input Parameters:
432: + linesearch - The linesearch instance.
433: . X - The current solution
434: - Y - The step direction
436: Output Parameter:
437: . changed - Indicator that the precheck routine has changed `Y`
439: Level: advanced
441: Note:
442: This calls any function provided with `SNESLineSearchSetPreCheck()` and is called automatically inside the line search routines
444: Developer Note:
445: The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided
447: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
448: `SNESLineSearchGetPostCheck()`
449: @*/
450: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed)
451: {
452: PetscFunctionBegin;
453: *changed = PETSC_FALSE;
454: if (linesearch->ops->precheck) {
455: PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
457: }
458: PetscFunctionReturn(PETSC_SUCCESS);
459: }
461: /*@
462: SNESLineSearchPostCheck - Hook to modify step direction or updated solution after a successful linesearch
464: Logically Collective
466: Input Parameters:
467: + linesearch - The line search context
468: . X - The last solution
469: . Y - The step direction
470: - W - The updated solution, `W = X - lambda * Y` for some lambda
472: Output Parameters:
473: + changed_Y - Indicator if the direction `Y` has been changed.
474: - changed_W - Indicator if the new candidate solution `W` has been changed.
476: Level: developer
478: Note:
479: This calls any function provided with `SNESLineSearchSetPostCheck()` and is called automatically inside the line search routines
481: Developer Note:
482: The use of `PetscObjectGetState()` would eliminate the need for the `changed_Y` and `changed_W` arguments to be provided
484: .seealso: [](ch_snes), `SNES`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
485: @*/
486: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W)
487: {
488: PetscFunctionBegin;
489: *changed_Y = PETSC_FALSE;
490: *changed_W = PETSC_FALSE;
491: if (linesearch->ops->postcheck) {
492: PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
495: }
496: PetscFunctionReturn(PETSC_SUCCESS);
497: }
499: /*@C
500: SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration {cite}`hindmarsh1996time`
502: Logically Collective
504: Input Parameters:
505: + linesearch - the line search context
506: . X - base state for this step
507: - ctx - context for this function
509: Input/Output Parameter:
510: . Y - correction, possibly modified
512: Output Parameter:
513: . changed - flag indicating that `Y` was modified
515: Options Database Keys:
516: + -snes_linesearch_precheck_picard - activate this routine
517: - -snes_linesearch_precheck_picard_angle - angle
519: Level: advanced
521: Notes:
522: This function should be passed to `SNESLineSearchSetPreCheck()`
524: The justification for this method involves the linear convergence of a Picard iteration
525: so the Picard linearization should be provided in place of the "Jacobian" {cite}`hindmarsh1996time`. This correction
526: is generally not useful when using a Newton linearization.
528: Developer Note:
529: The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided
531: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetPicard()`, `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
532: @*/
533: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, void *ctx)
534: {
535: PetscReal angle = *(PetscReal *)linesearch->precheckctx;
536: Vec Ylast;
537: PetscScalar dot;
538: PetscInt iter;
539: PetscReal ynorm, ylastnorm, theta, angle_radians;
540: SNES snes;
542: PetscFunctionBegin;
543: PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
544: PetscCall(PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast));
545: if (!Ylast) {
546: PetscCall(VecDuplicate(Y, &Ylast));
547: PetscCall(PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast));
548: PetscCall(PetscObjectDereference((PetscObject)Ylast));
549: }
550: PetscCall(SNESGetIterationNumber(snes, &iter));
551: if (iter < 2) {
552: PetscCall(VecCopy(Y, Ylast));
553: *changed = PETSC_FALSE;
554: PetscFunctionReturn(PETSC_SUCCESS);
555: }
557: PetscCall(VecDot(Y, Ylast, &dot));
558: PetscCall(VecNorm(Y, NORM_2, &ynorm));
559: PetscCall(VecNorm(Ylast, NORM_2, &ylastnorm));
560: if (ynorm == 0. || ylastnorm == 0.) {
561: *changed = PETSC_FALSE;
562: PetscFunctionReturn(PETSC_SUCCESS);
563: }
564: /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
565: theta = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
566: angle_radians = angle * PETSC_PI / 180.;
567: if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
568: /* Modify the step Y */
569: PetscReal alpha, ydiffnorm;
570: PetscCall(VecAXPY(Ylast, -1.0, Y));
571: PetscCall(VecNorm(Ylast, NORM_2, &ydiffnorm));
572: alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
573: PetscCall(VecCopy(Y, Ylast));
574: PetscCall(VecScale(Y, alpha));
575: 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));
576: *changed = PETSC_TRUE;
577: } else {
578: PetscCall(PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180 / PETSC_PI), (double)angle));
579: PetscCall(VecCopy(Y, Ylast));
580: *changed = PETSC_FALSE;
581: }
582: PetscFunctionReturn(PETSC_SUCCESS);
583: }
585: /*@
586: SNESLineSearchApply - Computes the line-search update.
588: Collective
590: Input Parameter:
591: . linesearch - The line search context
593: Input/Output Parameters:
594: + X - The current solution, on output the new solution
595: . F - The current function value, on output the new function value at the solution value `X`
596: . fnorm - The current norm of `F`, on output the new norm of `F`
597: - Y - The current search direction, on output the direction determined by the linesearch, i.e. `Xnew = Xold - lambda*Y`
599: Options Database Keys:
600: + -snes_linesearch_type - basic (or equivalently none), bt, secant, cp, nleqerr, bisection, shell
601: . -snes_linesearch_monitor [:filename] - Print progress of line searches
602: . -snes_linesearch_damping - The linesearch damping parameter, default is 1.0 (no damping)
603: . -snes_linesearch_norms - Turn on/off the linesearch norms computation (SNESLineSearchSetComputeNorms())
604: . -snes_linesearch_keeplambda - Keep the previous `lambda` as the initial guess
605: - -snes_linesearch_max_it - The number of iterations for iterative line searches
607: Level: intermediate
609: Notes:
610: This is typically called from within a `SNESSolve()` implementation in order to
611: help with convergence of the nonlinear method. Various `SNES` types use line searches
612: in different ways, but the overarching theme is that a line search is used to determine
613: an optimal damping parameter (that is `lambda`) of a step at each iteration of the method. Each
614: application of the line search may invoke `SNESComputeFunction()` several times, and
615: therefore may be fairly expensive.
617: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchGetLambda()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
618: `SNESLineSearchType`, `SNESLineSearchSetType()`
619: @*/
620: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y)
621: {
622: PetscFunctionBegin;
628: linesearch->result = SNES_LINESEARCH_SUCCEEDED;
630: linesearch->vec_sol = X;
631: linesearch->vec_update = Y;
632: linesearch->vec_func = F;
634: PetscCall(SNESLineSearchSetUp(linesearch));
636: if (!linesearch->keeplambda) linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */
638: if (fnorm) linesearch->fnorm = *fnorm;
639: else PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm));
641: PetscCall(PetscLogEventBegin(SNESLINESEARCH_Apply, linesearch, X, F, Y));
643: PetscUseTypeMethod(linesearch, apply);
645: PetscCall(PetscLogEventEnd(SNESLINESEARCH_Apply, linesearch, X, F, Y));
647: if (fnorm) *fnorm = linesearch->fnorm;
648: PetscFunctionReturn(PETSC_SUCCESS);
649: }
651: /*@
652: SNESLineSearchDestroy - Destroys the line search instance.
654: Collective
656: Input Parameter:
657: . linesearch - The line search context
659: Level: developer
661: Note:
662: The line search in `SNES` is automatically called on `SNESDestroy()` so this call is rarely needed
664: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
665: @*/
666: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch)
667: {
668: PetscFunctionBegin;
669: if (!*linesearch) PetscFunctionReturn(PETSC_SUCCESS);
671: if (--((PetscObject)*linesearch)->refct > 0) {
672: *linesearch = NULL;
673: PetscFunctionReturn(PETSC_SUCCESS);
674: }
675: PetscCall(PetscObjectSAWsViewOff((PetscObject)*linesearch));
676: PetscCall(SNESLineSearchReset(*linesearch));
677: PetscTryTypeMethod(*linesearch, destroy);
678: PetscCall(PetscViewerDestroy(&(*linesearch)->monitor));
679: PetscCall(SNESLineSearchMonitorCancel(*linesearch));
680: PetscCall(PetscHeaderDestroy(linesearch));
681: PetscFunctionReturn(PETSC_SUCCESS);
682: }
684: /*@
685: SNESLineSearchSetDefaultMonitor - Turns on/off printing useful information and debugging output about the line search.
687: Logically Collective
689: Input Parameters:
690: + linesearch - the linesearch object
691: - viewer - an `PETSCVIEWERASCII` `PetscViewer` or `NULL` to turn off monitor
693: Options Database Key:
694: . -snes_linesearch_monitor [:filename] - enables the monitor
696: Level: intermediate
698: Developer Notes:
699: This monitor is implemented differently than the other line search monitors that are set with
700: `SNESLineSearchMonitorSet()` since it is called in many locations of the line search routines to display aspects of the
701: line search that are not visible to the other monitors.
703: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PETSCVIEWERASCII`, `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`,
704: `SNESLineSearchMonitorSetFromOptions()`
705: @*/
706: PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
707: {
708: PetscFunctionBegin;
709: PetscCall(PetscViewerDestroy(&linesearch->monitor));
710: linesearch->monitor = viewer;
711: PetscFunctionReturn(PETSC_SUCCESS);
712: }
714: /*@
715: SNESLineSearchGetDefaultMonitor - Gets the `PetscViewer` instance for the default line search monitor that is turned on with `SNESLineSearchSetDefaultMonitor()`
717: Logically Collective
719: Input Parameter:
720: . linesearch - the line search context
722: Output Parameter:
723: . monitor - monitor context
725: Level: intermediate
727: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
728: @*/
729: PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
730: {
731: PetscFunctionBegin;
733: *monitor = linesearch->monitor;
734: PetscFunctionReturn(PETSC_SUCCESS);
735: }
737: /*@C
738: SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated in the options database
740: Collective
742: Input Parameters:
743: + ls - `SNESLineSearch` object to monitor
744: . name - the monitor type
745: . help - message indicating what monitoring is done
746: . manual - manual page for the monitor
747: . monitor - the monitor function, must use `PetscViewerAndFormat` as its context
748: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNESLineSearch` or `PetscViewer`
750: Calling sequence of `monitor`:
751: + ls - `SNESLineSearch` object being monitored
752: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used
754: Calling sequence of `monitorsetup`:
755: + ls - `SNESLineSearch` object being monitored
756: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used
758: Level: advanced
760: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetMonitor()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
761: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
762: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
763: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
764: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
765: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
766: `PetscOptionsFList()`, `PetscOptionsEList()`
767: @*/
768: 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))
769: {
770: PetscViewer viewer;
771: PetscViewerFormat format;
772: PetscBool flg;
774: PetscFunctionBegin;
775: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg));
776: if (flg) {
777: PetscViewerAndFormat *vf;
778: PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
779: PetscCall(PetscViewerDestroy(&viewer));
780: if (monitorsetup) PetscCall((*monitorsetup)(ls, vf));
781: PetscCall(SNESLineSearchMonitorSet(ls, (PetscErrorCode (*)(SNESLineSearch, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
782: }
783: PetscFunctionReturn(PETSC_SUCCESS);
784: }
786: /*@
787: SNESLineSearchSetFromOptions - Sets options for the line search
789: Logically Collective
791: Input Parameter:
792: . linesearch - a `SNESLineSearch` line search context
794: Options Database Keys:
795: + -snes_linesearch_type <type> - basic (or equivalently none), `bt`, `secant`, `cp`, `nleqerr`, `bisection`, `shell`
796: . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (`bt` supports 1, 2 or 3)
797: . -snes_linesearch_norms - Turn on/off the linesearch norms for the basic linesearch typem (`SNESLineSearchSetComputeNorms()`)
798: . -snes_linesearch_minlambda - The minimum `lambda`
799: . -snes_linesearch_maxlambda - The maximum `lambda`
800: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
801: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
802: . -snes_linesearch_ltol - Change in `lambda` tolerance for iterative line searches
803: . -snes_linesearch_max_it - The number of iterations for iterative line searches
804: . -snes_linesearch_monitor [:filename] - Print progress of line searches
805: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
806: . -snes_linesearch_damping - The linesearch damping parameter
807: . -snes_linesearch_keeplambda - Keep the previous `lambda` as the initial guess.
808: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
809: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method
811: Level: intermediate
813: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
814: `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
815: @*/
816: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
817: {
818: const char *deft = SNESLINESEARCHBASIC;
819: char type[256];
820: PetscBool flg, set;
821: PetscViewer viewer;
823: PetscFunctionBegin;
824: PetscCall(SNESLineSearchRegisterAll());
826: PetscObjectOptionsBegin((PetscObject)linesearch);
827: if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
828: PetscCall(PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg));
829: if (flg) {
830: PetscCall(SNESLineSearchSetType(linesearch, type));
831: } else if (!((PetscObject)linesearch)->type_name) {
832: PetscCall(SNESLineSearchSetType(linesearch, deft));
833: }
835: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set));
836: if (set) PetscCall(SNESLineSearchSetDefaultMonitor(linesearch, viewer));
837: PetscCall(SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL));
839: /* tolerances */
840: PetscCall(PetscOptionsReal("-snes_linesearch_minlambda", "Minimum lambda", "SNESLineSearchSetTolerances", linesearch->minlambda, &linesearch->minlambda, NULL));
841: PetscCall(PetscOptionsReal("-snes_linesearch_maxlambda", "Maximum lambda", "SNESLineSearchSetTolerances", linesearch->maxlambda, &linesearch->maxlambda, NULL));
842: PetscCall(PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL));
843: PetscCall(PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL));
844: PetscCall(PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL));
845: PetscCall(PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_it, &linesearch->max_it, NULL));
847: /* deprecated options */
848: PetscCall(PetscOptionsDeprecated("-snes_linesearch_maxstep", "-snes_linesearch_maxlambda", "3.24.0", NULL));
850: /* damping parameters */
851: PetscCall(PetscOptionsReal("-snes_linesearch_damping", "Line search damping (and depending on chosen line search initial lambda guess)", "SNESLineSearchSetDamping", linesearch->damping, &linesearch->damping, NULL));
853: PetscCall(PetscOptionsBool("-snes_linesearch_keeplambda", "Use previous lambda as damping", "SNESLineSearchSetKeepLambda", linesearch->keeplambda, &linesearch->keeplambda, NULL));
855: /* precheck */
856: PetscCall(PetscOptionsBool("-snes_linesearch_precheck_picard", "Use a correction that sometimes improves convergence of Picard iteration", "SNESLineSearchPreCheckPicard", flg, &flg, &set));
857: if (set) {
858: if (flg) {
859: linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */
861: 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));
862: PetscCall(SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle));
863: } else {
864: PetscCall(SNESLineSearchSetPreCheck(linesearch, NULL, NULL));
865: }
866: }
867: PetscCall(PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL));
868: PetscCall(PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL));
870: PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);
872: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject));
873: PetscOptionsEnd();
874: PetscFunctionReturn(PETSC_SUCCESS);
875: }
877: /*@
878: SNESLineSearchView - Prints useful information about the line search
880: Logically Collective
882: Input Parameters:
883: + linesearch - line search context
884: - viewer - the `PetscViewer` to display the line search information to
886: Level: intermediate
888: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`
889: @*/
890: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
891: {
892: PetscBool isascii;
894: PetscFunctionBegin;
896: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer));
898: PetscCheckSameComm(linesearch, 1, viewer, 2);
900: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
901: if (isascii) {
902: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer));
903: PetscCall(PetscViewerASCIIPushTab(viewer));
904: PetscTryTypeMethod(linesearch, view, viewer);
905: PetscCall(PetscViewerASCIIPopTab(viewer));
906: PetscCall(PetscViewerASCIIPrintf(viewer, " maxlambda=%e, minlambda=%e\n", (double)linesearch->maxlambda, (double)linesearch->minlambda));
907: PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol));
908: PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT "\n", linesearch->max_it));
909: if (linesearch->ops->precheck) {
910: if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
911: PetscCall(PetscViewerASCIIPrintf(viewer, " using precheck step to speed up Picard convergence\n"));
912: } else {
913: PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined precheck step\n"));
914: }
915: }
916: if (linesearch->ops->postcheck) PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined postcheck step\n"));
917: }
918: PetscFunctionReturn(PETSC_SUCCESS);
919: }
921: /*@
922: SNESLineSearchGetType - Gets the `SNESLinesearchType` of a `SNESLineSearch`
924: Logically Collective
926: Input Parameter:
927: . linesearch - the line search context
929: Output Parameter:
930: . type - The type of line search, or `NULL` if not set
932: Level: intermediate
934: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
935: @*/
936: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
937: {
938: PetscFunctionBegin;
940: PetscAssertPointer(type, 2);
941: *type = ((PetscObject)linesearch)->type_name;
942: PetscFunctionReturn(PETSC_SUCCESS);
943: }
945: /*@
946: SNESLineSearchSetType - Sets the `SNESLinesearchType` of a `SNESLineSearch` object to indicate the line search algorithm that should be used by a given `SNES` solver
948: Logically Collective
950: Input Parameters:
951: + linesearch - the line search context
952: - type - The type of line search to be used, see `SNESLineSearchType`
954: Options Database Key:
955: . -snes_linesearch_type <type> - basic (or equivalently none), bt, secant, cp, nleqerr, bisection, shell
957: Level: intermediate
959: Note:
960: The `SNESLineSearch` object is generally obtained with `SNESGetLineSearch()`
962: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`,
963: `SNESGetLineSearch()`
964: @*/
965: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
966: {
967: PetscBool match;
968: PetscErrorCode (*r)(SNESLineSearch);
970: PetscFunctionBegin;
972: PetscAssertPointer(type, 2);
974: PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, type, &match));
975: if (match) PetscFunctionReturn(PETSC_SUCCESS);
977: PetscCall(PetscFunctionListFind(SNESLineSearchList, type, &r));
978: PetscCheck(r, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Line Search type %s", type);
979: /* Destroy the previous private line search context */
980: PetscTryTypeMethod(linesearch, destroy);
981: linesearch->ops->destroy = NULL;
982: /* Reinitialize function pointers in SNESLineSearchOps structure */
983: linesearch->ops->apply = NULL;
984: linesearch->ops->view = NULL;
985: linesearch->ops->setfromoptions = NULL;
986: linesearch->ops->destroy = NULL;
988: PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch, type));
989: PetscCall((*r)(linesearch));
990: PetscFunctionReturn(PETSC_SUCCESS);
991: }
993: /*@
994: SNESLineSearchSetSNES - Sets the `SNES` for the linesearch for function evaluation.
996: Input Parameters:
997: + linesearch - the line search context
998: - snes - The `SNES` instance
1000: Level: developer
1002: Note:
1003: This happens automatically when the line search is obtained/created with
1004: `SNESGetLineSearch()`. This routine is therefore mainly called within `SNES`
1005: implementations.
1007: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`
1008: @*/
1009: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
1010: {
1011: PetscFunctionBegin;
1014: linesearch->snes = snes;
1015: PetscFunctionReturn(PETSC_SUCCESS);
1016: }
1018: /*@
1019: SNESLineSearchGetSNES - Gets the `SNES` instance associated with the line search.
1021: Not Collective
1023: Input Parameter:
1024: . linesearch - the line search context
1026: Output Parameter:
1027: . snes - The `SNES` instance
1029: Level: developer
1031: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESType`, `SNESLineSearchSetVecs()`
1032: @*/
1033: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
1034: {
1035: PetscFunctionBegin;
1037: PetscAssertPointer(snes, 2);
1038: *snes = linesearch->snes;
1039: PetscFunctionReturn(PETSC_SUCCESS);
1040: }
1042: /*@
1043: SNESLineSearchGetLambda - Gets the last line search `lambda` used
1045: Not Collective
1047: Input Parameter:
1048: . linesearch - the line search context
1050: Output Parameter:
1051: . lambda - The last `lambda` (scaling of the solution update) computed during `SNESLineSearchApply()`
1053: Level: advanced
1055: Note:
1056: This is useful in methods where the solver is ill-scaled and
1057: requires some adaptive notion of the difference in scale between the
1058: solution and the function. For instance, `SNESQN` may be scaled by the
1059: line search `lambda` using the argument -snes_qn_scaling ls.
1061: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1062: @*/
1063: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1064: {
1065: PetscFunctionBegin;
1067: PetscAssertPointer(lambda, 2);
1068: *lambda = linesearch->lambda;
1069: PetscFunctionReturn(PETSC_SUCCESS);
1070: }
1072: /*@
1073: SNESLineSearchSetLambda - Sets the line search `lambda` (scaling of the solution update)
1075: Input Parameters:
1076: + linesearch - line search context
1077: - lambda - The `lambda` to use
1079: Level: advanced
1081: Note:
1082: This routine is typically used within implementations of `SNESLineSearchApply()`
1083: to set the final `lambda`. This routine (and `SNESLineSearchGetLambda()`) were
1084: added to facilitate Quasi-Newton methods that use the previous `lambda`
1085: as an inner scaling parameter.
1087: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetLambda()`
1088: @*/
1089: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1090: {
1091: PetscFunctionBegin;
1093: linesearch->lambda = lambda;
1094: PetscFunctionReturn(PETSC_SUCCESS);
1095: }
1097: /*@
1098: SNESLineSearchGetTolerances - Gets the tolerances for the line search.
1100: Not Collective
1102: Input Parameter:
1103: . linesearch - the line search context
1105: Output Parameters:
1106: + minlambda - The minimum `lambda` allowed
1107: . maxlambda - The maximum `lambda` allowed
1108: . rtol - The relative tolerance for iterative line searches
1109: . atol - The absolute tolerance for iterative line searches
1110: . ltol - The change in `lambda` tolerance for iterative line searches
1111: - max_it - The maximum number of iterations of the line search
1113: Level: intermediate
1115: Note:
1116: Different line searches may implement these parameters slightly differently as
1117: the type requires.
1119: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1120: @*/
1121: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *minlambda, PetscReal *maxlambda, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_it)
1122: {
1123: PetscFunctionBegin;
1125: if (minlambda) {
1126: PetscAssertPointer(minlambda, 2);
1127: *minlambda = linesearch->minlambda;
1128: }
1129: if (maxlambda) {
1130: PetscAssertPointer(maxlambda, 3);
1131: *maxlambda = linesearch->maxlambda;
1132: }
1133: if (rtol) {
1134: PetscAssertPointer(rtol, 4);
1135: *rtol = linesearch->rtol;
1136: }
1137: if (atol) {
1138: PetscAssertPointer(atol, 5);
1139: *atol = linesearch->atol;
1140: }
1141: if (ltol) {
1142: PetscAssertPointer(ltol, 6);
1143: *ltol = linesearch->ltol;
1144: }
1145: if (max_it) {
1146: PetscAssertPointer(max_it, 7);
1147: *max_it = linesearch->max_it;
1148: }
1149: PetscFunctionReturn(PETSC_SUCCESS);
1150: }
1152: /*@
1153: SNESLineSearchSetTolerances - Sets the tolerances for the linesearch.
1155: Collective
1157: Input Parameters:
1158: + linesearch - the line search context
1159: . minlambda - The minimum `lambda` allowed
1160: . maxlambda - The maximum `lambda` allowed
1161: . rtol - The relative tolerance for iterative line searches
1162: . atol - The absolute tolerance for iterative line searches
1163: . ltol - The change in `lambda` tolerance for iterative line searches
1164: - max_it - The maximum number of iterations of the line search
1166: Options Database Keys:
1167: + -snes_linesearch_minlambda - The minimum `lambda` allowed
1168: . -snes_linesearch_maxlambda - The maximum `lambda` allowed
1169: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
1170: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
1171: . -snes_linesearch_ltol - Change in `lambda` tolerance for iterative line searches
1172: - -snes_linesearch_max_it - The number of iterations for iterative line searches
1174: Level: intermediate
1176: Note:
1177: The user may choose to not set any of the tolerances using `PETSC_DEFAULT` in place of an argument.
1179: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1180: @*/
1181: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal minlambda, PetscReal maxlambda, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_it)
1182: {
1183: PetscFunctionBegin;
1192: if (minlambda != (PetscReal)PETSC_DEFAULT) {
1193: PetscCheck(minlambda >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum lambda %14.12e must be non-negative", (double)minlambda);
1194: 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);
1195: linesearch->minlambda = minlambda;
1196: }
1198: if (maxlambda != (PetscReal)PETSC_DEFAULT) {
1199: PetscCheck(maxlambda > 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum lambda %14.12e must be positive", (double)maxlambda);
1200: linesearch->maxlambda = maxlambda;
1201: }
1203: if (rtol != (PetscReal)PETSC_DEFAULT) {
1204: 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);
1205: linesearch->rtol = rtol;
1206: }
1208: if (atol != (PetscReal)PETSC_DEFAULT) {
1209: PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %14.12e must be non-negative", (double)atol);
1210: linesearch->atol = atol;
1211: }
1213: if (ltol != (PetscReal)PETSC_DEFAULT) {
1214: PetscCheck(ltol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Lambda tolerance %14.12e must be non-negative", (double)ltol);
1215: linesearch->ltol = ltol;
1216: }
1218: if (max_it != PETSC_DEFAULT) {
1219: PetscCheck(max_it >= 0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", max_it);
1220: linesearch->max_it = max_it;
1221: }
1222: PetscFunctionReturn(PETSC_SUCCESS);
1223: }
1225: /*@
1226: SNESLineSearchGetDamping - Gets the line search damping parameter.
1228: Input Parameter:
1229: . linesearch - the line search context
1231: Output Parameter:
1232: . damping - The damping parameter
1234: Level: advanced
1236: .seealso: [](ch_snes), `SNES`, `SNESLineSearchGetStepTolerance()`, `SNESQN`
1237: @*/
1238: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1239: {
1240: PetscFunctionBegin;
1242: PetscAssertPointer(damping, 2);
1243: *damping = linesearch->damping;
1244: PetscFunctionReturn(PETSC_SUCCESS);
1245: }
1247: /*@
1248: SNESLineSearchSetDamping - Sets the line search damping parameter.
1250: Input Parameters:
1251: + linesearch - the line search context
1252: - damping - The damping parameter
1254: Options Database Key:
1255: . -snes_linesearch_damping <damping> - the damping value
1257: Level: intermediate
1259: Note:
1260: The `SNESLINESEARCHNONE` line search merely takes the update step scaled by the damping parameter.
1261: The use of the damping parameter in the `SNESLINESEARCHSECANT` and `SNESLINESEARCHCP` line searches is much more subtle;
1262: it is used as a starting point for the secant method. Depending on the choice for `maxlambda`,
1263: the eventual `lambda` may be greater than the damping parameter however.
1264: For `SNESLINESEARCHBISECTION` and `SNESLINESEARCHBT` the damping is instead used as the initial guess,
1265: below which the line search will not go. Hence, it is the maximum possible value for `lambda`.
1267: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetDamping()`
1268: @*/
1269: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1270: {
1271: PetscFunctionBegin;
1273: linesearch->damping = damping;
1274: PetscFunctionReturn(PETSC_SUCCESS);
1275: }
1277: /*@
1278: SNESLineSearchGetOrder - Gets the line search approximation order.
1280: Input Parameter:
1281: . linesearch - the line search context
1283: Output Parameter:
1284: . order - The order
1286: Level: intermediate
1288: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetOrder()`
1289: @*/
1290: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1291: {
1292: PetscFunctionBegin;
1294: PetscAssertPointer(order, 2);
1295: *order = linesearch->order;
1296: PetscFunctionReturn(PETSC_SUCCESS);
1297: }
1299: /*@
1300: SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search
1302: Input Parameters:
1303: + linesearch - the line search context
1304: - order - The order
1306: Level: intermediate
1308: Values for `order`\:
1309: + 1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1310: . 2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1311: - 3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order
1313: Options Database Key:
1314: . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (`SNESLINESEARCHBT` supports 2 or 3)
1316: Note:
1317: These orders are supported by `SNESLINESEARCHBT` and `SNESLINESEARCHCP`
1319: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1320: @*/
1321: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1322: {
1323: PetscFunctionBegin;
1325: linesearch->order = order;
1326: PetscFunctionReturn(PETSC_SUCCESS);
1327: }
1329: /*@
1330: SNESLineSearchGetNorms - Gets the norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1332: Not Collective
1334: Input Parameter:
1335: . linesearch - the line search context
1337: Output Parameters:
1338: + xnorm - The norm of the current solution
1339: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution.
1340: - ynorm - The norm of the current update (after scaling by the linesearch computed `lambda`)
1342: Level: developer
1344: Notes:
1345: Some values may not be up-to-date at particular points in the code.
1347: This, in combination with `SNESLineSearchSetNorms()`, allow the line search and the `SNESSolve_XXX()` to share
1348: computed values.
1350: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1351: @*/
1352: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1353: {
1354: PetscFunctionBegin;
1356: if (xnorm) *xnorm = linesearch->xnorm;
1357: if (fnorm) *fnorm = linesearch->fnorm;
1358: if (ynorm) *ynorm = linesearch->ynorm;
1359: PetscFunctionReturn(PETSC_SUCCESS);
1360: }
1362: /*@
1363: SNESLineSearchSetNorms - Sets the computed norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1365: Collective
1367: Input Parameters:
1368: + linesearch - the line search context
1369: . xnorm - The norm of the current solution
1370: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution
1371: - ynorm - The norm of the current update (after scaling by the linesearch computed `lambda`)
1373: Level: developer
1375: Note:
1376: This is called by the line search routines to store the values they have just computed
1378: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1379: @*/
1380: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1381: {
1382: PetscFunctionBegin;
1384: linesearch->xnorm = xnorm;
1385: linesearch->fnorm = fnorm;
1386: linesearch->ynorm = ynorm;
1387: PetscFunctionReturn(PETSC_SUCCESS);
1388: }
1390: /*@
1391: SNESLineSearchComputeNorms - Explicitly computes the norms of the current solution `X`, the current update `Y`, and the current function value `F`.
1393: Input Parameter:
1394: . linesearch - the line search context
1396: Options Database Key:
1397: . -snes_linesearch_norms - turn norm computation on or off
1399: Level: intermediate
1401: Developer Note:
1402: The options database key is misnamed. It should be -snes_linesearch_compute_norms
1404: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1405: @*/
1406: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1407: {
1408: SNES snes;
1410: PetscFunctionBegin;
1411: if (linesearch->norms) {
1412: if (linesearch->ops->vinorm) {
1413: PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1414: PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1415: PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1416: PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1417: } else {
1418: PetscCall(VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1419: PetscCall(VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1420: PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1421: PetscCall(VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1422: PetscCall(VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1423: PetscCall(VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1424: }
1425: }
1426: PetscFunctionReturn(PETSC_SUCCESS);
1427: }
1429: /*@
1430: SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.
1432: Input Parameters:
1433: + linesearch - the line search context
1434: - flg - indicates whether or not to compute norms
1436: Options Database Key:
1437: . -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic (none) `SNESLINESEARCHBASIC` line search
1439: Level: intermediate
1441: Note:
1442: This is most relevant to the `SNESLINESEARCHBASIC` (or equivalently `SNESLINESEARCHNONE`) line search type since most line searches have a stopping criteria involving the norm.
1444: Developer Note:
1445: The options database key is misnamed. It should be -snes_linesearch_compute_norms
1447: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1448: @*/
1449: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1450: {
1451: PetscFunctionBegin;
1452: linesearch->norms = flg;
1453: PetscFunctionReturn(PETSC_SUCCESS);
1454: }
1456: /*@
1457: SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context
1459: Not Collective but the vectors are parallel
1461: Input Parameter:
1462: . linesearch - the line search context
1464: Output Parameters:
1465: + X - Solution vector
1466: . F - Function vector
1467: . Y - Search direction vector
1468: . W - Solution work vector
1469: - G - Function work vector
1471: Level: advanced
1473: Notes:
1474: At the beginning of a line search application, `X` should contain a
1475: solution and the vector `F` the function computed at `X`. At the end of the
1476: line search application, `X` should contain the new solution, and `F` the
1477: function evaluated at the new solution.
1479: These vectors are owned by the `SNESLineSearch` and should not be destroyed by the caller
1481: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1482: @*/
1483: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1484: {
1485: PetscFunctionBegin;
1487: if (X) {
1488: PetscAssertPointer(X, 2);
1489: *X = linesearch->vec_sol;
1490: }
1491: if (F) {
1492: PetscAssertPointer(F, 3);
1493: *F = linesearch->vec_func;
1494: }
1495: if (Y) {
1496: PetscAssertPointer(Y, 4);
1497: *Y = linesearch->vec_update;
1498: }
1499: if (W) {
1500: PetscAssertPointer(W, 5);
1501: *W = linesearch->vec_sol_new;
1502: }
1503: if (G) {
1504: PetscAssertPointer(G, 6);
1505: *G = linesearch->vec_func_new;
1506: }
1507: PetscFunctionReturn(PETSC_SUCCESS);
1508: }
1510: /*@
1511: SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context
1513: Logically Collective
1515: Input Parameters:
1516: + linesearch - the line search context
1517: . X - Solution vector
1518: . F - Function vector
1519: . Y - Search direction vector
1520: . W - Solution work vector
1521: - G - Function work vector
1523: Level: developer
1525: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1526: @*/
1527: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1528: {
1529: PetscFunctionBegin;
1531: if (X) {
1533: linesearch->vec_sol = X;
1534: }
1535: if (F) {
1537: linesearch->vec_func = F;
1538: }
1539: if (Y) {
1541: linesearch->vec_update = Y;
1542: }
1543: if (W) {
1545: linesearch->vec_sol_new = W;
1546: }
1547: if (G) {
1549: linesearch->vec_func_new = G;
1550: }
1551: PetscFunctionReturn(PETSC_SUCCESS);
1552: }
1554: /*@
1555: SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1556: `SNESLineSearch` options in the database.
1558: Logically Collective
1560: Input Parameters:
1561: + linesearch - the `SNESLineSearch` context
1562: - prefix - the prefix to prepend to all option names
1564: Level: advanced
1566: Note:
1567: A hyphen (-) must NOT be given at the beginning of the prefix name.
1568: The first character of all runtime options is AUTOMATICALLY the hyphen.
1570: .seealso: [](ch_snes), `SNES`, `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1571: @*/
1572: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1573: {
1574: PetscFunctionBegin;
1576: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix));
1577: PetscFunctionReturn(PETSC_SUCCESS);
1578: }
1580: /*@
1581: SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1582: SNESLineSearch options in the database.
1584: Not Collective
1586: Input Parameter:
1587: . linesearch - the `SNESLineSearch` context
1589: Output Parameter:
1590: . prefix - pointer to the prefix string used
1592: Level: advanced
1594: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1595: @*/
1596: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1597: {
1598: PetscFunctionBegin;
1600: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix));
1601: PetscFunctionReturn(PETSC_SUCCESS);
1602: }
1604: /*@C
1605: SNESLineSearchSetWorkVecs - Sets work vectors for the line search.
1607: Input Parameters:
1608: + linesearch - the `SNESLineSearch` context
1609: - nwork - the number of work vectors
1611: Level: developer
1613: Developer Note:
1614: This is called from within the set up routines for each of the line search types `SNESLineSearchType`
1616: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetWorkVecs()`
1617: @*/
1618: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1619: {
1620: PetscFunctionBegin;
1621: PetscCheck(linesearch->vec_sol, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1622: PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1623: PetscFunctionReturn(PETSC_SUCCESS);
1624: }
1626: /*@
1627: SNESLineSearchGetReason - Gets the success/failure status of the last line search application
1629: Input Parameter:
1630: . linesearch - the line search context
1632: Output Parameter:
1633: . result - The success or failure status
1635: Level: developer
1637: Note:
1638: This is typically called after `SNESLineSearchApply()` in order to determine if the line search failed
1639: (and set into the `SNES` convergence accordingly).
1641: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1642: @*/
1643: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1644: {
1645: PetscFunctionBegin;
1647: PetscAssertPointer(result, 2);
1648: *result = linesearch->result;
1649: PetscFunctionReturn(PETSC_SUCCESS);
1650: }
1652: /*@
1653: SNESLineSearchSetReason - Sets the success/failure status of the line search application
1655: Logically Collective; No Fortran Support
1657: Input Parameters:
1658: + linesearch - the line search context
1659: - result - The success or failure status
1661: Level: developer
1663: Note:
1664: This is typically called in a `SNESLineSearchType` implementation of `SNESLineSearchApply()` or a `SNESLINESEARCHSHELL` implementation to set
1665: the success or failure of the line search method.
1667: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`
1668: @*/
1669: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1670: {
1671: PetscFunctionBegin;
1673: linesearch->result = result;
1674: PetscFunctionReturn(PETSC_SUCCESS);
1675: }
1677: // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
1678: /*@C
1679: SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.
1681: Logically Collective
1683: Input Parameters:
1684: + linesearch - the linesearch object
1685: . projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1686: . normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn` for calling sequence
1687: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence
1689: Level: advanced
1691: Notes:
1692: The VI solvers require projection of the solution to the feasible set. `projectfunc` should implement this.
1694: The VI solvers require special evaluation of the function norm such that the norm is only calculated
1695: on the inactive set. This should be implemented by `normfunc`.
1697: The VI solvers further require special evaluation of the directional derivative (when assuming that there exists some $G(x)$
1698: for which the `SNESFunctionFn` $F(x) = grad G(x)$) such that it is only calculated on the inactive set.
1699: This should be implemented by `dirderivfunc`.
1701: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`,
1702: `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`, `SNESLineSearchVIDirDerivFn`
1703: @*/
1704: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn *projectfunc, SNESLineSearchVINormFn *normfunc, SNESLineSearchVIDirDerivFn *dirderivfunc)
1705: {
1706: PetscFunctionBegin;
1708: if (projectfunc) linesearch->ops->viproject = projectfunc;
1709: if (normfunc) linesearch->ops->vinorm = normfunc;
1710: if (dirderivfunc) linesearch->ops->vidirderiv = dirderivfunc;
1711: PetscFunctionReturn(PETSC_SUCCESS);
1712: }
1714: /*@C
1715: SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.
1717: Not Collective
1719: Input Parameter:
1720: . linesearch - the line search context, obtain with `SNESGetLineSearch()`
1722: Output Parameters:
1723: + projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1724: . normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn ` for calling sequence
1725: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence
1727: Level: advanced
1729: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
1730: `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`
1731: @*/
1732: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn **projectfunc, SNESLineSearchVINormFn **normfunc, SNESLineSearchVIDirDerivFn **dirderivfunc)
1733: {
1734: PetscFunctionBegin;
1735: if (projectfunc) *projectfunc = linesearch->ops->viproject;
1736: if (normfunc) *normfunc = linesearch->ops->vinorm;
1737: if (dirderivfunc) *dirderivfunc = linesearch->ops->vidirderiv;
1738: PetscFunctionReturn(PETSC_SUCCESS);
1739: }
1741: /*@C
1742: SNESLineSearchRegister - register a line search type `SNESLineSearchType`
1744: Logically Collective, No Fortran Support
1746: Input Parameters:
1747: + sname - name of the `SNESLineSearchType()`
1748: - function - the creation function for that type
1750: Calling sequence of `function`:
1751: . ls - the line search context
1753: Level: advanced
1755: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1756: @*/
1757: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch ls))
1758: {
1759: PetscFunctionBegin;
1760: PetscCall(SNESInitializePackage());
1761: PetscCall(PetscFunctionListAdd(&SNESLineSearchList, sname, function));
1762: PetscFunctionReturn(PETSC_SUCCESS);
1763: }