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`)
83: Calling sequence of `f`:
84: + ls - the `SNESLineSearch` context
85: - mctx - [optional] user-defined context for private data for the monitor routine
87: Calling sequence of `monitordestroy`:
88: . mctx - [optional] user-defined context for private data for the monitor routine
90: Level: intermediate
92: Note:
93: Several different monitoring routines may be set by calling
94: `SNESLineSearchMonitorSet()` multiple times; all will be called in the
95: order in which they were set.
97: Fortran Note:
98: Only a single monitor function can be set for each `SNESLineSearch` object
100: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorCancel()`
101: @*/
102: PetscErrorCode SNESLineSearchMonitorSet(SNESLineSearch ls, PetscErrorCode (*f)(SNESLineSearch ls, void *mctx), void *mctx, PetscErrorCode (*monitordestroy)(void **mctx))
103: {
104: PetscInt i;
105: PetscBool identical;
107: PetscFunctionBegin;
109: for (i = 0; i < ls->numbermonitors; i++) {
110: PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))ls->monitorftns[i], ls->monitorcontext[i], ls->monitordestroy[i], &identical));
111: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
112: }
113: PetscCheck(ls->numbermonitors < MAXSNESLSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
114: ls->monitorftns[ls->numbermonitors] = f;
115: ls->monitordestroy[ls->numbermonitors] = monitordestroy;
116: ls->monitorcontext[ls->numbermonitors++] = (void *)mctx;
117: PetscFunctionReturn(PETSC_SUCCESS);
118: }
120: /*@C
121: SNESLineSearchMonitorSolutionUpdate - Monitors each update of the function value the linesearch tries
123: Collective
125: Input Parameters:
126: + ls - the `SNESLineSearch` object
127: - vf - the context for the monitor, in this case it is an `PetscViewerAndFormat`
129: Options Database Key:
130: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
132: Level: developer
134: This is not normally called directly but is passed to `SNESLineSearchMonitorSet()`
136: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorSet()`, `SNESMonitorSolution()`
137: @*/
138: PetscErrorCode SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls, PetscViewerAndFormat *vf)
139: {
140: PetscViewer viewer = vf->viewer;
141: Vec Y, W, G;
143: PetscFunctionBegin;
144: PetscCall(SNESLineSearchGetVecs(ls, NULL, NULL, &Y, &W, &G));
145: PetscCall(PetscViewerPushFormat(viewer, vf->format));
146: PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted update to solution \n"));
147: PetscCall(VecView(Y, viewer));
148: PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted new solution \n"));
149: PetscCall(VecView(W, viewer));
150: PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted updated function value\n"));
151: PetscCall(VecView(G, viewer));
152: PetscCall(PetscViewerPopFormat(viewer));
153: PetscFunctionReturn(PETSC_SUCCESS);
154: }
156: /*@
157: SNESLineSearchCreate - Creates a `SNESLineSearch` context.
159: Logically Collective
161: Input Parameter:
162: . comm - MPI communicator for the line search (typically from the associated `SNES` context).
164: Output Parameter:
165: . outlinesearch - the new line search context
167: Level: developer
169: Note:
170: The preferred calling sequence is to use `SNESGetLineSearch()` to acquire the `SNESLineSearch` instance
171: already associated with the `SNES`.
173: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `LineSearchDestroy()`, `SNESGetLineSearch()`
174: @*/
175: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
176: {
177: SNESLineSearch linesearch;
179: PetscFunctionBegin;
180: PetscAssertPointer(outlinesearch, 2);
181: PetscCall(SNESInitializePackage());
183: PetscCall(PetscHeaderCreate(linesearch, SNESLINESEARCH_CLASSID, "SNESLineSearch", "Linesearch", "SNESLineSearch", comm, SNESLineSearchDestroy, SNESLineSearchView));
184: linesearch->vec_sol_new = NULL;
185: linesearch->vec_func_new = NULL;
186: linesearch->vec_sol = NULL;
187: linesearch->vec_func = NULL;
188: linesearch->vec_update = NULL;
190: linesearch->lambda = 1.0;
191: linesearch->fnorm = 1.0;
192: linesearch->ynorm = 1.0;
193: linesearch->xnorm = 1.0;
194: linesearch->result = SNES_LINESEARCH_SUCCEEDED;
195: linesearch->norms = PETSC_TRUE;
196: linesearch->keeplambda = PETSC_FALSE;
197: linesearch->damping = 1.0;
198: linesearch->maxstep = 1e8;
199: linesearch->steptol = 1e-12;
200: linesearch->rtol = 1e-8;
201: linesearch->atol = 1e-15;
202: linesearch->ltol = 1e-8;
203: linesearch->precheckctx = NULL;
204: linesearch->postcheckctx = NULL;
205: linesearch->max_its = 1;
206: linesearch->setupcalled = PETSC_FALSE;
207: linesearch->monitor = NULL;
208: *outlinesearch = linesearch;
209: PetscFunctionReturn(PETSC_SUCCESS);
210: }
212: /*@
213: SNESLineSearchSetUp - Prepares the line search for being applied by allocating
214: any required vectors.
216: Collective
218: Input Parameter:
219: . linesearch - The `SNESLineSearch` instance.
221: Level: advanced
223: Note:
224: For most cases, this needn't be called by users or outside of `SNESLineSearchApply()`.
225: The only current case where this is called outside of this is for the VI
226: solvers, which modify the solution and work vectors before the first call
227: of `SNESLineSearchApply()`, requiring the `SNESLineSearch` work vectors to be
228: allocated upfront.
230: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchReset()`
231: @*/
232: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
233: {
234: PetscFunctionBegin;
235: if (!((PetscObject)linesearch)->type_name) PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC));
236: if (!linesearch->setupcalled) {
237: if (!linesearch->vec_sol_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new));
238: if (!linesearch->vec_func_new) PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new));
239: PetscTryTypeMethod(linesearch, setup);
240: if (!linesearch->ops->snesfunc) PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunction));
241: linesearch->lambda = linesearch->damping;
242: linesearch->setupcalled = PETSC_TRUE;
243: }
244: PetscFunctionReturn(PETSC_SUCCESS);
245: }
247: /*@
248: SNESLineSearchReset - Undoes the `SNESLineSearchSetUp()` and deletes any `Vec`s or `Mat`s allocated by the line search.
250: Collective
252: Input Parameter:
253: . linesearch - The `SNESLineSearch` instance.
255: Level: developer
257: Note:
258: Usually only called by `SNESReset()`
260: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetUp()`
261: @*/
262: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
263: {
264: PetscFunctionBegin;
265: PetscTryTypeMethod(linesearch, reset);
267: PetscCall(VecDestroy(&linesearch->vec_sol_new));
268: PetscCall(VecDestroy(&linesearch->vec_func_new));
270: PetscCall(VecDestroyVecs(linesearch->nwork, &linesearch->work));
272: linesearch->nwork = 0;
273: linesearch->setupcalled = PETSC_FALSE;
274: PetscFunctionReturn(PETSC_SUCCESS);
275: }
277: /*@C
278: SNESLineSearchSetFunction - Sets the function evaluation used by the `SNES` line search
279: `
281: Input Parameters:
282: + linesearch - the `SNESLineSearch` context
283: - func - function evaluation routine, this is usually the function provided with `SNESSetFunction()`
285: Calling sequence of `func`:
286: + snes - the `SNES` with which the `SNESLineSearch` context is associated with
287: . x - the input vector
288: - f - the computed value of the function
290: Level: developer
292: Note:
293: By default the `SNESLineSearch` uses the function provided by `SNESSetFunction()` so this is rarely needed
295: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESSetFunction()`
296: @*/
297: PetscErrorCode SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES snes, Vec x, Vec f))
298: {
299: PetscFunctionBegin;
301: linesearch->ops->snesfunc = func;
302: PetscFunctionReturn(PETSC_SUCCESS);
303: }
305: /*@C
306: SNESLineSearchSetPreCheck - Sets a function that is called after the initial search direction has been computed but
307: before the line search routine has been applied. Allows adjusting the result of (usually a linear solve) that
308: determined the search direction.
310: Logically Collective
312: Input Parameters:
313: + linesearch - the `SNESLineSearch` context
314: . func - [optional] function evaluation routine
315: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
317: Calling sequence of `func`:
318: + ls - the `SNESLineSearch` context
319: . x - the current solution
320: . d - the current search direction
321: . changed_d - indicates if the search direction has been changed
322: - ctx - the context passed to `SNESLineSearchSetPreCheck()`
324: Level: intermediate
326: Note:
327: Use `SNESLineSearchSetPostCheck()` to change the step after the line search is complete.
329: Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
331: .seealso: [](ch_snes), `SNES`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
332: `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()`
334: @*/
335: PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, PetscBool *changed_d, void *ctx), void *ctx)
336: {
337: PetscFunctionBegin;
339: if (func) linesearch->ops->precheck = func;
340: if (ctx) linesearch->precheckctx = ctx;
341: PetscFunctionReturn(PETSC_SUCCESS);
342: }
344: /*@C
345: SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.
347: Input Parameter:
348: . linesearch - the `SNESLineSearch` context
350: Output Parameters:
351: + func - [optional] function evaluation routine, for calling sequence see `SNESLineSearchSetPreCheck()`
352: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
354: Level: intermediate
356: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
357: @*/
358: PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void **ctx)
359: {
360: PetscFunctionBegin;
362: if (func) *func = linesearch->ops->precheck;
363: if (ctx) *ctx = linesearch->precheckctx;
364: PetscFunctionReturn(PETSC_SUCCESS);
365: }
367: /*@C
368: SNESLineSearchSetPostCheck - Sets a user function that is called after the line search has been applied to determine the step
369: direction and length. Allows the user a chance to change or override the decision of the line search routine
371: Logically Collective
373: Input Parameters:
374: + linesearch - the `SNESLineSearch` context
375: . func - [optional] function evaluation routine
376: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
378: Calling sequence of `func`:
379: + ls - the `SNESLineSearch` context
380: . x - the current solution
381: . d - the current search direction
382: . w - $ w = x + lambda*d $ for some lambda
383: . changed_d - indicates if the search direction `d` has been changed
384: . changed_w - indicates `w` has been changed
385: - ctx - the context passed to `SNESLineSearchSetPreCheck()`
387: Level: intermediate
389: Notes:
390: Use `SNESLineSearchSetPreCheck()` to change the step before the line search is completed.
391: The calling sequence of the callback does not contain the current scaling factor. To access the value, use `SNESLineSearchGetLambda()`.
393: Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
395: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
396: `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()`
397: @*/
398: PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch ls, Vec x, Vec d, Vec w, PetscBool *changed_d, PetscBool *changed_w, void *ctx), void *ctx)
399: {
400: PetscFunctionBegin;
402: if (func) linesearch->ops->postcheck = func;
403: if (ctx) linesearch->postcheckctx = ctx;
404: PetscFunctionReturn(PETSC_SUCCESS);
405: }
407: /*@C
408: SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.
410: Input Parameter:
411: . linesearch - the `SNESLineSearch` context
413: Output Parameters:
414: + func - [optional] function evaluation routine, see for the calling sequence `SNESLineSearchSetPostCheck()`
415: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
417: Level: intermediate
419: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
420: @*/
421: PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void **ctx)
422: {
423: PetscFunctionBegin;
425: if (func) *func = linesearch->ops->postcheck;
426: if (ctx) *ctx = linesearch->postcheckctx;
427: PetscFunctionReturn(PETSC_SUCCESS);
428: }
430: /*@
431: SNESLineSearchPreCheck - Prepares the line search for being applied.
433: Logically Collective
435: Input Parameters:
436: + linesearch - The linesearch instance.
437: . X - The current solution
438: - Y - The step direction
440: Output Parameter:
441: . changed - Indicator that the precheck routine has changed `Y`
443: Level: advanced
445: Note:
446: This calls any function provided with `SNESLineSearchSetPreCheck()` and is called automatically inside the line search routines
448: Developer Note:
449: The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided
451: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
452: `SNESLineSearchGetPostCheck()`
453: @*/
454: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed)
455: {
456: PetscFunctionBegin;
457: *changed = PETSC_FALSE;
458: if (linesearch->ops->precheck) {
459: PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
461: }
462: PetscFunctionReturn(PETSC_SUCCESS);
463: }
465: /*@
466: SNESLineSearchPostCheck - Hook to modify step direction or updated solution after a successful linesearch
468: Logically Collective
470: Input Parameters:
471: + linesearch - The line search context
472: . X - The last solution
473: . Y - The step direction
474: - W - The updated solution, `W = X - lambda * Y` for some lambda
476: Output Parameters:
477: + changed_Y - Indicator if the direction `Y` has been changed.
478: - changed_W - Indicator if the new candidate solution `W` has been changed.
480: Level: developer
482: Note:
483: This calls any function provided with `SNESLineSearchSetPostCheck()` and is called automatically inside the line search routines
485: Developer Note:
486: The use of `PetscObjectGetState()` would eliminate the need for the `changed_Y` and `changed_W` arguments to be provided
488: .seealso: [](ch_snes), `SNES`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
489: @*/
490: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W)
491: {
492: PetscFunctionBegin;
493: *changed_Y = PETSC_FALSE;
494: *changed_W = PETSC_FALSE;
495: if (linesearch->ops->postcheck) {
496: PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
499: }
500: PetscFunctionReturn(PETSC_SUCCESS);
501: }
503: /*@C
504: SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration {cite}`hindmarsh1996time`
506: Logically Collective
508: Input Parameters:
509: + linesearch - the line search context
510: . X - base state for this step
511: - ctx - context for this function
513: Input/Output Parameter:
514: . Y - correction, possibly modified
516: Output Parameter:
517: . changed - flag indicating that `Y` was modified
519: Options Database Keys:
520: + -snes_linesearch_precheck_picard - activate this routine
521: - -snes_linesearch_precheck_picard_angle - angle
523: Level: advanced
525: Notes:
526: This function should be passed to `SNESLineSearchSetPreCheck()`
528: The justification for this method involves the linear convergence of a Picard iteration
529: so the Picard linearization should be provided in place of the "Jacobian" {cite}`hindmarsh1996time`. This correction
530: is generally not useful when using a Newton linearization.
532: Developer Note:
533: The use of `PetscObjectGetState()` would eliminate the need for the `changed` argument to be provided
535: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetPicard()`, `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
536: @*/
537: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, void *ctx)
538: {
539: PetscReal angle = *(PetscReal *)linesearch->precheckctx;
540: Vec Ylast;
541: PetscScalar dot;
542: PetscInt iter;
543: PetscReal ynorm, ylastnorm, theta, angle_radians;
544: SNES snes;
546: PetscFunctionBegin;
547: PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
548: PetscCall(PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast));
549: if (!Ylast) {
550: PetscCall(VecDuplicate(Y, &Ylast));
551: PetscCall(PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast));
552: PetscCall(PetscObjectDereference((PetscObject)Ylast));
553: }
554: PetscCall(SNESGetIterationNumber(snes, &iter));
555: if (iter < 2) {
556: PetscCall(VecCopy(Y, Ylast));
557: *changed = PETSC_FALSE;
558: PetscFunctionReturn(PETSC_SUCCESS);
559: }
561: PetscCall(VecDot(Y, Ylast, &dot));
562: PetscCall(VecNorm(Y, NORM_2, &ynorm));
563: PetscCall(VecNorm(Ylast, NORM_2, &ylastnorm));
564: /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
565: theta = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
566: angle_radians = angle * PETSC_PI / 180.;
567: if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
568: /* Modify the step Y */
569: PetscReal alpha, ydiffnorm;
570: PetscCall(VecAXPY(Ylast, -1.0, Y));
571: PetscCall(VecNorm(Ylast, NORM_2, &ydiffnorm));
572: alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
573: PetscCall(VecCopy(Y, Ylast));
574: PetscCall(VecScale(Y, alpha));
575: PetscCall(PetscInfo(snes, "Angle %14.12e degrees less than threshold %14.12e, corrected step by alpha=%14.12e\n", (double)(theta * 180. / PETSC_PI), (double)angle, (double)alpha));
576: *changed = PETSC_TRUE;
577: } else {
578: PetscCall(PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180. / PETSC_PI), (double)angle));
579: PetscCall(VecCopy(Y, Ylast));
580: *changed = PETSC_FALSE;
581: }
582: PetscFunctionReturn(PETSC_SUCCESS);
583: }
585: /*@
586: SNESLineSearchApply - Computes the line-search update.
588: Collective
590: Input Parameter:
591: . linesearch - The line search context
593: Input/Output Parameters:
594: + X - The current solution, on output the new solution
595: . F - The current function value, on output the new function value at the solution value `X`
596: . fnorm - The current norm of `F`, on output the new norm of `F`
597: - Y - The current search direction, on output the direction determined by the linesearch, i.e. Xnew = Xold - lambda*Y
599: Options Database Keys:
600: + -snes_linesearch_type - basic (or equivalently none), bt, l2, cp, nleqerr, shell
601: . -snes_linesearch_monitor [:filename] - Print progress of line searches
602: . -snes_linesearch_damping - The linesearch damping parameter, default is 1.0 (no damping)
603: . -snes_linesearch_norms - Turn on/off the linesearch norms computation (SNESLineSearchSetComputeNorms())
604: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
605: - -snes_linesearch_max_it - The number of iterations for iterative line searches
607: Level: intermediate
609: Notes:
610: This is typically called from within a `SNESSolve()` implementation in order to
611: help with convergence of the nonlinear method. Various `SNES` types use line searches
612: in different ways, but the overarching theme is that a line search is used to determine
613: an optimal damping parameter of a step at each iteration of the method. Each
614: application of the line search may invoke `SNESComputeFunction()` several times, and
615: therefore may be fairly expensive.
617: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchGetLambda()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
618: `SNESLineSearchType`, `SNESLineSearchSetType()`
619: @*/
620: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y)
621: {
622: PetscFunctionBegin;
628: linesearch->result = SNES_LINESEARCH_SUCCEEDED;
630: linesearch->vec_sol = X;
631: linesearch->vec_update = Y;
632: linesearch->vec_func = F;
634: PetscCall(SNESLineSearchSetUp(linesearch));
636: if (!linesearch->keeplambda) linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */
638: if (fnorm) linesearch->fnorm = *fnorm;
639: else PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm));
641: PetscCall(PetscLogEventBegin(SNESLINESEARCH_Apply, linesearch, X, F, Y));
643: PetscUseTypeMethod(linesearch, apply);
645: PetscCall(PetscLogEventEnd(SNESLINESEARCH_Apply, linesearch, X, F, Y));
647: if (fnorm) *fnorm = linesearch->fnorm;
648: PetscFunctionReturn(PETSC_SUCCESS);
649: }
651: /*@
652: SNESLineSearchDestroy - Destroys the line search instance.
654: Collective
656: Input Parameter:
657: . linesearch - The line search context
659: Level: developer
661: Note:
662: The line search in `SNES` is automatically called on `SNESDestroy()` so this call is rarely needed
664: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
665: @*/
666: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch)
667: {
668: PetscFunctionBegin;
669: if (!*linesearch) PetscFunctionReturn(PETSC_SUCCESS);
671: if (--((PetscObject)*linesearch)->refct > 0) {
672: *linesearch = NULL;
673: PetscFunctionReturn(PETSC_SUCCESS);
674: }
675: PetscCall(PetscObjectSAWsViewOff((PetscObject)*linesearch));
676: PetscCall(SNESLineSearchReset(*linesearch));
677: PetscTryTypeMethod(*linesearch, destroy);
678: PetscCall(PetscViewerDestroy(&(*linesearch)->monitor));
679: PetscCall(SNESLineSearchMonitorCancel(*linesearch));
680: PetscCall(PetscHeaderDestroy(linesearch));
681: PetscFunctionReturn(PETSC_SUCCESS);
682: }
684: /*@
685: SNESLineSearchSetDefaultMonitor - Turns on/off printing useful information and debugging output about the line search.
687: Logically Collective
689: Input Parameters:
690: + linesearch - the linesearch object
691: - viewer - an `PETSCVIEWERASCII` `PetscViewer` or `NULL` to turn off monitor
693: Options Database Key:
694: . -snes_linesearch_monitor [:filename] - enables the monitor
696: Level: intermediate
698: Developer Notes:
699: This monitor is implemented differently than the other line search monitors that are set with
700: `SNESLineSearchMonitorSet()` since it is called in many locations of the line search routines to display aspects of the
701: line search that are not visible to the other monitors.
703: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PETSCVIEWERASCII`, `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`,
704: `SNESLineSearchMonitorSetFromOptions()`
705: @*/
706: PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
707: {
708: PetscFunctionBegin;
709: PetscCall(PetscViewerDestroy(&linesearch->monitor));
710: linesearch->monitor = viewer;
711: PetscFunctionReturn(PETSC_SUCCESS);
712: }
714: /*@
715: SNESLineSearchGetDefaultMonitor - Gets the `PetscViewer` instance for the default line search monitor that is turned on with `SNESLineSearchSetDefaultMonitor()`
717: Logically Collective
719: Input Parameter:
720: . linesearch - the line search context
722: Output Parameter:
723: . monitor - monitor context
725: Level: intermediate
727: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
728: @*/
729: PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
730: {
731: PetscFunctionBegin;
733: *monitor = linesearch->monitor;
734: PetscFunctionReturn(PETSC_SUCCESS);
735: }
737: /*@C
738: SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated in the options database
740: Collective
742: Input Parameters:
743: + ls - `SNESLineSearch` object to monitor
744: . name - the monitor type
745: . help - message indicating what monitoring is done
746: . manual - manual page for the monitor
747: . monitor - the monitor function
748: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNESLineSearch` or `PetscViewer`
750: Calling sequence of `monitor`:
751: + ls - `SNESLineSearch` object being monitored
752: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used
754: Calling sequence of `monitorsetup`:
755: + ls - `SNESLineSearch` object being monitored
756: - vf - a `PetscViewerAndFormat` struct that provides the `PetscViewer` and `PetscViewerFormat` being used
758: Level: advanced
760: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetMonitor()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
761: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
762: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
763: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
764: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
765: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
766: `PetscOptionsFList()`, `PetscOptionsEList()`
767: @*/
768: PetscErrorCode SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNESLineSearch ls, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(SNESLineSearch ls, PetscViewerAndFormat *vf))
769: {
770: PetscViewer viewer;
771: PetscViewerFormat format;
772: PetscBool flg;
774: PetscFunctionBegin;
775: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg));
776: if (flg) {
777: PetscViewerAndFormat *vf;
778: PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
779: PetscCall(PetscViewerDestroy(&viewer));
780: if (monitorsetup) PetscCall((*monitorsetup)(ls, vf));
781: PetscCall(SNESLineSearchMonitorSet(ls, (PetscErrorCode (*)(SNESLineSearch, void *))monitor, vf, (PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy));
782: }
783: PetscFunctionReturn(PETSC_SUCCESS);
784: }
786: /*@
787: SNESLineSearchSetFromOptions - Sets options for the line search
789: Logically Collective
791: Input Parameter:
792: . linesearch - a `SNESLineSearch` line search context
794: Options Database Keys:
795: + -snes_linesearch_type <type> - basic (or equivalently none), `bt`, `l2`, `cp`, `nleqerr`, `shell`
796: . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (`bt` supports 2 or 3)
797: . -snes_linesearch_norms - Turn on/off the linesearch norms for the basic linesearch typem (`SNESLineSearchSetComputeNorms()`)
798: . -snes_linesearch_minlambda - The minimum step length
799: . -snes_linesearch_maxstep - The maximum step size
800: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
801: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
802: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
803: . -snes_linesearch_max_it - The number of iterations for iterative line searches
804: . -snes_linesearch_monitor [:filename] - Print progress of line searches
805: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
806: . -snes_linesearch_damping - The linesearch damping parameter
807: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
808: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
809: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method
811: Level: intermediate
813: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
814: `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
815: @*/
816: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
817: {
818: const char *deft = SNESLINESEARCHBASIC;
819: char type[256];
820: PetscBool flg, set;
821: PetscViewer viewer;
823: PetscFunctionBegin;
824: PetscCall(SNESLineSearchRegisterAll());
826: PetscObjectOptionsBegin((PetscObject)linesearch);
827: if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
828: PetscCall(PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg));
829: if (flg) {
830: PetscCall(SNESLineSearchSetType(linesearch, type));
831: } else if (!((PetscObject)linesearch)->type_name) {
832: PetscCall(SNESLineSearchSetType(linesearch, deft));
833: }
835: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set));
836: if (set) PetscCall(SNESLineSearchSetDefaultMonitor(linesearch, viewer));
837: PetscCall(SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL));
839: /* tolerances */
840: PetscCall(PetscOptionsReal("-snes_linesearch_minlambda", "Minimum step length", "SNESLineSearchSetTolerances", linesearch->steptol, &linesearch->steptol, NULL));
841: PetscCall(PetscOptionsReal("-snes_linesearch_maxstep", "Maximum step size", "SNESLineSearchSetTolerances", linesearch->maxstep, &linesearch->maxstep, NULL));
842: PetscCall(PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL));
843: PetscCall(PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL));
844: PetscCall(PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL));
845: PetscCall(PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_its, &linesearch->max_its, NULL));
847: /* damping parameters */
848: PetscCall(PetscOptionsReal("-snes_linesearch_damping", "Line search damping and initial step guess", "SNESLineSearchSetDamping", linesearch->damping, &linesearch->damping, NULL));
850: PetscCall(PetscOptionsBool("-snes_linesearch_keeplambda", "Use previous lambda as damping", "SNESLineSearchSetKeepLambda", linesearch->keeplambda, &linesearch->keeplambda, NULL));
852: /* precheck */
853: PetscCall(PetscOptionsBool("-snes_linesearch_precheck_picard", "Use a correction that sometimes improves convergence of Picard iteration", "SNESLineSearchPreCheckPicard", flg, &flg, &set));
854: if (set) {
855: if (flg) {
856: linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */
858: 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));
859: PetscCall(SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle));
860: } else {
861: PetscCall(SNESLineSearchSetPreCheck(linesearch, NULL, NULL));
862: }
863: }
864: PetscCall(PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL));
865: PetscCall(PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL));
867: PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);
869: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject));
870: PetscOptionsEnd();
871: PetscFunctionReturn(PETSC_SUCCESS);
872: }
874: /*@
875: SNESLineSearchView - Prints useful information about the line search
877: Logically Collective
879: Input Parameters:
880: + linesearch - line search context
881: - viewer - the `PetscViewer` to display the line search information to
883: Level: intermediate
885: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`
886: @*/
887: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
888: {
889: PetscBool iascii;
891: PetscFunctionBegin;
893: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer));
895: PetscCheckSameComm(linesearch, 1, viewer, 2);
897: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
898: if (iascii) {
899: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer));
900: PetscCall(PetscViewerASCIIPushTab(viewer));
901: PetscTryTypeMethod(linesearch, view, viewer);
902: PetscCall(PetscViewerASCIIPopTab(viewer));
903: PetscCall(PetscViewerASCIIPrintf(viewer, " maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep, (double)linesearch->steptol));
904: PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol));
905: PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT "\n", linesearch->max_its));
906: if (linesearch->ops->precheck) {
907: if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
908: PetscCall(PetscViewerASCIIPrintf(viewer, " using precheck step to speed up Picard convergence\n"));
909: } else {
910: PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined precheck step\n"));
911: }
912: }
913: if (linesearch->ops->postcheck) PetscCall(PetscViewerASCIIPrintf(viewer, " using user-defined postcheck step\n"));
914: }
915: PetscFunctionReturn(PETSC_SUCCESS);
916: }
918: /*@
919: SNESLineSearchGetType - Gets the `SNESLinesearchType` of a `SNESLineSearch`
921: Logically Collective
923: Input Parameter:
924: . linesearch - the line search context
926: Output Parameter:
927: . type - The type of line search, or `NULL` if not set
929: Level: intermediate
931: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
932: @*/
933: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
934: {
935: PetscFunctionBegin;
937: PetscAssertPointer(type, 2);
938: *type = ((PetscObject)linesearch)->type_name;
939: PetscFunctionReturn(PETSC_SUCCESS);
940: }
942: /*@
943: SNESLineSearchSetType - Sets the `SNESLinesearchType` of a `SNESLineSearch` object to indicate the line search algorithm that should be used by a given `SNES` solver
945: Logically Collective
947: Input Parameters:
948: + linesearch - the line search context
949: - type - The type of line search to be used, see `SNESLineSearchType`
951: Options Database Key:
952: . -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
954: Level: intermediate
956: Note:
957: The `SNESLineSearch` object is generally obtained with `SNESGetLineSearch()`
959: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`,
960: `SNESGetLineSearch()`
961: @*/
962: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
963: {
964: PetscBool match;
965: PetscErrorCode (*r)(SNESLineSearch);
967: PetscFunctionBegin;
969: PetscAssertPointer(type, 2);
971: PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, type, &match));
972: if (match) PetscFunctionReturn(PETSC_SUCCESS);
974: PetscCall(PetscFunctionListFind(SNESLineSearchList, type, &r));
975: PetscCheck(r, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Line Search type %s", type);
976: /* Destroy the previous private line search context */
977: PetscTryTypeMethod(linesearch, destroy);
978: linesearch->ops->destroy = NULL;
979: /* Reinitialize function pointers in SNESLineSearchOps structure */
980: linesearch->ops->apply = NULL;
981: linesearch->ops->view = NULL;
982: linesearch->ops->setfromoptions = NULL;
983: linesearch->ops->destroy = NULL;
985: PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch, type));
986: PetscCall((*r)(linesearch));
987: PetscFunctionReturn(PETSC_SUCCESS);
988: }
990: /*@
991: SNESLineSearchSetSNES - Sets the `SNES` for the linesearch for function evaluation.
993: Input Parameters:
994: + linesearch - the line search context
995: - snes - The `SNES` instance
997: Level: developer
999: Note:
1000: This happens automatically when the line search is obtained/created with
1001: `SNESGetLineSearch()`. This routine is therefore mainly called within `SNES`
1002: implementations.
1004: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`
1005: @*/
1006: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
1007: {
1008: PetscFunctionBegin;
1011: linesearch->snes = snes;
1012: PetscFunctionReturn(PETSC_SUCCESS);
1013: }
1015: /*@
1016: SNESLineSearchGetSNES - Gets the `SNES` instance associated with the line search.
1018: Not Collective
1020: Input Parameter:
1021: . linesearch - the line search context
1023: Output Parameter:
1024: . snes - The `SNES` instance
1026: Level: developer
1028: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESType`, `SNESLineSearchSetVecs()`
1029: @*/
1030: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
1031: {
1032: PetscFunctionBegin;
1034: PetscAssertPointer(snes, 2);
1035: *snes = linesearch->snes;
1036: PetscFunctionReturn(PETSC_SUCCESS);
1037: }
1039: /*@
1040: SNESLineSearchGetLambda - Gets the last line search steplength used
1042: Not Collective
1044: Input Parameter:
1045: . linesearch - the line search context
1047: Output Parameter:
1048: . lambda - The last steplength computed during `SNESLineSearchApply()`
1050: Level: advanced
1052: Note:
1053: This is useful in methods where the solver is ill-scaled and
1054: requires some adaptive notion of the difference in scale between the
1055: solution and the function. For instance, `SNESQN` may be scaled by the
1056: line search lambda using the argument -snes_qn_scaling ls.
1058: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1059: @*/
1060: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1061: {
1062: PetscFunctionBegin;
1064: PetscAssertPointer(lambda, 2);
1065: *lambda = linesearch->lambda;
1066: PetscFunctionReturn(PETSC_SUCCESS);
1067: }
1069: /*@
1070: SNESLineSearchSetLambda - Sets the line search steplength
1072: Input Parameters:
1073: + linesearch - line search context
1074: - lambda - The steplength to use
1076: Level: advanced
1078: Note:
1079: This routine is typically used within implementations of `SNESLineSearchApply()`
1080: to set the final steplength. This routine (and `SNESLineSearchGetLambda()`) were
1081: added in order to facilitate Quasi-Newton methods that use the previous steplength
1082: as an inner scaling parameter.
1084: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetLambda()`
1085: @*/
1086: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1087: {
1088: PetscFunctionBegin;
1090: linesearch->lambda = lambda;
1091: PetscFunctionReturn(PETSC_SUCCESS);
1092: }
1094: /*@
1095: SNESLineSearchGetTolerances - Gets the tolerances for the line search.
1097: Not Collective
1099: Input Parameter:
1100: . linesearch - the line search context
1102: Output Parameters:
1103: + steptol - The minimum steplength
1104: . maxstep - The maximum steplength
1105: . rtol - The relative tolerance for iterative line searches
1106: . atol - The absolute tolerance for iterative line searches
1107: . ltol - The change in lambda tolerance for iterative line searches
1108: - max_its - The maximum number of iterations of the line search
1110: Level: intermediate
1112: Note:
1113: Different line searches may implement these parameters slightly differently as
1114: the type requires.
1116: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1117: @*/
1118: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *steptol, PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1119: {
1120: PetscFunctionBegin;
1122: if (steptol) {
1123: PetscAssertPointer(steptol, 2);
1124: *steptol = linesearch->steptol;
1125: }
1126: if (maxstep) {
1127: PetscAssertPointer(maxstep, 3);
1128: *maxstep = linesearch->maxstep;
1129: }
1130: if (rtol) {
1131: PetscAssertPointer(rtol, 4);
1132: *rtol = linesearch->rtol;
1133: }
1134: if (atol) {
1135: PetscAssertPointer(atol, 5);
1136: *atol = linesearch->atol;
1137: }
1138: if (ltol) {
1139: PetscAssertPointer(ltol, 6);
1140: *ltol = linesearch->ltol;
1141: }
1142: if (max_its) {
1143: PetscAssertPointer(max_its, 7);
1144: *max_its = linesearch->max_its;
1145: }
1146: PetscFunctionReturn(PETSC_SUCCESS);
1147: }
1149: /*@
1150: SNESLineSearchSetTolerances - Sets the tolerances for the linesearch.
1152: Collective
1154: Input Parameters:
1155: + linesearch - the line search context
1156: . steptol - The minimum steplength
1157: . maxstep - The maximum steplength
1158: . rtol - The relative tolerance for iterative line searches
1159: . atol - The absolute tolerance for iterative line searches
1160: . ltol - The change in lambda tolerance for iterative line searches
1161: - max_it - The maximum number of iterations of the line search
1163: Options Database Keys:
1164: + -snes_linesearch_minlambda - The minimum step length
1165: . -snes_linesearch_maxstep - The maximum step size
1166: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
1167: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
1168: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
1169: - -snes_linesearch_max_it - The number of iterations for iterative line searches
1171: Level: intermediate
1173: Note:
1174: The user may choose to not set any of the tolerances using `PETSC_DEFAULT` in place of an argument.
1176: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1177: @*/
1178: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal steptol, PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_it)
1179: {
1180: PetscFunctionBegin;
1189: if (steptol != (PetscReal)PETSC_DEFAULT) {
1190: PetscCheck(steptol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum step length %14.12e must be non-negative", (double)steptol);
1191: linesearch->steptol = steptol;
1192: }
1194: if (maxstep != (PetscReal)PETSC_DEFAULT) {
1195: PetscCheck(maxstep >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum step length %14.12e must be non-negative", (double)maxstep);
1196: linesearch->maxstep = maxstep;
1197: }
1199: if (rtol != (PetscReal)PETSC_DEFAULT) {
1200: 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);
1201: linesearch->rtol = rtol;
1202: }
1204: if (atol != (PetscReal)PETSC_DEFAULT) {
1205: PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %14.12e must be non-negative", (double)atol);
1206: linesearch->atol = atol;
1207: }
1209: if (ltol != (PetscReal)PETSC_DEFAULT) {
1210: PetscCheck(ltol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Lambda tolerance %14.12e must be non-negative", (double)ltol);
1211: linesearch->ltol = ltol;
1212: }
1214: if (max_it != PETSC_DEFAULT) {
1215: PetscCheck(max_it >= 0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", max_it);
1216: linesearch->max_its = max_it;
1217: }
1218: PetscFunctionReturn(PETSC_SUCCESS);
1219: }
1221: /*@
1222: SNESLineSearchGetDamping - Gets the line search damping parameter.
1224: Input Parameter:
1225: . linesearch - the line search context
1227: Output Parameter:
1228: . damping - The damping parameter
1230: Level: advanced
1232: .seealso: [](ch_snes), `SNES`, `SNESLineSearchGetStepTolerance()`, `SNESQN`
1233: @*/
1234: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1235: {
1236: PetscFunctionBegin;
1238: PetscAssertPointer(damping, 2);
1239: *damping = linesearch->damping;
1240: PetscFunctionReturn(PETSC_SUCCESS);
1241: }
1243: /*@
1244: SNESLineSearchSetDamping - Sets the line search damping parameter.
1246: Input Parameters:
1247: + linesearch - the line search context
1248: - damping - The damping parameter
1250: Options Database Key:
1251: . -snes_linesearch_damping <damping> - the damping value
1253: Level: intermediate
1255: Note:
1256: The `SNESLINESEARCHNONE` line search merely takes the update step scaled by the damping parameter.
1257: The use of the damping parameter in the `SNESLINESEARCHL2` and `SNESLINESEARCHCP` line searches is much more subtle;
1258: it is used as a starting point in calculating the secant step. However, the eventual
1259: step may be of greater length than the damping parameter. In the `SNESLINESEARCHBT` line search it is
1260: used as the maximum possible step length, as the `SNESLINESEARCHBT` line search only backtracks.
1262: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetDamping()`
1263: @*/
1264: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1265: {
1266: PetscFunctionBegin;
1268: linesearch->damping = damping;
1269: PetscFunctionReturn(PETSC_SUCCESS);
1270: }
1272: /*@
1273: SNESLineSearchGetOrder - Gets the line search approximation order.
1275: Input Parameter:
1276: . linesearch - the line search context
1278: Output Parameter:
1279: . order - The order
1281: Level: intermediate
1283: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetOrder()`
1284: @*/
1285: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1286: {
1287: PetscFunctionBegin;
1289: PetscAssertPointer(order, 2);
1290: *order = linesearch->order;
1291: PetscFunctionReturn(PETSC_SUCCESS);
1292: }
1294: /*@
1295: SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search
1297: Input Parameters:
1298: + linesearch - the line search context
1299: - order - The order
1301: Level: intermediate
1303: Values for `order`\:
1304: + 1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1305: . 2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1306: - 3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order
1308: Options Database Key:
1309: . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (`SNESLINESEARCHBT` supports 2 or 3)
1311: Note:
1312: These orders are supported by `SNESLINESEARCHBT` and `SNESLINESEARCHCP`
1314: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1315: @*/
1316: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1317: {
1318: PetscFunctionBegin;
1320: linesearch->order = order;
1321: PetscFunctionReturn(PETSC_SUCCESS);
1322: }
1324: /*@
1325: SNESLineSearchGetNorms - Gets the norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1327: Not Collective
1329: Input Parameter:
1330: . linesearch - the line search context
1332: Output Parameters:
1333: + xnorm - The norm of the current solution
1334: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution.
1335: - ynorm - The norm of the current update (after scaling by the linesearch computed lambda)
1337: Level: developer
1339: Notes:
1340: Some values may not be up-to-date at particular points in the code.
1342: This, in combination with `SNESLineSearchSetNorms()`, allow the line search and the `SNESSolve_XXX()` to share
1343: computed values.
1345: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1346: @*/
1347: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1348: {
1349: PetscFunctionBegin;
1351: if (xnorm) *xnorm = linesearch->xnorm;
1352: if (fnorm) *fnorm = linesearch->fnorm;
1353: if (ynorm) *ynorm = linesearch->ynorm;
1354: PetscFunctionReturn(PETSC_SUCCESS);
1355: }
1357: /*@
1358: SNESLineSearchSetNorms - Sets the computed norms for the current solution `X`, the current update `Y`, and the current function value `F`.
1360: Collective
1362: Input Parameters:
1363: + linesearch - the line search context
1364: . xnorm - The norm of the current solution
1365: . fnorm - The norm of the current function, this is the `norm(function(X))` where `X` is the current solution
1366: - ynorm - The norm of the current update (after scaling by the linesearch computed lambda)
1368: Level: developer
1370: Note:
1371: This is called by the line search routines to store the values they have just computed
1373: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1374: @*/
1375: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1376: {
1377: PetscFunctionBegin;
1379: linesearch->xnorm = xnorm;
1380: linesearch->fnorm = fnorm;
1381: linesearch->ynorm = ynorm;
1382: PetscFunctionReturn(PETSC_SUCCESS);
1383: }
1385: /*@
1386: SNESLineSearchComputeNorms - Explicitly computes the norms of the current solution `X`, the current update `Y`, and the current function value `F`.
1388: Input Parameter:
1389: . linesearch - the line search context
1391: Options Database Key:
1392: . -snes_linesearch_norms - turn norm computation on or off
1394: Level: intermediate
1396: Developer Note:
1397: The options database key is misnamed. It should be -snes_linesearch_compute_norms
1399: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1400: @*/
1401: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1402: {
1403: SNES snes;
1405: PetscFunctionBegin;
1406: if (linesearch->norms) {
1407: if (linesearch->ops->vinorm) {
1408: PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1409: PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1410: PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1411: PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1412: } else {
1413: PetscCall(VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1414: PetscCall(VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1415: PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1416: PetscCall(VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1417: PetscCall(VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1418: PetscCall(VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1419: }
1420: }
1421: PetscFunctionReturn(PETSC_SUCCESS);
1422: }
1424: /*@
1425: SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.
1427: Input Parameters:
1428: + linesearch - the line search context
1429: - flg - indicates whether or not to compute norms
1431: Options Database Key:
1432: . -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic (none) `SNESLINESEARCHBASIC` line search
1434: Level: intermediate
1436: Note:
1437: This is most relevant to the `SNESLINESEARCHBASIC` (or equivalently `SNESLINESEARCHNONE`) line search type since most line searches have a stopping criteria involving the norm.
1439: Developer Note:
1440: The options database key is misnamed. It should be -snes_linesearch_compute_norms
1442: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1443: @*/
1444: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1445: {
1446: PetscFunctionBegin;
1447: linesearch->norms = flg;
1448: PetscFunctionReturn(PETSC_SUCCESS);
1449: }
1451: /*@
1452: SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context
1454: Not Collective but the vectors are parallel
1456: Input Parameter:
1457: . linesearch - the line search context
1459: Output Parameters:
1460: + X - Solution vector
1461: . F - Function vector
1462: . Y - Search direction vector
1463: . W - Solution work vector
1464: - G - Function work vector
1466: Level: advanced
1468: Notes:
1469: At the beginning of a line search application, `X` should contain a
1470: solution and the vector `F` the function computed at `X`. At the end of the
1471: line search application, `X` should contain the new solution, and `F` the
1472: function evaluated at the new solution.
1474: These vectors are owned by the `SNESLineSearch` and should not be destroyed by the caller
1476: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1477: @*/
1478: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1479: {
1480: PetscFunctionBegin;
1482: if (X) {
1483: PetscAssertPointer(X, 2);
1484: *X = linesearch->vec_sol;
1485: }
1486: if (F) {
1487: PetscAssertPointer(F, 3);
1488: *F = linesearch->vec_func;
1489: }
1490: if (Y) {
1491: PetscAssertPointer(Y, 4);
1492: *Y = linesearch->vec_update;
1493: }
1494: if (W) {
1495: PetscAssertPointer(W, 5);
1496: *W = linesearch->vec_sol_new;
1497: }
1498: if (G) {
1499: PetscAssertPointer(G, 6);
1500: *G = linesearch->vec_func_new;
1501: }
1502: PetscFunctionReturn(PETSC_SUCCESS);
1503: }
1505: /*@
1506: SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context
1508: Logically Collective
1510: Input Parameters:
1511: + linesearch - the line search context
1512: . X - Solution vector
1513: . F - Function vector
1514: . Y - Search direction vector
1515: . W - Solution work vector
1516: - G - Function work vector
1518: Level: developer
1520: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1521: @*/
1522: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1523: {
1524: PetscFunctionBegin;
1526: if (X) {
1528: linesearch->vec_sol = X;
1529: }
1530: if (F) {
1532: linesearch->vec_func = F;
1533: }
1534: if (Y) {
1536: linesearch->vec_update = Y;
1537: }
1538: if (W) {
1540: linesearch->vec_sol_new = W;
1541: }
1542: if (G) {
1544: linesearch->vec_func_new = G;
1545: }
1546: PetscFunctionReturn(PETSC_SUCCESS);
1547: }
1549: /*@
1550: SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1551: `SNESLineSearch` options in the database.
1553: Logically Collective
1555: Input Parameters:
1556: + linesearch - the `SNESLineSearch` context
1557: - prefix - the prefix to prepend to all option names
1559: Level: advanced
1561: Note:
1562: A hyphen (-) must NOT be given at the beginning of the prefix name.
1563: The first character of all runtime options is AUTOMATICALLY the hyphen.
1565: .seealso: [](ch_snes), `SNES`, `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1566: @*/
1567: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1568: {
1569: PetscFunctionBegin;
1571: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix));
1572: PetscFunctionReturn(PETSC_SUCCESS);
1573: }
1575: /*@
1576: SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1577: SNESLineSearch options in the database.
1579: Not Collective
1581: Input Parameter:
1582: . linesearch - the `SNESLineSearch` context
1584: Output Parameter:
1585: . prefix - pointer to the prefix string used
1587: Level: advanced
1589: Fortran Notes:
1590: The user should pass in a string 'prefix' of
1591: sufficient length to hold the prefix.
1593: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1594: @*/
1595: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1596: {
1597: PetscFunctionBegin;
1599: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix));
1600: PetscFunctionReturn(PETSC_SUCCESS);
1601: }
1603: /*@C
1604: SNESLineSearchSetWorkVecs - Sets work vectors for the line search.
1606: Input Parameters:
1607: + linesearch - the `SNESLineSearch` context
1608: - nwork - the number of work vectors
1610: Level: developer
1612: Developer Note:
1613: This is called from within the set up routines for each of the line search types `SNESLineSearchType`
1615: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESSetWorkVecs()`
1616: @*/
1617: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1618: {
1619: PetscFunctionBegin;
1620: PetscCheck(linesearch->vec_sol, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1621: PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1622: PetscFunctionReturn(PETSC_SUCCESS);
1623: }
1625: /*@
1626: SNESLineSearchGetReason - Gets the success/failure status of the last line search application
1628: Input Parameter:
1629: . linesearch - the line search context
1631: Output Parameter:
1632: . result - The success or failure status
1634: Level: developer
1636: Note:
1637: This is typically called after `SNESLineSearchApply()` in order to determine if the line search failed
1638: (and set into the `SNES` convergence accordingly).
1640: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1641: @*/
1642: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1643: {
1644: PetscFunctionBegin;
1646: PetscAssertPointer(result, 2);
1647: *result = linesearch->result;
1648: PetscFunctionReturn(PETSC_SUCCESS);
1649: }
1651: /*@
1652: SNESLineSearchSetReason - Sets the success/failure status of the line search application
1654: Logically Collective; No Fortran Support
1656: Input Parameters:
1657: + linesearch - the line search context
1658: - result - The success or failure status
1660: Level: developer
1662: Note:
1663: This is typically called in a `SNESLineSearchType` implementation of `SNESLineSearchApply()` or a `SNESLINESEARCHSHELL` implementation to set
1664: the success or failure of the line search method.
1666: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`
1667: @*/
1668: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1669: {
1670: PetscFunctionBegin;
1672: linesearch->result = result;
1673: PetscFunctionReturn(PETSC_SUCCESS);
1674: }
1676: // PetscClangLinter pragma disable: -fdoc-param-list-func-parameter-documentation
1677: /*@C
1678: SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.
1680: Logically Collective
1682: Input Parameters:
1683: + linesearch - the linesearch object
1684: . projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1685: - normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn` for calling sequence
1687: Level: advanced
1689: Notes:
1690: The VI solvers require projection of the solution to the feasible set. `projectfunc` should implement this.
1692: The VI solvers require special evaluation of the function norm such that the norm is only calculated
1693: on the inactive set. This should be implemented by `normfunc`.
1695: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`,
1696: `SNESLineSearchVIProjectFn`, `SNESLineSearchVINormFn`
1697: @*/
1698: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFn *projectfunc, SNESLineSearchVINormFn *normfunc)
1699: {
1700: PetscFunctionBegin;
1702: if (projectfunc) linesearch->ops->viproject = projectfunc;
1703: if (normfunc) linesearch->ops->vinorm = normfunc;
1704: PetscFunctionReturn(PETSC_SUCCESS);
1705: }
1707: /*@C
1708: SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.
1710: Not Collective
1712: Input Parameter:
1713: . linesearch - the line search context, obtain with `SNESGetLineSearch()`
1715: Output Parameters:
1716: + projectfunc - function for projecting the function to the bounds, see `SNESLineSearchVIProjectFn` for calling sequence
1717: - normfunc - function for computing the norm of an active set, see `SNESLineSearchVINormFn ` 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)
1725: {
1726: PetscFunctionBegin;
1727: if (projectfunc) *projectfunc = linesearch->ops->viproject;
1728: if (normfunc) *normfunc = linesearch->ops->vinorm;
1729: PetscFunctionReturn(PETSC_SUCCESS);
1730: }
1732: /*@C
1733: SNESLineSearchRegister - register a line search type `SNESLineSearchType`
1735: Logically Collective, No Fortran Support
1737: Input Parameters:
1738: + sname - name of the `SNESLineSearchType()`
1739: - function - the creation function for that type
1741: Calling sequence of `function`:
1742: . ls - the line search context
1744: Level: advanced
1746: .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1747: @*/
1748: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch ls))
1749: {
1750: PetscFunctionBegin;
1751: PetscCall(SNESInitializePackage());
1752: PetscCall(PetscFunctionListAdd(&SNESLineSearchList, sname, function));
1753: PetscFunctionReturn(PETSC_SUCCESS);
1754: }