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, sizeof(type), &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: SNESLineSearchViewFromOptions - View a `SNESLineSearch` object based on values in the options database
882: Collective
884: Input Parameters:
885: + A - the `SNESLineSearch` context
886: . obj - optional object that provides the prefix for the option names, pass `NULL` to use the options prefix of `A`
887: - name - command line option
889: Options Database Key:
890: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`
892: Level: intermediate
894: Note:
895: This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
896: rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.
898: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchView()`, `PetscObjectViewFromOptions()`, `SNESLineSearchCreate()`, `PetscOptionsCreateViewer()`
899: @*/
900: PetscErrorCode SNESLineSearchViewFromOptions(SNESLineSearch A, PetscObject obj, const char name[])
901: {
902: PetscFunctionBegin;
904: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
905: PetscFunctionReturn(PETSC_SUCCESS);
906: }
908: /*@
909: SNESLineSearchView - Prints useful information about the line search
911: Logically Collective
913: Input Parameters:
914: + linesearch - line search context
915: - viewer - the `PetscViewer` to display the line search information to
917: Level: intermediate
919: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`, `SNESLineSearchViewFromOptions()`
920: @*/
921: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
922: {
923: PetscBool isascii;
925: PetscFunctionBegin;
927: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer));
929: PetscCheckSameComm(linesearch, 1, viewer, 2);
931: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
932: if (isascii) {
933: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer));
934: PetscCall(PetscViewerASCIIPushTab(viewer));
935: PetscTryTypeMethod(linesearch, view, viewer);
936: PetscCall(PetscViewerASCIIPopTab(viewer));
937: PetscCall(PetscViewerASCIIPrintf(viewer, " maxlambda=%e, minlambda=%e\n", (double)linesearch->maxlambda, (double)linesearch->minlambda));
938: PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol));
939: PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT "\n", linesearch->max_it));
940: if (linesearch->ops->precheck) {
941: if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
942: PetscCall(PetscViewerASCIIPrintf(viewer, " using precheck step to speed up Picard convergence\n"));
943: } else {
944: PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined precheck step\n"));
945: }
946: }
947: if (linesearch->ops->postcheck) PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined postcheck step\n"));
948: }
949: PetscFunctionReturn(PETSC_SUCCESS);
950: }
952: /*@
953: SNESLineSearchGetType - Gets the `SNESLinesearchType` of a `SNESLineSearch`
955: Logically Collective
957: Input Parameter:
958: . linesearch - the line search context
960: Output Parameter:
961: . type - The type of line search, or `NULL` if not set
963: Level: intermediate
965: Note:
966: `type` should not be retained for later use as it will be an invalid pointer if the `SNESLineSearchType` of `linesearch` is changed.
968: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`,
969: `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
970: @*/
971: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
972: {
973: PetscFunctionBegin;
975: PetscAssertPointer(type, 2);
976: *type = ((PetscObject)linesearch)->type_name;
977: PetscFunctionReturn(PETSC_SUCCESS);
978: }
980: /*@
981: SNESLineSearchSetType - Sets the `SNESLinesearchType` of a `SNESLineSearch` object to indicate the line search algorithm that should be used by a given `SNES` solver
983: Logically Collective
985: Input Parameters:
986: + linesearch - the line search context
987: - type - The type of line search to be used, see `SNESLineSearchType`
989: Options Database Key:
990: . -snes_linesearch_type (none|bt|secant|cp|nleqerr|bisection|shell) - Line search type to use, see `SNESLineSearchType`
992: Level: intermediate
994: Note:
995: The `SNESLineSearch` object is generally obtained with `SNESGetLineSearch()`
997: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`,
998: `SNESGetLineSearch()`
999: @*/
1000: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
1001: {
1002: PetscBool match;
1003: PetscErrorCode (*r)(SNESLineSearch);
1005: PetscFunctionBegin;
1007: PetscAssertPointer(type, 2);
1009: PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, type, &match));
1010: if (match) PetscFunctionReturn(PETSC_SUCCESS);
1012: PetscCall(PetscFunctionListFind(SNESLineSearchList, type, &r));
1013: PetscCheck(r, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Line Search type %s", type);
1014: /* Destroy the previous private line search context */
1015: PetscTryTypeMethod(linesearch, destroy);
1016: linesearch->ops->destroy = NULL;
1017: /* Reinitialize function pointers in SNESLineSearchOps structure */
1018: linesearch->ops->apply = NULL;
1019: linesearch->ops->view = NULL;
1020: linesearch->ops->setfromoptions = NULL;
1021: linesearch->ops->destroy = NULL;
1023: PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch, type));
1024: PetscCall((*r)(linesearch));
1025: PetscFunctionReturn(PETSC_SUCCESS);
1026: }
1028: /*@
1029: SNESLineSearchSetSNES - Sets the `SNES` for the line search for function evaluation.
1031: Input Parameters:
1032: + linesearch - the line search context
1033: - snes - The `SNES` instance
1035: Level: developer
1037: Note:
1038: This happens automatically when the line search is obtained/created with
1039: `SNESGetLineSearch()`. This routine is therefore mainly called within `SNES`
1040: implementations.
1042: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`
1043: @*/
1044: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
1045: {
1046: PetscFunctionBegin;
1049: linesearch->snes = snes;
1050: PetscFunctionReturn(PETSC_SUCCESS);
1051: }
1053: /*@
1054: SNESLineSearchGetSNES - Gets the `SNES` instance associated with the line search.
1056: Not Collective
1058: Input Parameter:
1059: . linesearch - the line search context
1061: Output Parameter:
1062: . snes - The `SNES` instance
1064: Level: developer
1066: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESType`, `SNESLineSearchSetVecs()`
1067: @*/
1068: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
1069: {
1070: PetscFunctionBegin;
1072: PetscAssertPointer(snes, 2);
1073: *snes = linesearch->snes;
1074: PetscFunctionReturn(PETSC_SUCCESS);
1075: }
1077: /*@
1078: SNESLineSearchGetLambda - Gets the last line search `lambda` used
1080: Not Collective
1082: Input Parameter:
1083: . linesearch - the line search context
1085: Output Parameter:
1086: . lambda - The last `lambda` (scaling of the solution update) computed during `SNESLineSearchApply()`
1088: Level: advanced
1090: Note:
1091: This is useful in methods where the solver is ill-scaled and
1092: requires some adaptive notion of the difference in scale between the
1093: solution and the function. For instance, `SNESQN` may be scaled by the
1094: line search `lambda` using the argument `-snes_qn_scaling ls`.
1096: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1097: @*/
1098: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1099: {
1100: PetscFunctionBegin;
1102: PetscAssertPointer(lambda, 2);
1103: *lambda = linesearch->lambda;
1104: PetscFunctionReturn(PETSC_SUCCESS);
1105: }
1107: /*@
1108: SNESLineSearchSetLambda - Sets the line search `lambda` (scaling of the solution update)
1110: Input Parameters:
1111: + linesearch - line search context
1112: - lambda - The `lambda` to use
1114: Level: developer
1116: Notes:
1117: This routine is typically used within implementations of `SNESLineSearchApply()`
1118: to set the final `lambda`. This routine (and `SNESLineSearchGetLambda()`) were
1119: added to facilitate Quasi-Newton methods that use the previous `lambda`
1120: as an inner scaling parameter.
1122: For `SNESLINESEARCHNONE` use `SNESLineSearchSetDamping()`, not this function.
1124: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetLambda()`, `SNESLineSearchSetDamping()`
1125: @*/
1126: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1127: {
1128: PetscFunctionBegin;
1130: linesearch->lambda = lambda;
1131: PetscFunctionReturn(PETSC_SUCCESS);
1132: }
1134: /*@
1135: SNESLineSearchGetTolerances - Gets the tolerances for the line search.
1137: Not Collective
1139: Input Parameter:
1140: . linesearch - the line search context
1142: Output Parameters:
1143: + minlambda - The minimum `lambda` allowed
1144: . maxlambda - The maximum `lambda` allowed
1145: . rtol - The relative tolerance for iterative line searches
1146: . atol - The absolute tolerance for iterative line searches
1147: . ltol - The change in `lambda` tolerance for iterative line searches
1148: - max_it - The maximum number of iterations of the line search
1150: Level: intermediate
1152: Note:
1153: Different line searches may implement these parameters slightly differently as
1154: the type requires.
1156: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1157: @*/
1158: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *minlambda, PetscReal *maxlambda, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_it)
1159: {
1160: PetscFunctionBegin;
1162: if (minlambda) {
1163: PetscAssertPointer(minlambda, 2);
1164: *minlambda = linesearch->minlambda;
1165: }
1166: if (maxlambda) {
1167: PetscAssertPointer(maxlambda, 3);
1168: *maxlambda = linesearch->maxlambda;
1169: }
1170: if (rtol) {
1171: PetscAssertPointer(rtol, 4);
1172: *rtol = linesearch->rtol;
1173: }
1174: if (atol) {
1175: PetscAssertPointer(atol, 5);
1176: *atol = linesearch->atol;
1177: }
1178: if (ltol) {
1179: PetscAssertPointer(ltol, 6);
1180: *ltol = linesearch->ltol;
1181: }
1182: if (max_it) {
1183: PetscAssertPointer(max_it, 7);
1184: *max_it = linesearch->max_it;
1185: }
1186: PetscFunctionReturn(PETSC_SUCCESS);
1187: }
1189: /*@
1190: SNESLineSearchSetTolerances - Sets the tolerances for the linesearch.
1192: Collective
1194: Input Parameters:
1195: + linesearch - The line search context
1196: . minlambda - The minimum `lambda` allowed
1197: . maxlambda - The maximum `lambda` allowed
1198: . rtol - The relative tolerance for iterative line searches
1199: . atol - The absolute tolerance for iterative line searches
1200: . ltol - The change in `lambda` tolerance for iterative line searches
1201: - max_it - The maximum number of iterations of the line search
1203: Options Database Keys:
1204: + -snes_linesearch_minlambda - The minimum `lambda` allowed
1205: . -snes_linesearch_maxlambda - The maximum `lambda` allowed
1206: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
1207: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
1208: . -snes_linesearch_ltol - Change in `lambda` tolerance for iterative line searches
1209: - -snes_linesearch_max_it - The number of iterations for iterative line searches
1211: Level: intermediate
1213: Note:
1214: The user may choose to not set any of the tolerances using `PETSC_DEFAULT` in place of an argument.
1216: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1217: @*/
1218: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal minlambda, PetscReal maxlambda, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_it)
1219: {
1220: PetscFunctionBegin;
1229: if (minlambda != (PetscReal)PETSC_DEFAULT) {
1230: PetscCheck(minlambda >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum lambda %14.12e must be non-negative", (double)minlambda);
1231: 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);
1232: linesearch->minlambda = minlambda;
1233: }
1235: if (maxlambda != (PetscReal)PETSC_DEFAULT) {
1236: PetscCheck(maxlambda > 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum lambda %14.12e must be positive", (double)maxlambda);
1237: linesearch->maxlambda = maxlambda;
1238: }
1240: if (rtol != (PetscReal)PETSC_DEFAULT) {
1241: 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);
1242: linesearch->rtol = rtol;
1243: }
1245: if (atol != (PetscReal)PETSC_DEFAULT) {
1246: PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %14.12e must be non-negative", (double)atol);
1247: linesearch->atol = atol;
1248: }
1250: if (ltol != (PetscReal)PETSC_DEFAULT) {
1251: PetscCheck(ltol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Lambda tolerance %14.12e must be non-negative", (double)ltol);
1252: linesearch->ltol = ltol;
1253: }
1255: if (max_it != PETSC_DEFAULT) {
1256: PetscCheck(max_it >= 0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", max_it);
1257: linesearch->max_it = max_it;
1258: }
1259: PetscFunctionReturn(PETSC_SUCCESS);
1260: }
1262: /*@
1263: SNESLineSearchGetDamping - Gets the line search damping parameter.
1265: Input Parameter:
1266: . linesearch - The line search context
1268: Output Parameter:
1269: . damping - The damping parameter
1271: Level: advanced
1273: .seealso: [](ch_snes), `SNES`, `SNESLineSearchGetStepTolerance()`, `SNESQN`
1274: @*/
1275: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1276: {
1277: PetscFunctionBegin;
1279: PetscAssertPointer(damping, 2);
1280: *damping = linesearch->damping;
1281: PetscFunctionReturn(PETSC_SUCCESS);
1282: }
1284: /*@
1285: SNESLineSearchSetDamping - Sets the line search damping parameter.
1287: Input Parameters:
1288: + linesearch - the line search context
1289: - damping - The damping parameter
1291: Options Database Key:
1292: . -snes_linesearch_damping damping - the damping value
1294: Level: intermediate
1296: Note:
1297: The `SNESLINESEARCHNONE` line search merely takes the update step scaled by the damping parameter.
1298: The use of the damping parameter in the `SNESLINESEARCHSECANT` and `SNESLINESEARCHCP` line searches is much more subtle;
1299: it is used as a starting point for the secant method. Depending on the choice for `maxlambda`,
1300: the eventual `lambda` may be greater than the damping parameter however.
1301: For `SNESLINESEARCHBISECTION` and `SNESLINESEARCHBT` the damping is instead used as the initial guess,
1302: below which the line search will not go. Hence, it is the maximum possible value for `lambda`.
1304: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetDamping()`, `SNESLineSearchSetLambda()`
1305: @*/
1306: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1307: {
1308: PetscFunctionBegin;
1310: linesearch->damping = damping;
1311: PetscFunctionReturn(PETSC_SUCCESS);
1312: }
1314: /*@
1315: SNESLineSearchGetOrder - Gets the line search approximation order.
1317: Input Parameter:
1318: . linesearch - The line search context
1320: Output Parameter:
1321: . order - The order
1323: Level: intermediate
1325: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetOrder()`
1326: @*/
1327: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1328: {
1329: PetscFunctionBegin;
1331: PetscAssertPointer(order, 2);
1332: *order = linesearch->order;
1333: PetscFunctionReturn(PETSC_SUCCESS);
1334: }
1336: /*@
1337: SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search
1339: Input Parameters:
1340: + linesearch - The line search context
1341: - order - The order
1343: Level: intermediate
1345: Values for `order`\:
1346: + 1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1347: . 2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1348: - 3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order
1350: Options Database Key:
1351: . -snes_linesearch_order order - 1, 2, 3. Most types only support certain orders (`SNESLINESEARCHBT` supports 2 or 3)
1353: Note:
1354: These orders are supported by `SNESLINESEARCHBT` and `SNESLINESEARCHCP`
1356: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1357: @*/
1358: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1359: {
1360: PetscFunctionBegin;
1362: linesearch->order = order;
1363: PetscFunctionReturn(PETSC_SUCCESS);
1364: }
1366: /*@
1367: SNESLineSearchGetNorms - Gets the norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1369: Not Collective
1371: Input Parameter:
1372: . linesearch - The line search context
1374: Output Parameters:
1375: + xnorm - The norm of the current solution
1376: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution.
1377: - ynorm - The norm of the current update (after scaling by the linesearch computed `lambda`)
1379: Level: developer
1381: Notes:
1382: Some values may not be up-to-date at particular points in the code.
1384: This, in combination with `SNESLineSearchSetNorms()`, allow the line search and the `SNESSolve_XXX()` to share
1385: computed values.
1387: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1388: @*/
1389: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1390: {
1391: PetscFunctionBegin;
1393: if (xnorm) *xnorm = linesearch->xnorm;
1394: if (fnorm) *fnorm = linesearch->fnorm;
1395: if (ynorm) *ynorm = linesearch->ynorm;
1396: PetscFunctionReturn(PETSC_SUCCESS);
1397: }
1399: /*@
1400: SNESLineSearchSetNorms - Sets the computed norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1402: Collective
1404: Input Parameters:
1405: + linesearch - The line search context
1406: . xnorm - The norm of the current solution
1407: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution
1408: - ynorm - The norm of the current update (after scaling by the linesearch computed `lambda`)
1410: Level: developer
1412: Note:
1413: This is called by the line search routines to store the values they have just computed
1415: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1416: @*/
1417: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1418: {
1419: PetscFunctionBegin;
1421: linesearch->xnorm = xnorm;
1422: linesearch->fnorm = fnorm;
1423: linesearch->ynorm = ynorm;
1424: PetscFunctionReturn(PETSC_SUCCESS);
1425: }
1427: /*@
1428: SNESLineSearchComputeNorms - Explicitly computes the norms of the current solution `X`, the current update `Y`, and the current function value `F`.
1430: Input Parameter:
1431: . linesearch - the line search context
1433: Options Database Key:
1434: . -snes_linesearch_norms (true|false) - turn norm computation on or off
1436: Level: intermediate
1438: Developer Note:
1439: The options database key is misnamed. It should be `-snes_linesearch_compute_norms`
1441: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1442: @*/
1443: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1444: {
1445: SNES snes;
1447: PetscFunctionBegin;
1448: if (linesearch->norms) {
1449: if (linesearch->ops->vinorm) {
1450: PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1451: PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1452: PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1453: PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1454: } else {
1455: PetscCall(VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1456: PetscCall(VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1457: PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1458: PetscCall(VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1459: PetscCall(VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1460: PetscCall(VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1461: }
1462: }
1463: PetscFunctionReturn(PETSC_SUCCESS);
1464: }
1466: /*@
1467: SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.
1469: Input Parameters:
1470: + linesearch - the line search context
1471: - flg - indicates whether or not to compute norms
1473: Options Database Key:
1474: . -snes_linesearch_norms (true|false) - Turns on/off computation of the norms for the `SNESLINESEARCHNONE` line search
1476: Level: intermediate
1478: Note:
1479: This is most relevant to the `SNESLINESEARCHNONE` line search type since most line searches have a stopping criteria involving the norm.
1481: Developer Note:
1482: The options database key is misnamed. It should be `-snes_linesearch_compute_norms`
1484: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHNONE`
1485: @*/
1486: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1487: {
1488: PetscFunctionBegin;
1489: linesearch->norms = flg;
1490: PetscFunctionReturn(PETSC_SUCCESS);
1491: }
1493: /*@
1494: SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context
1496: Not Collective but the vectors are parallel
1498: Input Parameter:
1499: . linesearch - The line search context
1501: Output Parameters:
1502: + X - Solution vector
1503: . F - Function vector
1504: . Y - Search direction vector
1505: . W - Solution work vector
1506: - G - Function work vector
1508: Level: advanced
1510: Notes:
1511: At the beginning of a line search application, `X` should contain a
1512: solution and the vector `F` the function computed at `X`. At the end of the
1513: line search application, `X` should contain the new solution, and `F` the
1514: function evaluated at the new solution.
1516: These vectors are owned by the `SNESLineSearch` and should not be destroyed by the caller
1518: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1519: @*/
1520: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1521: {
1522: PetscFunctionBegin;
1524: if (X) {
1525: PetscAssertPointer(X, 2);
1526: *X = linesearch->vec_sol;
1527: }
1528: if (F) {
1529: PetscAssertPointer(F, 3);
1530: *F = linesearch->vec_func;
1531: }
1532: if (Y) {
1533: PetscAssertPointer(Y, 4);
1534: *Y = linesearch->vec_update;
1535: }
1536: if (W) {
1537: PetscAssertPointer(W, 5);
1538: *W = linesearch->vec_sol_new;
1539: }
1540: if (G) {
1541: PetscAssertPointer(G, 6);
1542: *G = linesearch->vec_func_new;
1543: }
1544: PetscFunctionReturn(PETSC_SUCCESS);
1545: }
1547: /*@
1548: SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context
1550: Logically Collective
1552: Input Parameters:
1553: + linesearch - The line search context
1554: . X - Solution vector
1555: . F - Function vector
1556: . Y - Search direction vector
1557: . W - Solution work vector
1558: - G - Function work vector
1560: Level: developer
1562: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1563: @*/
1564: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1565: {
1566: PetscFunctionBegin;
1568: if (X) {
1570: linesearch->vec_sol = X;
1571: }
1572: if (F) {
1574: linesearch->vec_func = F;
1575: }
1576: if (Y) {
1578: linesearch->vec_update = Y;
1579: }
1580: if (W) {
1582: linesearch->vec_sol_new = W;
1583: }
1584: if (G) {
1586: linesearch->vec_func_new = G;
1587: }
1588: PetscFunctionReturn(PETSC_SUCCESS);
1589: }
1591: /*@
1592: SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1593: `SNESLineSearch` options in the database.
1595: Logically Collective
1597: Input Parameters:
1598: + linesearch - the `SNESLineSearch` context
1599: - prefix - the prefix to prepend to all option names
1601: Level: advanced
1603: Note:
1604: A hyphen (-) must NOT be given at the beginning of the prefix name.
1605: The first character of all runtime options is AUTOMATICALLY the hyphen.
1607: .seealso: [](ch_snes), `SNES`, `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1608: @*/
1609: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1610: {
1611: PetscFunctionBegin;
1613: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix));
1614: PetscFunctionReturn(PETSC_SUCCESS);
1615: }
1617: /*@
1618: SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1619: SNESLineSearch options in the database.
1621: Not Collective
1623: Input Parameter:
1624: . linesearch - the `SNESLineSearch` context
1626: Output Parameter:
1627: . prefix - pointer to the prefix string used
1629: Level: advanced
1631: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1632: @*/
1633: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1634: {
1635: PetscFunctionBegin;
1637: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix));
1638: PetscFunctionReturn(PETSC_SUCCESS);
1639: }
1641: /*@
1642: SNESLineSearchSetWorkVecs - Sets work vectors for the line search.
1644: Input Parameters:
1645: + linesearch - the `SNESLineSearch` context
1646: - nwork - the number of work vectors
1648: Level: developer
1650: Developer Note:
1651: This is called from within the set up routines for each of the line search types `SNESLineSearchType`
1653: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetWorkVecs()`
1654: @*/
1655: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1656: {
1657: PetscFunctionBegin;
1658: PetscCheck(linesearch->vec_sol, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1659: PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1660: PetscFunctionReturn(PETSC_SUCCESS);
1661: }
1663: /*@
1664: SNESLineSearchGetReason - Gets the success/failure status of the last line search application
1666: Input Parameter:
1667: . linesearch - The line search context
1669: Output Parameter:
1670: . reason - The success or failure status
1672: Level: developer
1674: Note:
1675: This is typically called after `SNESLineSearchApply()` in order to determine if the line search failed
1676: (and set into the `SNES` convergence accordingly).
1678: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1679: @*/
1680: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *reason)
1681: {
1682: PetscFunctionBegin;
1684: PetscAssertPointer(reason, 2);
1685: *reason = linesearch->reason;
1686: PetscFunctionReturn(PETSC_SUCCESS);
1687: }
1689: /*@
1690: SNESLineSearchSetReason - Sets the success/failure reason of the line search application
1692: Logically Collective; No Fortran Support
1694: Input Parameters:
1695: + linesearch - The line search context
1696: - reason - The success or failure reason
1698: Level: developer
1700: Notes:
1701: This is typically called in a `SNESLineSearchType` implementation of `SNESLineSearchApply()` or a `SNESLINESEARCHSHELL` implementation to set
1702: the success or failure of the line search method.
1704: Do not call this from callbacks provided with `SNESSetFunction()`, instead perhaps use `SNESSetFunctionDomainError()`
1706: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`, `SNESSetFunctionDomainError()`, `SNESSetFunction()`
1707: @*/
1708: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason reason)
1709: {
1710: PetscFunctionBegin;
1712: linesearch->reason = reason;
1713: PetscFunctionReturn(PETSC_SUCCESS);
1714: }
1716: // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
1717: /*@
1718: SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.
1720: Logically Collective
1722: Input Parameters:
1723: + linesearch - the linesearch object
1724: . projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1725: . normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn` for calling sequence
1726: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence
1728: Level: advanced
1730: Notes:
1731: The VI solvers require projection of the solution to the feasible set. `projectfunc` should implement this.
1733: The VI solvers require special evaluation of the function norm such that the norm is only calculated
1734: on the inactive set. This should be implemented by `normfunc`.
1736: The VI solvers further require special evaluation of the directional derivative (when assuming that there exists some $G(x)$
1737: for which the `SNESFunctionFn` $F(x) = grad G(x)$) such that it is only calculated on the inactive set.
1738: This should be implemented by `dirderivfunc`.
1740: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`,
1741: `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`, `SNESLineSearchVIDirDerivFn`
1742: @*/
1743: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn *projectfunc, SNESLineSearchVINormFn *normfunc, SNESLineSearchVIDirDerivFn *dirderivfunc)
1744: {
1745: PetscFunctionBegin;
1747: if (projectfunc) linesearch->ops->viproject = projectfunc;
1748: if (normfunc) linesearch->ops->vinorm = normfunc;
1749: if (dirderivfunc) linesearch->ops->vidirderiv = dirderivfunc;
1750: PetscFunctionReturn(PETSC_SUCCESS);
1751: }
1753: /*@
1754: SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.
1756: Not Collective
1758: Input Parameter:
1759: . linesearch - the line search context, obtain with `SNESGetLineSearch()`
1761: Output Parameters:
1762: + projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1763: . normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn ` for calling sequence
1764: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence
1766: Level: advanced
1768: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
1769: `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`
1770: @*/
1771: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn **projectfunc, SNESLineSearchVINormFn **normfunc, SNESLineSearchVIDirDerivFn **dirderivfunc)
1772: {
1773: PetscFunctionBegin;
1774: if (projectfunc) *projectfunc = linesearch->ops->viproject;
1775: if (normfunc) *normfunc = linesearch->ops->vinorm;
1776: if (dirderivfunc) *dirderivfunc = linesearch->ops->vidirderiv;
1777: PetscFunctionReturn(PETSC_SUCCESS);
1778: }
1780: /*@
1781: SNESLineSearchRegister - register a line search type `SNESLineSearchType`
1783: Logically Collective, No Fortran Support
1785: Input Parameters:
1786: + sname - name of the `SNESLineSearchType()`
1787: - function - the creation function for that type
1789: Calling sequence of `function`:
1790: . ls - the line search context
1792: Level: advanced
1794: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1795: @*/
1796: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch ls))
1797: {
1798: PetscFunctionBegin;
1799: PetscCall(SNESInitializePackage());
1800: PetscCall(PetscFunctionListAdd(&SNESLineSearchList, sname, function));
1801: PetscFunctionReturn(PETSC_SUCCESS);
1802: }