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: PetscInt i;
102: PetscBool identical;
104: PetscFunctionBegin;
106: for (i = 0; i < ls->numbermonitors; i++) {
107: PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))ls->monitorftns[i], ls->monitorcontext[i], ls->monitordestroy[i], &identical));
108: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
109: }
110: PetscCheck(ls->numbermonitors < MAXSNESLSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
111: ls->monitorftns[ls->numbermonitors] = f;
112: ls->monitordestroy[ls->numbermonitors] = monitordestroy;
113: ls->monitorcontext[ls->numbermonitors++] = mctx;
114: PetscFunctionReturn(PETSC_SUCCESS);
115: }
117: /*@C
118: SNESLineSearchMonitorSolutionUpdate - Monitors each update of the function value the linesearch tries
120: Collective
122: Input Parameters:
123: + ls - the `SNESLineSearch` object
124: - vf - the context for the monitor, in this case it is an `PetscViewerAndFormat`
126: Options Database Key:
127: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
129: Level: developer
131: This is not normally called directly but is passed to `SNESLineSearchMonitorSet()`
133: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorSet()`, `SNESMonitorSolution()`
134: @*/
135: PetscErrorCode SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls, PetscViewerAndFormat *vf)
136: {
137: PetscViewer viewer = vf->viewer;
138: Vec Y, W, G;
140: PetscFunctionBegin;
141: PetscCall(SNESLineSearchGetVecs(ls, NULL, NULL, &Y, &W, &G));
142: PetscCall(PetscViewerPushFormat(viewer, vf->format));
143: PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted update to solution \n"));
144: PetscCall(VecView(Y, viewer));
145: PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted new solution \n"));
146: PetscCall(VecView(W, viewer));
147: PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted updated function value\n"));
148: PetscCall(VecView(G, viewer));
149: PetscCall(PetscViewerPopFormat(viewer));
150: PetscFunctionReturn(PETSC_SUCCESS);
151: }
153: /*@
154: SNESLineSearchCreate - Creates a `SNESLineSearch` context.
156: Logically Collective
158: Input Parameter:
159: . comm - MPI communicator for the line search (typically from the associated `SNES` context).
161: Output Parameter:
162: . outlinesearch - the new line search context
164: Level: developer
166: Note:
167: The preferred calling sequence is to use `SNESGetLineSearch()` to acquire the `SNESLineSearch` instance
168: already associated with the `SNES`.
170: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `LineSearchDestroy()`, `SNESGetLineSearch()`
171: @*/
172: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
173: {
174: SNESLineSearch linesearch;
176: PetscFunctionBegin;
177: PetscAssertPointer(outlinesearch, 2);
178: PetscCall(SNESInitializePackage());
180: PetscCall(PetscHeaderCreate(linesearch, SNESLINESEARCH_CLASSID, "SNESLineSearch", "Linesearch", "SNESLineSearch", comm, SNESLineSearchDestroy, SNESLineSearchView));
181: linesearch->vec_sol_new = NULL;
182: linesearch->vec_func_new = NULL;
183: linesearch->vec_sol = NULL;
184: linesearch->vec_func = NULL;
185: linesearch->vec_update = NULL;
187: linesearch->lambda = 1.0;
188: linesearch->fnorm = 1.0;
189: linesearch->ynorm = 1.0;
190: linesearch->xnorm = 1.0;
191: linesearch->result = SNES_LINESEARCH_SUCCEEDED;
192: linesearch->norms = PETSC_TRUE;
193: linesearch->keeplambda = PETSC_FALSE;
194: linesearch->damping = 1.0;
195: linesearch->maxstep = 1e8;
196: linesearch->steptol = 1e-12;
197: linesearch->rtol = 1e-8;
198: linesearch->atol = 1e-15;
199: linesearch->ltol = 1e-8;
200: linesearch->precheckctx = NULL;
201: linesearch->postcheckctx = NULL;
202: linesearch->max_its = 1;
203: linesearch->setupcalled = PETSC_FALSE;
204: linesearch->monitor = NULL;
205: *outlinesearch = linesearch;
206: PetscFunctionReturn(PETSC_SUCCESS);
207: }
209: /*@
210: SNESLineSearchSetUp - Prepares the line search for being applied by allocating
211: any required vectors.
213: Collective
215: Input Parameter:
216: . linesearch - The `SNESLineSearch` instance.
218: Level: advanced
220: Note:
221: For most cases, this needn't be called by users or outside of `SNESLineSearchApply()`.
222: The only current case where this is called outside of this is for the VI
223: solvers, which modify the solution and work vectors before the first call
224: of `SNESLineSearchApply()`, requiring the `SNESLineSearch` work vectors to be
225: allocated upfront.
227: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchReset()`
228: @*/
229: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
230: {
231: PetscFunctionBegin;
232: if (!((PetscObject)linesearch)->type_name) PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC));
233: if (!linesearch->setupcalled) {
234: if (!linesearch->vec_sol_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new));
235: if (!linesearch->vec_func_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new));
236: PetscTryTypeMethod(linesearch, setup);
237: if (!linesearch->ops->snesfunc) PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunction));
238: linesearch->lambda = linesearch->damping;
239: linesearch->setupcalled = PETSC_TRUE;
240: }
241: PetscFunctionReturn(PETSC_SUCCESS);
242: }
244: /*@
245: SNESLineSearchReset - Undoes the `SNESLineSearchSetUp()` and deletes any `Vec`s or `Mat`s allocated by the line search.
247: Collective
249: Input Parameter:
250: . linesearch - The `SNESLineSearch` instance.
252: Level: developer
254: Note:
255: Usually only called by `SNESReset()`
257: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetUp()`
258: @*/
259: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
260: {
261: PetscFunctionBegin;
262: PetscTryTypeMethod(linesearch, reset);
264: PetscCall(VecDestroy(&linesearch->vec_sol_new));
265: PetscCall(VecDestroy(&linesearch->vec_func_new));
267: PetscCall(VecDestroyVecs(linesearch->nwork, &linesearch->work));
269: linesearch->nwork = 0;
270: linesearch->setupcalled = PETSC_FALSE;
271: PetscFunctionReturn(PETSC_SUCCESS);
272: }
274: /*@C
275: SNESLineSearchSetFunction - Sets the function evaluation used by the `SNES` line search
276: `
278: Input Parameters:
279: + linesearch - the `SNESLineSearch` context
280: - func - function evaluation routine, this is usually the function provided with `SNESSetFunction()`
282: Calling sequence of `func`:
283: + snes - the `SNES` with which the `SNESLineSearch` context is associated with
284: . x - the input vector
285: - f - the computed value of the function
287: Level: developer
289: Note:
290: By default the `SNESLineSearch` uses the function provided by `SNESSetFunction()` so this is rarely needed
292: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESSetFunction()`
293: @*/
294: PetscErrorCode SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES snes, Vec x, Vec f))
295: {
296: PetscFunctionBegin;
298: linesearch->ops->snesfunc = func;
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
302: /*@C
303: SNESLineSearchSetPreCheck - Sets a function that is called after the initial search direction has been computed but
304: before the line search routine has been applied. Allows adjusting the result of (usually a linear solve) that
305: determined the search direction.
307: Logically Collective
309: Input Parameters:
310: + linesearch - the `SNESLineSearch` context
311: . func - [optional] function evaluation routine
312: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
314: Calling sequence of `func`:
315: + ls - the `SNESLineSearch` context
316: . x - the current solution
317: . d - the current search direction
318: . changed_d - indicates if the search direction has been changed
319: - ctx - the context passed to `SNESLineSearchSetPreCheck()`
321: Level: intermediate
323: Note:
324: Use `SNESLineSearchSetPostCheck()` to change the step after the line search is complete.
326: Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
328: .seealso: [](ch_snes), `SNES`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
329: `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()`
331: @*/
332: PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, PetscBool *changed_d, void *ctx), void *ctx)
333: {
334: PetscFunctionBegin;
336: if (func) linesearch->ops->precheck = func;
337: if (ctx) linesearch->precheckctx = ctx;
338: PetscFunctionReturn(PETSC_SUCCESS);
339: }
341: /*@C
342: SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.
344: Input Parameter:
345: . linesearch - the `SNESLineSearch` context
347: Output Parameters:
348: + func - [optional] function evaluation routine, for calling sequence see `SNESLineSearchSetPreCheck()`
349: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
351: Level: intermediate
353: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
354: @*/
355: PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void **ctx)
356: {
357: PetscFunctionBegin;
359: if (func) *func = linesearch->ops->precheck;
360: if (ctx) *ctx = linesearch->precheckctx;
361: PetscFunctionReturn(PETSC_SUCCESS);
362: }
364: /*@C
365: SNESLineSearchSetPostCheck - Sets a user function that is called after the line search has been applied to determine the step
366: direction and length. Allows the user a chance to change or override the decision of the line search routine
368: Logically Collective
370: Input Parameters:
371: + linesearch - the `SNESLineSearch` context
372: . func - [optional] function evaluation routine
373: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
375: Calling sequence of `func`:
376: + ls - the `SNESLineSearch` context
377: . x - the current solution
378: . d - the current search direction
379: . w - $ w = x + lambda*d $ for some lambda
380: . changed_d - indicates if the search direction `d` has been changed
381: . changed_w - indicates `w` has been changed
382: - ctx - the context passed to `SNESLineSearchSetPreCheck()`
384: Level: intermediate
386: Notes:
387: Use `SNESLineSearchSetPreCheck()` to change the step before the line search is completed.
388: The calling sequence of the callback does not contain the current scaling factor. To access the value, use `SNESLineSearchGetLambda()`.
390: Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
392: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
393: `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()`
394: @*/
395: PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, Vec w, PetscBool *changed_d, PetscBool *changed_w, void *ctx), void *ctx)
396: {
397: PetscFunctionBegin;
399: if (func) linesearch->ops->postcheck = func;
400: if (ctx) linesearch->postcheckctx = ctx;
401: PetscFunctionReturn(PETSC_SUCCESS);
402: }
404: /*@C
405: SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.
407: Input Parameter:
408: . linesearch - the `SNESLineSearch` context
410: Output Parameters:
411: + func - [optional] function evaluation routine, see for the calling sequence `SNESLineSearchSetPostCheck()`
412: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
414: Level: intermediate
416: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
417: @*/
418: PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void **ctx)
419: {
420: PetscFunctionBegin;
422: if (func) *func = linesearch->ops->postcheck;
423: if (ctx) *ctx = linesearch->postcheckctx;
424: PetscFunctionReturn(PETSC_SUCCESS);
425: }
427: /*@
428: SNESLineSearchPreCheck - Prepares the line search for being applied.
430: Logically Collective
432: Input Parameters:
433: + linesearch - The linesearch instance.
434: . X - The current solution
435: - Y - The step direction
437: Output Parameter:
438: . changed - Indicator that the precheck routine has changed `Y`
440: Level: advanced
442: Note:
443: This calls any function provided with `SNESLineSearchSetPreCheck()` and is called automatically inside the line search routines
445: Developer Note:
446: The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided
448: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
449: `SNESLineSearchGetPostCheck()`
450: @*/
451: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed)
452: {
453: PetscFunctionBegin;
454: *changed = PETSC_FALSE;
455: if (linesearch->ops->precheck) {
456: PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
458: }
459: PetscFunctionReturn(PETSC_SUCCESS);
460: }
462: /*@
463: SNESLineSearchPostCheck - Hook to modify step direction or updated solution after a successful linesearch
465: Logically Collective
467: Input Parameters:
468: + linesearch - The line search context
469: . X - The last solution
470: . Y - The step direction
471: - W - The updated solution, `W = X - lambda * Y` for some lambda
473: Output Parameters:
474: + changed_Y - Indicator if the direction `Y` has been changed.
475: - changed_W - Indicator if the new candidate solution `W` has been changed.
477: Level: developer
479: Note:
480: This calls any function provided with `SNESLineSearchSetPostCheck()` and is called automatically inside the line search routines
482: Developer Note:
483: The use of `PetscObjectGetState()` would eliminate the need for the `changed_Y` and `changed_W` arguments to be provided
485: .seealso: [](ch_snes), `SNES`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
486: @*/
487: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W)
488: {
489: PetscFunctionBegin;
490: *changed_Y = PETSC_FALSE;
491: *changed_W = PETSC_FALSE;
492: if (linesearch->ops->postcheck) {
493: PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
496: }
497: PetscFunctionReturn(PETSC_SUCCESS);
498: }
500: /*@C
501: SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration {cite}`hindmarsh1996time`
503: Logically Collective
505: Input Parameters:
506: + linesearch - the line search context
507: . X - base state for this step
508: - ctx - context for this function
510: Input/Output Parameter:
511: . Y - correction, possibly modified
513: Output Parameter:
514: . changed - flag indicating that `Y` was modified
516: Options Database Keys:
517: + -snes_linesearch_precheck_picard - activate this routine
518: - -snes_linesearch_precheck_picard_angle - angle
520: Level: advanced
522: Notes:
523: This function should be passed to `SNESLineSearchSetPreCheck()`
525: The justification for this method involves the linear convergence of a Picard iteration
526: so the Picard linearization should be provided in place of the "Jacobian" {cite}`hindmarsh1996time`. This correction
527: is generally not useful when using a Newton linearization.
529: Developer Note:
530: The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided
532: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetPicard()`, `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
533: @*/
534: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, void *ctx)
535: {
536: PetscReal angle = *(PetscReal *)linesearch->precheckctx;
537: Vec Ylast;
538: PetscScalar dot;
539: PetscInt iter;
540: PetscReal ynorm, ylastnorm, theta, angle_radians;
541: SNES snes;
543: PetscFunctionBegin;
544: PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
545: PetscCall(PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast));
546: if (!Ylast) {
547: PetscCall(VecDuplicate(Y, &Ylast));
548: PetscCall(PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast));
549: PetscCall(PetscObjectDereference((PetscObject)Ylast));
550: }
551: PetscCall(SNESGetIterationNumber(snes, &iter));
552: if (iter < 2) {
553: PetscCall(VecCopy(Y, Ylast));
554: *changed = PETSC_FALSE;
555: PetscFunctionReturn(PETSC_SUCCESS);
556: }
558: PetscCall(VecDot(Y, Ylast, &dot));
559: PetscCall(VecNorm(Y, NORM_2, &ynorm));
560: PetscCall(VecNorm(Ylast, NORM_2, &ylastnorm));
561: /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
562: theta = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
563: angle_radians = angle * PETSC_PI / 180.;
564: if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
565: /* Modify the step Y */
566: PetscReal alpha, ydiffnorm;
567: PetscCall(VecAXPY(Ylast, -1.0, Y));
568: PetscCall(VecNorm(Ylast, NORM_2, &ydiffnorm));
569: alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
570: PetscCall(VecCopy(Y, Ylast));
571: PetscCall(VecScale(Y, alpha));
572: 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));
573: *changed = PETSC_TRUE;
574: } else {
575: PetscCall(PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180 / PETSC_PI), (double)angle));
576: PetscCall(VecCopy(Y, Ylast));
577: *changed = PETSC_FALSE;
578: }
579: PetscFunctionReturn(PETSC_SUCCESS);
580: }
582: /*@
583: SNESLineSearchApply - Computes the line-search update.
585: Collective
587: Input Parameter:
588: . linesearch - The line search context
590: Input/Output Parameters:
591: + X - The current solution, on output the new solution
592: . F - The current function value, on output the new function value at the solution value `X`
593: . fnorm - The current norm of `F`, on output the new norm of `F`
594: - Y - The current search direction, on output the direction determined by the linesearch, i.e. Xnew = Xold - lambda*Y
596: Options Database Keys:
597: + -snes_linesearch_type - basic (or equivalently none), bt, l2, cp, nleqerr, bisection, shell
598: . -snes_linesearch_monitor [:filename] - Print progress of line searches
599: . -snes_linesearch_damping - The linesearch damping parameter, default is 1.0 (no damping)
600: . -snes_linesearch_norms - Turn on/off the linesearch norms computation (SNESLineSearchSetComputeNorms())
601: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
602: - -snes_linesearch_max_it - The number of iterations for iterative line searches
604: Level: intermediate
606: Notes:
607: This is typically called from within a `SNESSolve()` implementation in order to
608: help with convergence of the nonlinear method. Various `SNES` types use line searches
609: in different ways, but the overarching theme is that a line search is used to determine
610: an optimal damping parameter of a step at each iteration of the method. Each
611: application of the line search may invoke `SNESComputeFunction()` several times, and
612: therefore may be fairly expensive.
614: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchGetLambda()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
615: `SNESLineSearchType`, `SNESLineSearchSetType()`
616: @*/
617: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y)
618: {
619: PetscFunctionBegin;
625: linesearch->result = SNES_LINESEARCH_SUCCEEDED;
627: linesearch->vec_sol = X;
628: linesearch->vec_update = Y;
629: linesearch->vec_func = F;
631: PetscCall(SNESLineSearchSetUp(linesearch));
633: if (!linesearch->keeplambda) linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */
635: if (fnorm) linesearch->fnorm = *fnorm;
636: else PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm));
638: PetscCall(PetscLogEventBegin(SNESLINESEARCH_Apply, linesearch, X, F, Y));
640: PetscUseTypeMethod(linesearch, apply);
642: PetscCall(PetscLogEventEnd(SNESLINESEARCH_Apply, linesearch, X, F, Y));
644: if (fnorm) *fnorm = linesearch->fnorm;
645: PetscFunctionReturn(PETSC_SUCCESS);
646: }
648: /*@
649: SNESLineSearchDestroy - Destroys the line search instance.
651: Collective
653: Input Parameter:
654: . linesearch - The line search context
656: Level: developer
658: Note:
659: The line search in `SNES` is automatically called on `SNESDestroy()` so this call is rarely needed
661: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
662: @*/
663: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch)
664: {
665: PetscFunctionBegin;
666: if (!*linesearch) PetscFunctionReturn(PETSC_SUCCESS);
668: if (--((PetscObject)*linesearch)->refct > 0) {
669: *linesearch = NULL;
670: PetscFunctionReturn(PETSC_SUCCESS);
671: }
672: PetscCall(PetscObjectSAWsViewOff((PetscObject)*linesearch));
673: PetscCall(SNESLineSearchReset(*linesearch));
674: PetscTryTypeMethod(*linesearch, destroy);
675: PetscCall(PetscViewerDestroy(&(*linesearch)->monitor));
676: PetscCall(SNESLineSearchMonitorCancel(*linesearch));
677: PetscCall(PetscHeaderDestroy(linesearch));
678: PetscFunctionReturn(PETSC_SUCCESS);
679: }
681: /*@
682: SNESLineSearchSetDefaultMonitor - Turns on/off printing useful information and debugging output about the line search.
684: Logically Collective
686: Input Parameters:
687: + linesearch - the linesearch object
688: - viewer - an `PETSCVIEWERASCII` `PetscViewer` or `NULL` to turn off monitor
690: Options Database Key:
691: . -snes_linesearch_monitor [:filename] - enables the monitor
693: Level: intermediate
695: Developer Notes:
696: This monitor is implemented differently than the other line search monitors that are set with
697: `SNESLineSearchMonitorSet()` since it is called in many locations of the line search routines to display aspects of the
698: line search that are not visible to the other monitors.
700: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PETSCVIEWERASCII`, `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`,
701: `SNESLineSearchMonitorSetFromOptions()`
702: @*/
703: PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
704: {
705: PetscFunctionBegin;
706: PetscCall(PetscViewerDestroy(&linesearch->monitor));
707: linesearch->monitor = viewer;
708: PetscFunctionReturn(PETSC_SUCCESS);
709: }
711: /*@
712: SNESLineSearchGetDefaultMonitor - Gets the `PetscViewer` instance for the default line search monitor that is turned on with `SNESLineSearchSetDefaultMonitor()`
714: Logically Collective
716: Input Parameter:
717: . linesearch - the line search context
719: Output Parameter:
720: . monitor - monitor context
722: Level: intermediate
724: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
725: @*/
726: PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
727: {
728: PetscFunctionBegin;
730: *monitor = linesearch->monitor;
731: PetscFunctionReturn(PETSC_SUCCESS);
732: }
734: /*@C
735: SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated in the options database
737: Collective
739: Input Parameters:
740: + ls - `SNESLineSearch` object to monitor
741: . name - the monitor type
742: . help - message indicating what monitoring is done
743: . manual - manual page for the monitor
744: . monitor - the monitor function, must use `PetscViewerAndFormat` as its context
745: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNESLineSearch` or `PetscViewer`
747: Calling sequence of `monitor`:
748: + ls - `SNESLineSearch` object being monitored
749: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used
751: Calling sequence of `monitorsetup`:
752: + ls - `SNESLineSearch` object being monitored
753: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used
755: Level: advanced
757: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetMonitor()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
758: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
759: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
760: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
761: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
762: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
763: `PetscOptionsFList()`, `PetscOptionsEList()`
764: @*/
765: 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))
766: {
767: PetscViewer viewer;
768: PetscViewerFormat format;
769: PetscBool flg;
771: PetscFunctionBegin;
772: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg));
773: if (flg) {
774: PetscViewerAndFormat *vf;
775: PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
776: PetscCall(PetscViewerDestroy(&viewer));
777: if (monitorsetup) PetscCall((*monitorsetup)(ls, vf));
778: PetscCall(SNESLineSearchMonitorSet(ls, (PetscErrorCode (*)(SNESLineSearch, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
779: }
780: PetscFunctionReturn(PETSC_SUCCESS);
781: }
783: /*@
784: SNESLineSearchSetFromOptions - Sets options for the line search
786: Logically Collective
788: Input Parameter:
789: . linesearch - a `SNESLineSearch` line search context
791: Options Database Keys:
792: + -snes_linesearch_type <type> - basic (or equivalently none), `bt`, `l2`, `cp`, `nleqerr`, `bisection`, `shell`
793: . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (`bt` supports 2 or 3)
794: . -snes_linesearch_norms - Turn on/off the linesearch norms for the basic linesearch typem (`SNESLineSearchSetComputeNorms()`)
795: . -snes_linesearch_minlambda - The minimum step length
796: . -snes_linesearch_maxstep - The maximum step size
797: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
798: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
799: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
800: . -snes_linesearch_max_it - The number of iterations for iterative line searches
801: . -snes_linesearch_monitor [:filename] - Print progress of line searches
802: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
803: . -snes_linesearch_damping - The linesearch damping parameter
804: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
805: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
806: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method
808: Level: intermediate
810: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
811: `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
812: @*/
813: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
814: {
815: const char *deft = SNESLINESEARCHBASIC;
816: char type[256];
817: PetscBool flg, set;
818: PetscViewer viewer;
820: PetscFunctionBegin;
821: PetscCall(SNESLineSearchRegisterAll());
823: PetscObjectOptionsBegin((PetscObject)linesearch);
824: if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
825: PetscCall(PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg));
826: if (flg) {
827: PetscCall(SNESLineSearchSetType(linesearch, type));
828: } else if (!((PetscObject)linesearch)->type_name) {
829: PetscCall(SNESLineSearchSetType(linesearch, deft));
830: }
832: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set));
833: if (set) PetscCall(SNESLineSearchSetDefaultMonitor(linesearch, viewer));
834: PetscCall(SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL));
836: /* tolerances */
837: PetscCall(PetscOptionsReal("-snes_linesearch_minlambda", "Minimum step length", "SNESLineSearchSetTolerances", linesearch->steptol, &linesearch->steptol, NULL));
838: PetscCall(PetscOptionsReal("-snes_linesearch_maxstep", "Maximum step size", "SNESLineSearchSetTolerances", linesearch->maxstep, &linesearch->maxstep, NULL));
839: PetscCall(PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL));
840: PetscCall(PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL));
841: PetscCall(PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL));
842: PetscCall(PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_its, &linesearch->max_its, NULL));
844: /* damping parameters */
845: PetscCall(PetscOptionsReal("-snes_linesearch_damping", "Line search damping and initial step guess", "SNESLineSearchSetDamping", linesearch->damping, &linesearch->damping, NULL));
847: PetscCall(PetscOptionsBool("-snes_linesearch_keeplambda", "Use previous lambda as damping", "SNESLineSearchSetKeepLambda", linesearch->keeplambda, &linesearch->keeplambda, NULL));
849: /* precheck */
850: PetscCall(PetscOptionsBool("-snes_linesearch_precheck_picard", "Use a correction that sometimes improves convergence of Picard iteration", "SNESLineSearchPreCheckPicard", flg, &flg, &set));
851: if (set) {
852: if (flg) {
853: linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */
855: 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));
856: PetscCall(SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle));
857: } else {
858: PetscCall(SNESLineSearchSetPreCheck(linesearch, NULL, NULL));
859: }
860: }
861: PetscCall(PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL));
862: PetscCall(PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL));
864: PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);
866: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject));
867: PetscOptionsEnd();
868: PetscFunctionReturn(PETSC_SUCCESS);
869: }
871: /*@
872: SNESLineSearchView - Prints useful information about the line search
874: Logically Collective
876: Input Parameters:
877: + linesearch - line search context
878: - viewer - the `PetscViewer` to display the line search information to
880: Level: intermediate
882: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`
883: @*/
884: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
885: {
886: PetscBool iascii;
888: PetscFunctionBegin;
890: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer));
892: PetscCheckSameComm(linesearch, 1, viewer, 2);
894: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
895: if (iascii) {
896: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer));
897: PetscCall(PetscViewerASCIIPushTab(viewer));
898: PetscTryTypeMethod(linesearch, view, viewer);
899: PetscCall(PetscViewerASCIIPopTab(viewer));
900: PetscCall(PetscViewerASCIIPrintf(viewer, " maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep, (double)linesearch->steptol));
901: PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol));
902: PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT "\n", linesearch->max_its));
903: if (linesearch->ops->precheck) {
904: if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
905: PetscCall(PetscViewerASCIIPrintf(viewer, " using precheck step to speed up Picard convergence\n"));
906: } else {
907: PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined precheck step\n"));
908: }
909: }
910: if (linesearch->ops->postcheck) PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined postcheck step\n"));
911: }
912: PetscFunctionReturn(PETSC_SUCCESS);
913: }
915: /*@
916: SNESLineSearchGetType - Gets the `SNESLinesearchType` of a `SNESLineSearch`
918: Logically Collective
920: Input Parameter:
921: . linesearch - the line search context
923: Output Parameter:
924: . type - The type of line search, or `NULL` if not set
926: Level: intermediate
928: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
929: @*/
930: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
931: {
932: PetscFunctionBegin;
934: PetscAssertPointer(type, 2);
935: *type = ((PetscObject)linesearch)->type_name;
936: PetscFunctionReturn(PETSC_SUCCESS);
937: }
939: /*@
940: SNESLineSearchSetType - Sets the `SNESLinesearchType` of a `SNESLineSearch` object to indicate the line search algorithm that should be used by a given `SNES` solver
942: Logically Collective
944: Input Parameters:
945: + linesearch - the line search context
946: - type - The type of line search to be used, see `SNESLineSearchType`
948: Options Database Key:
949: . -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
951: Level: intermediate
953: Note:
954: The `SNESLineSearch` object is generally obtained with `SNESGetLineSearch()`
956: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`,
957: `SNESGetLineSearch()`
958: @*/
959: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
960: {
961: PetscBool match;
962: PetscErrorCode (*r)(SNESLineSearch);
964: PetscFunctionBegin;
966: PetscAssertPointer(type, 2);
968: PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, type, &match));
969: if (match) PetscFunctionReturn(PETSC_SUCCESS);
971: PetscCall(PetscFunctionListFind(SNESLineSearchList, type, &r));
972: PetscCheck(r, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Line Search type %s", type);
973: /* Destroy the previous private line search context */
974: PetscTryTypeMethod(linesearch, destroy);
975: linesearch->ops->destroy = NULL;
976: /* Reinitialize function pointers in SNESLineSearchOps structure */
977: linesearch->ops->apply = NULL;
978: linesearch->ops->view = NULL;
979: linesearch->ops->setfromoptions = NULL;
980: linesearch->ops->destroy = NULL;
982: PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch, type));
983: PetscCall((*r)(linesearch));
984: PetscFunctionReturn(PETSC_SUCCESS);
985: }
987: /*@
988: SNESLineSearchSetSNES - Sets the `SNES` for the linesearch for function evaluation.
990: Input Parameters:
991: + linesearch - the line search context
992: - snes - The `SNES` instance
994: Level: developer
996: Note:
997: This happens automatically when the line search is obtained/created with
998: `SNESGetLineSearch()`. This routine is therefore mainly called within `SNES`
999: implementations.
1001: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`
1002: @*/
1003: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
1004: {
1005: PetscFunctionBegin;
1008: linesearch->snes = snes;
1009: PetscFunctionReturn(PETSC_SUCCESS);
1010: }
1012: /*@
1013: SNESLineSearchGetSNES - Gets the `SNES` instance associated with the line search.
1015: Not Collective
1017: Input Parameter:
1018: . linesearch - the line search context
1020: Output Parameter:
1021: . snes - The `SNES` instance
1023: Level: developer
1025: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESType`, `SNESLineSearchSetVecs()`
1026: @*/
1027: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
1028: {
1029: PetscFunctionBegin;
1031: PetscAssertPointer(snes, 2);
1032: *snes = linesearch->snes;
1033: PetscFunctionReturn(PETSC_SUCCESS);
1034: }
1036: /*@
1037: SNESLineSearchGetLambda - Gets the last line search steplength used
1039: Not Collective
1041: Input Parameter:
1042: . linesearch - the line search context
1044: Output Parameter:
1045: . lambda - The last steplength computed during `SNESLineSearchApply()`
1047: Level: advanced
1049: Note:
1050: This is useful in methods where the solver is ill-scaled and
1051: requires some adaptive notion of the difference in scale between the
1052: solution and the function. For instance, `SNESQN` may be scaled by the
1053: line search lambda using the argument -snes_qn_scaling ls.
1055: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1056: @*/
1057: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1058: {
1059: PetscFunctionBegin;
1061: PetscAssertPointer(lambda, 2);
1062: *lambda = linesearch->lambda;
1063: PetscFunctionReturn(PETSC_SUCCESS);
1064: }
1066: /*@
1067: SNESLineSearchSetLambda - Sets the line search steplength
1069: Input Parameters:
1070: + linesearch - line search context
1071: - lambda - The steplength to use
1073: Level: advanced
1075: Note:
1076: This routine is typically used within implementations of `SNESLineSearchApply()`
1077: to set the final steplength. This routine (and `SNESLineSearchGetLambda()`) were
1078: added in order to facilitate Quasi-Newton methods that use the previous steplength
1079: as an inner scaling parameter.
1081: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetLambda()`
1082: @*/
1083: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1084: {
1085: PetscFunctionBegin;
1087: linesearch->lambda = lambda;
1088: PetscFunctionReturn(PETSC_SUCCESS);
1089: }
1091: /*@
1092: SNESLineSearchGetTolerances - Gets the tolerances for the line search.
1094: Not Collective
1096: Input Parameter:
1097: . linesearch - the line search context
1099: Output Parameters:
1100: + steptol - The minimum steplength
1101: . maxstep - The maximum steplength
1102: . rtol - The relative tolerance for iterative line searches
1103: . atol - The absolute tolerance for iterative line searches
1104: . ltol - The change in lambda tolerance for iterative line searches
1105: - max_its - The maximum number of iterations of the line search
1107: Level: intermediate
1109: Note:
1110: Different line searches may implement these parameters slightly differently as
1111: the type requires.
1113: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1114: @*/
1115: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *steptol, PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1116: {
1117: PetscFunctionBegin;
1119: if (steptol) {
1120: PetscAssertPointer(steptol, 2);
1121: *steptol = linesearch->steptol;
1122: }
1123: if (maxstep) {
1124: PetscAssertPointer(maxstep, 3);
1125: *maxstep = linesearch->maxstep;
1126: }
1127: if (rtol) {
1128: PetscAssertPointer(rtol, 4);
1129: *rtol = linesearch->rtol;
1130: }
1131: if (atol) {
1132: PetscAssertPointer(atol, 5);
1133: *atol = linesearch->atol;
1134: }
1135: if (ltol) {
1136: PetscAssertPointer(ltol, 6);
1137: *ltol = linesearch->ltol;
1138: }
1139: if (max_its) {
1140: PetscAssertPointer(max_its, 7);
1141: *max_its = linesearch->max_its;
1142: }
1143: PetscFunctionReturn(PETSC_SUCCESS);
1144: }
1146: /*@
1147: SNESLineSearchSetTolerances - Sets the tolerances for the linesearch.
1149: Collective
1151: Input Parameters:
1152: + linesearch - the line search context
1153: . steptol - The minimum steplength
1154: . maxstep - The maximum steplength
1155: . rtol - The relative tolerance for iterative line searches
1156: . atol - The absolute tolerance for iterative line searches
1157: . ltol - The change in lambda tolerance for iterative line searches
1158: - max_it - The maximum number of iterations of the line search
1160: Options Database Keys:
1161: + -snes_linesearch_minlambda - The minimum step length
1162: . -snes_linesearch_maxstep - The maximum step size
1163: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
1164: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
1165: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
1166: - -snes_linesearch_max_it - The number of iterations for iterative line searches
1168: Level: intermediate
1170: Note:
1171: The user may choose to not set any of the tolerances using `PETSC_DEFAULT` in place of an argument.
1173: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1174: @*/
1175: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal steptol, PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_it)
1176: {
1177: PetscFunctionBegin;
1186: if (steptol != (PetscReal)PETSC_DEFAULT) {
1187: PetscCheck(steptol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum step length %14.12e must be non-negative", (double)steptol);
1188: linesearch->steptol = steptol;
1189: }
1191: if (maxstep != (PetscReal)PETSC_DEFAULT) {
1192: PetscCheck(maxstep >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum step length %14.12e must be non-negative", (double)maxstep);
1193: linesearch->maxstep = maxstep;
1194: }
1196: if (rtol != (PetscReal)PETSC_DEFAULT) {
1197: 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);
1198: linesearch->rtol = rtol;
1199: }
1201: if (atol != (PetscReal)PETSC_DEFAULT) {
1202: PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %14.12e must be non-negative", (double)atol);
1203: linesearch->atol = atol;
1204: }
1206: if (ltol != (PetscReal)PETSC_DEFAULT) {
1207: PetscCheck(ltol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Lambda tolerance %14.12e must be non-negative", (double)ltol);
1208: linesearch->ltol = ltol;
1209: }
1211: if (max_it != PETSC_DEFAULT) {
1212: PetscCheck(max_it >= 0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", max_it);
1213: linesearch->max_its = max_it;
1214: }
1215: PetscFunctionReturn(PETSC_SUCCESS);
1216: }
1218: /*@
1219: SNESLineSearchGetDamping - Gets the line search damping parameter.
1221: Input Parameter:
1222: . linesearch - the line search context
1224: Output Parameter:
1225: . damping - The damping parameter
1227: Level: advanced
1229: .seealso: [](ch_snes), `SNES`, `SNESLineSearchGetStepTolerance()`, `SNESQN`
1230: @*/
1231: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1232: {
1233: PetscFunctionBegin;
1235: PetscAssertPointer(damping, 2);
1236: *damping = linesearch->damping;
1237: PetscFunctionReturn(PETSC_SUCCESS);
1238: }
1240: /*@
1241: SNESLineSearchSetDamping - Sets the line search damping parameter.
1243: Input Parameters:
1244: + linesearch - the line search context
1245: - damping - The damping parameter
1247: Options Database Key:
1248: . -snes_linesearch_damping <damping> - the damping value
1250: Level: intermediate
1252: Note:
1253: The `SNESLINESEARCHNONE` line search merely takes the update step scaled by the damping parameter.
1254: The use of the damping parameter in the `SNESLINESEARCHL2` and `SNESLINESEARCHCP` line searches is much more subtle;
1255: it is used as a starting point in calculating the secant step. However, the eventual
1256: step may be of greater length than the damping parameter. In the `SNESLINESEARCHBT` line search it is
1257: used as the maximum possible step length, as the `SNESLINESEARCHBT` line search only backtracks.
1259: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetDamping()`
1260: @*/
1261: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1262: {
1263: PetscFunctionBegin;
1265: linesearch->damping = damping;
1266: PetscFunctionReturn(PETSC_SUCCESS);
1267: }
1269: /*@
1270: SNESLineSearchGetOrder - Gets the line search approximation order.
1272: Input Parameter:
1273: . linesearch - the line search context
1275: Output Parameter:
1276: . order - The order
1278: Level: intermediate
1280: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetOrder()`
1281: @*/
1282: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1283: {
1284: PetscFunctionBegin;
1286: PetscAssertPointer(order, 2);
1287: *order = linesearch->order;
1288: PetscFunctionReturn(PETSC_SUCCESS);
1289: }
1291: /*@
1292: SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search
1294: Input Parameters:
1295: + linesearch - the line search context
1296: - order - The order
1298: Level: intermediate
1300: Values for `order`\:
1301: + 1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1302: . 2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1303: - 3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order
1305: Options Database Key:
1306: . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (`SNESLINESEARCHBT` supports 2 or 3)
1308: Note:
1309: These orders are supported by `SNESLINESEARCHBT` and `SNESLINESEARCHCP`
1311: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1312: @*/
1313: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1314: {
1315: PetscFunctionBegin;
1317: linesearch->order = order;
1318: PetscFunctionReturn(PETSC_SUCCESS);
1319: }
1321: /*@
1322: SNESLineSearchGetNorms - Gets the norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1324: Not Collective
1326: Input Parameter:
1327: . linesearch - the line search context
1329: Output Parameters:
1330: + xnorm - The norm of the current solution
1331: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution.
1332: - ynorm - The norm of the current update (after scaling by the linesearch computed lambda)
1334: Level: developer
1336: Notes:
1337: Some values may not be up-to-date at particular points in the code.
1339: This, in combination with `SNESLineSearchSetNorms()`, allow the line search and the `SNESSolve_XXX()` to share
1340: computed values.
1342: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1343: @*/
1344: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1345: {
1346: PetscFunctionBegin;
1348: if (xnorm) *xnorm = linesearch->xnorm;
1349: if (fnorm) *fnorm = linesearch->fnorm;
1350: if (ynorm) *ynorm = linesearch->ynorm;
1351: PetscFunctionReturn(PETSC_SUCCESS);
1352: }
1354: /*@
1355: SNESLineSearchSetNorms - Sets the computed norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1357: Collective
1359: Input Parameters:
1360: + linesearch - the line search context
1361: . xnorm - The norm of the current solution
1362: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution
1363: - ynorm - The norm of the current update (after scaling by the linesearch computed lambda)
1365: Level: developer
1367: Note:
1368: This is called by the line search routines to store the values they have just computed
1370: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1371: @*/
1372: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1373: {
1374: PetscFunctionBegin;
1376: linesearch->xnorm = xnorm;
1377: linesearch->fnorm = fnorm;
1378: linesearch->ynorm = ynorm;
1379: PetscFunctionReturn(PETSC_SUCCESS);
1380: }
1382: /*@
1383: SNESLineSearchComputeNorms - Explicitly computes the norms of the current solution `X`, the current update `Y`, and the current function value `F`.
1385: Input Parameter:
1386: . linesearch - the line search context
1388: Options Database Key:
1389: . -snes_linesearch_norms - turn norm computation on or off
1391: Level: intermediate
1393: Developer Note:
1394: The options database key is misnamed. It should be -snes_linesearch_compute_norms
1396: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1397: @*/
1398: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1399: {
1400: SNES snes;
1402: PetscFunctionBegin;
1403: if (linesearch->norms) {
1404: if (linesearch->ops->vinorm) {
1405: PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1406: PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1407: PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1408: PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1409: } else {
1410: PetscCall(VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1411: PetscCall(VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1412: PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1413: PetscCall(VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1414: PetscCall(VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1415: PetscCall(VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1416: }
1417: }
1418: PetscFunctionReturn(PETSC_SUCCESS);
1419: }
1421: /*@
1422: SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.
1424: Input Parameters:
1425: + linesearch - the line search context
1426: - flg - indicates whether or not to compute norms
1428: Options Database Key:
1429: . -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic (none) `SNESLINESEARCHBASIC` line search
1431: Level: intermediate
1433: Note:
1434: This is most relevant to the `SNESLINESEARCHBASIC` (or equivalently `SNESLINESEARCHNONE`) line search type since most line searches have a stopping criteria involving the norm.
1436: Developer Note:
1437: The options database key is misnamed. It should be -snes_linesearch_compute_norms
1439: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1440: @*/
1441: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1442: {
1443: PetscFunctionBegin;
1444: linesearch->norms = flg;
1445: PetscFunctionReturn(PETSC_SUCCESS);
1446: }
1448: /*@
1449: SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context
1451: Not Collective but the vectors are parallel
1453: Input Parameter:
1454: . linesearch - the line search context
1456: Output Parameters:
1457: + X - Solution vector
1458: . F - Function vector
1459: . Y - Search direction vector
1460: . W - Solution work vector
1461: - G - Function work vector
1463: Level: advanced
1465: Notes:
1466: At the beginning of a line search application, `X` should contain a
1467: solution and the vector `F` the function computed at `X`. At the end of the
1468: line search application, `X` should contain the new solution, and `F` the
1469: function evaluated at the new solution.
1471: These vectors are owned by the `SNESLineSearch` and should not be destroyed by the caller
1473: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1474: @*/
1475: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1476: {
1477: PetscFunctionBegin;
1479: if (X) {
1480: PetscAssertPointer(X, 2);
1481: *X = linesearch->vec_sol;
1482: }
1483: if (F) {
1484: PetscAssertPointer(F, 3);
1485: *F = linesearch->vec_func;
1486: }
1487: if (Y) {
1488: PetscAssertPointer(Y, 4);
1489: *Y = linesearch->vec_update;
1490: }
1491: if (W) {
1492: PetscAssertPointer(W, 5);
1493: *W = linesearch->vec_sol_new;
1494: }
1495: if (G) {
1496: PetscAssertPointer(G, 6);
1497: *G = linesearch->vec_func_new;
1498: }
1499: PetscFunctionReturn(PETSC_SUCCESS);
1500: }
1502: /*@
1503: SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context
1505: Logically Collective
1507: Input Parameters:
1508: + linesearch - the line search context
1509: . X - Solution vector
1510: . F - Function vector
1511: . Y - Search direction vector
1512: . W - Solution work vector
1513: - G - Function work vector
1515: Level: developer
1517: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1518: @*/
1519: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1520: {
1521: PetscFunctionBegin;
1523: if (X) {
1525: linesearch->vec_sol = X;
1526: }
1527: if (F) {
1529: linesearch->vec_func = F;
1530: }
1531: if (Y) {
1533: linesearch->vec_update = Y;
1534: }
1535: if (W) {
1537: linesearch->vec_sol_new = W;
1538: }
1539: if (G) {
1541: linesearch->vec_func_new = G;
1542: }
1543: PetscFunctionReturn(PETSC_SUCCESS);
1544: }
1546: /*@
1547: SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1548: `SNESLineSearch` options in the database.
1550: Logically Collective
1552: Input Parameters:
1553: + linesearch - the `SNESLineSearch` context
1554: - prefix - the prefix to prepend to all option names
1556: Level: advanced
1558: Note:
1559: A hyphen (-) must NOT be given at the beginning of the prefix name.
1560: The first character of all runtime options is AUTOMATICALLY the hyphen.
1562: .seealso: [](ch_snes), `SNES`, `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1563: @*/
1564: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1565: {
1566: PetscFunctionBegin;
1568: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix));
1569: PetscFunctionReturn(PETSC_SUCCESS);
1570: }
1572: /*@
1573: SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1574: SNESLineSearch options in the database.
1576: Not Collective
1578: Input Parameter:
1579: . linesearch - the `SNESLineSearch` context
1581: Output Parameter:
1582: . prefix - pointer to the prefix string used
1584: Level: advanced
1586: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1587: @*/
1588: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1589: {
1590: PetscFunctionBegin;
1592: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix));
1593: PetscFunctionReturn(PETSC_SUCCESS);
1594: }
1596: /*@C
1597: SNESLineSearchSetWorkVecs - Sets work vectors for the line search.
1599: Input Parameters:
1600: + linesearch - the `SNESLineSearch` context
1601: - nwork - the number of work vectors
1603: Level: developer
1605: Developer Note:
1606: This is called from within the set up routines for each of the line search types `SNESLineSearchType`
1608: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetWorkVecs()`
1609: @*/
1610: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1611: {
1612: PetscFunctionBegin;
1613: PetscCheck(linesearch->vec_sol, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1614: PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1615: PetscFunctionReturn(PETSC_SUCCESS);
1616: }
1618: /*@
1619: SNESLineSearchGetReason - Gets the success/failure status of the last line search application
1621: Input Parameter:
1622: . linesearch - the line search context
1624: Output Parameter:
1625: . result - The success or failure status
1627: Level: developer
1629: Note:
1630: This is typically called after `SNESLineSearchApply()` in order to determine if the line search failed
1631: (and set into the `SNES` convergence accordingly).
1633: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1634: @*/
1635: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1636: {
1637: PetscFunctionBegin;
1639: PetscAssertPointer(result, 2);
1640: *result = linesearch->result;
1641: PetscFunctionReturn(PETSC_SUCCESS);
1642: }
1644: /*@
1645: SNESLineSearchSetReason - Sets the success/failure status of the line search application
1647: Logically Collective; No Fortran Support
1649: Input Parameters:
1650: + linesearch - the line search context
1651: - result - The success or failure status
1653: Level: developer
1655: Note:
1656: This is typically called in a `SNESLineSearchType` implementation of `SNESLineSearchApply()` or a `SNESLINESEARCHSHELL` implementation to set
1657: the success or failure of the line search method.
1659: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`
1660: @*/
1661: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1662: {
1663: PetscFunctionBegin;
1665: linesearch->result = result;
1666: PetscFunctionReturn(PETSC_SUCCESS);
1667: }
1669: // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
1670: /*@C
1671: SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.
1673: Logically Collective
1675: Input Parameters:
1676: + linesearch - the linesearch object
1677: . projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1678: . normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn` for calling sequence
1679: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence
1681: Level: advanced
1683: Notes:
1684: The VI solvers require projection of the solution to the feasible set. `projectfunc` should implement this.
1686: The VI solvers require special evaluation of the function norm such that the norm is only calculated
1687: on the inactive set. This should be implemented by `normfunc`.
1689: The VI solvers further require special evaluation of the directional derivative (when assuming that there exists some $G(x)$
1690: for which the `SNESFunctionFn` $F(x) = grad G(x)$) such that it is only calculated on the inactive set.
1691: This should be implemented by `dirderivfunc`.
1693: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`,
1694: `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`, `SNESLineSearchVIDirDerivFn`
1695: @*/
1696: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn *projectfunc, SNESLineSearchVINormFn *normfunc, SNESLineSearchVIDirDerivFn *dirderivfunc)
1697: {
1698: PetscFunctionBegin;
1700: if (projectfunc) linesearch->ops->viproject = projectfunc;
1701: if (normfunc) linesearch->ops->vinorm = normfunc;
1702: if (dirderivfunc) linesearch->ops->vidirderiv = dirderivfunc;
1703: PetscFunctionReturn(PETSC_SUCCESS);
1704: }
1706: /*@C
1707: SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.
1709: Not Collective
1711: Input Parameter:
1712: . linesearch - the line search context, obtain with `SNESGetLineSearch()`
1714: Output Parameters:
1715: + projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1716: . normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn ` for calling sequence
1717: - dirderivfunc - function for computing the directional derivative of an active set, see `SNESLineSearchVIDirDerivFn` for calling sequence
1719: Level: advanced
1721: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
1722: `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`
1723: @*/
1724: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn **projectfunc, SNESLineSearchVINormFn **normfunc, SNESLineSearchVIDirDerivFn **dirderivfunc)
1725: {
1726: PetscFunctionBegin;
1727: if (projectfunc) *projectfunc = linesearch->ops->viproject;
1728: if (normfunc) *normfunc = linesearch->ops->vinorm;
1729: if (dirderivfunc) *dirderivfunc = linesearch->ops->vidirderiv;
1730: PetscFunctionReturn(PETSC_SUCCESS);
1731: }
1733: /*@C
1734: SNESLineSearchRegister - register a line search type `SNESLineSearchType`
1736: Logically Collective, No Fortran Support
1738: Input Parameters:
1739: + sname - name of the `SNESLineSearchType()`
1740: - function - the creation function for that type
1742: Calling sequence of `function`:
1743: . ls - the line search context
1745: Level: advanced
1747: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1748: @*/
1749: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch ls))
1750: {
1751: PetscFunctionBegin;
1752: PetscCall(SNESInitializePackage());
1753: PetscCall(PetscFunctionListAdd(&SNESLineSearchList, sname, function));
1754: PetscFunctionReturn(PETSC_SUCCESS);
1755: }