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 Parameters:
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: Notes:
23: There is no way to clear one specific monitor from a `SNESLineSearch` object.
25: This does not clear the monitor set with `SNESLineSearchSetDefaultMonitor()` use `SNESLineSearchSetDefaultMonitor`(ls,NULL) to cancel
26: that one.
28: Level: advanced
30: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorSet()`
31: @*/
32: PetscErrorCode SNESLineSearchMonitorCancel(SNESLineSearch ls)
33: {
34: PetscInt i;
37: for (i = 0; i < ls->numbermonitors; i++) {
38: if (ls->monitordestroy[i]) (*ls->monitordestroy[i])(&ls->monitorcontext[i]);
39: }
40: ls->numbermonitors = 0;
41: return 0;
42: }
44: /*@
45: SNESLineSearchMonitor - runs the user provided monitor routines, if they exist
47: Collective
49: Input Parameters:
50: . ls - the linesearch object
52: Note:
53: This routine is called by the SNES implementations.
54: It does not typically need to be called by the user.
56: Level: developer
58: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorSet()`
59: @*/
60: PetscErrorCode SNESLineSearchMonitor(SNESLineSearch ls)
61: {
62: PetscInt i, n = ls->numbermonitors;
64: for (i = 0; i < n; i++) (*ls->monitorftns[i])(ls, ls->monitorcontext[i]);
65: return 0;
66: }
68: /*@C
69: SNESLineSearchMonitorSet - Sets an ADDITIONAL function that is to be used at every
70: iteration of the nonlinear solver to display the iteration's
71: progress.
73: Logically Collective
75: Input Parameters:
76: + ls - the `SNESLineSearch` context
77: . f - the monitor function
78: . mctx - [optional] user-defined context for private data for the
79: monitor routine (use NULL if no context is desired)
80: - monitordestroy - [optional] routine that frees monitor context
81: (may be NULL)
83: Note:
84: Several different monitoring routines may be set by calling
85: `SNESLineSearchMonitorSet()` multiple times; all will be called in the
86: order in which they were set.
88: Fortran Note:
89: Only a single monitor function can be set for each `SNESLineSearch` object
91: Level: intermediate
93: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorCancel()`
94: @*/
95: PetscErrorCode SNESLineSearchMonitorSet(SNESLineSearch ls, PetscErrorCode (*f)(SNESLineSearch, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
96: {
97: PetscInt i;
98: PetscBool identical;
101: for (i = 0; i < ls->numbermonitors; i++) {
102: PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))ls->monitorftns[i], ls->monitorcontext[i], ls->monitordestroy[i], &identical);
103: if (identical) return 0;
104: }
106: ls->monitorftns[ls->numbermonitors] = f;
107: ls->monitordestroy[ls->numbermonitors] = monitordestroy;
108: ls->monitorcontext[ls->numbermonitors++] = (void *)mctx;
109: return 0;
110: }
112: /*@C
113: SNESLineSearchMonitorSolutionUpdate - Monitors each update of the function value the linesearch tries
115: Collective
117: Input Parameters:
118: + ls - the `SNES` linesearch object
119: - vf - the context for the monitor, in this case it is an `PetscViewerAndFormat`
121: Level: intermediate
123: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESMonitorSet()`, `SNESMonitorSolution()`
124: @*/
125: PetscErrorCode SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls, PetscViewerAndFormat *vf)
126: {
127: PetscViewer viewer = vf->viewer;
128: Vec Y, W, G;
130: SNESLineSearchGetVecs(ls, NULL, NULL, &Y, &W, &G);
131: PetscViewerPushFormat(viewer, vf->format);
132: PetscViewerASCIIPrintf(viewer, "LineSearch attempted update to solution \n");
133: VecView(Y, viewer);
134: PetscViewerASCIIPrintf(viewer, "LineSearch attempted new solution \n");
135: VecView(W, viewer);
136: PetscViewerASCIIPrintf(viewer, "LineSearch attempted updated function value\n");
137: VecView(G, viewer);
138: PetscViewerPopFormat(viewer);
139: return 0;
140: }
142: /*@
143: SNESLineSearchCreate - Creates the line search context.
145: Logically Collective
147: Input Parameters:
148: . comm - MPI communicator for the line search (typically from the associated `SNES` context).
150: Output Parameters:
151: . outlinesearch - the new linesearch context
153: Level: developer
155: Note:
156: The preferred calling sequence for users is to use `SNESGetLineSearch()` to acquire the `SNESLineSearch` instance
157: already associated with the `SNES`.
159: .seealso: `SNESLineSearch`, `LineSearchDestroy()`, `SNESGetLineSearch()`
160: @*/
161: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
162: {
163: SNESLineSearch linesearch;
166: SNESInitializePackage();
167: *outlinesearch = NULL;
169: PetscHeaderCreate(linesearch, SNESLINESEARCH_CLASSID, "SNESLineSearch", "Linesearch", "SNESLineSearch", comm, SNESLineSearchDestroy, SNESLineSearchView);
171: linesearch->vec_sol_new = NULL;
172: linesearch->vec_func_new = NULL;
173: linesearch->vec_sol = NULL;
174: linesearch->vec_func = NULL;
175: linesearch->vec_update = NULL;
177: linesearch->lambda = 1.0;
178: linesearch->fnorm = 1.0;
179: linesearch->ynorm = 1.0;
180: linesearch->xnorm = 1.0;
181: linesearch->result = SNES_LINESEARCH_SUCCEEDED;
182: linesearch->norms = PETSC_TRUE;
183: linesearch->keeplambda = PETSC_FALSE;
184: linesearch->damping = 1.0;
185: linesearch->maxstep = 1e8;
186: linesearch->steptol = 1e-12;
187: linesearch->rtol = 1e-8;
188: linesearch->atol = 1e-15;
189: linesearch->ltol = 1e-8;
190: linesearch->precheckctx = NULL;
191: linesearch->postcheckctx = NULL;
192: linesearch->max_its = 1;
193: linesearch->setupcalled = PETSC_FALSE;
194: linesearch->monitor = NULL;
195: *outlinesearch = linesearch;
196: return 0;
197: }
199: /*@
200: SNESLineSearchSetUp - Prepares the line search for being applied by allocating
201: any required vectors.
203: Collective
205: Input Parameters:
206: . linesearch - The `SNESLineSearch` instance.
208: Note:
209: For most cases, this needn't be called by users or outside of `SNESLineSearchApply()`.
210: The only current case where this is called outside of this is for the VI
211: solvers, which modify the solution and work vectors before the first call
212: of `SNESLineSearchApply()`, requiring the `SNESLineSearch` work vectors to be
213: allocated upfront.
215: Level: advanced
217: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchReset()`
218: @*/
220: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
221: {
222: if (!((PetscObject)linesearch)->type_name) SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC);
223: if (!linesearch->setupcalled) {
224: if (!linesearch->vec_sol_new) VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
225: if (!linesearch->vec_func_new) VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
226: if (linesearch->ops->setup) PetscUseTypeMethod(linesearch, setup);
227: if (!linesearch->ops->snesfunc) SNESLineSearchSetFunction(linesearch, SNESComputeFunction);
228: linesearch->lambda = linesearch->damping;
229: linesearch->setupcalled = PETSC_TRUE;
230: }
231: return 0;
232: }
234: /*@
235: SNESLineSearchReset - Undoes the `SNESLineSearchSetUp()` and deletes any `Vec`s or `Mat`s allocated by the line search.
237: Collective
239: Input Parameters:
240: . linesearch - The `SNESLineSearch` instance.
242: Note:
243: Usually only called by `SNESReset()`
245: Level: developer
247: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetUp()`
248: @*/
250: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
251: {
252: if (linesearch->ops->reset) PetscUseTypeMethod(linesearch, reset);
254: VecDestroy(&linesearch->vec_sol_new);
255: VecDestroy(&linesearch->vec_func_new);
257: VecDestroyVecs(linesearch->nwork, &linesearch->work);
259: linesearch->nwork = 0;
260: linesearch->setupcalled = PETSC_FALSE;
261: return 0;
262: }
264: /*@C
265: SNESLineSearchSetFunction - Sets the function evaluation used by the `SNES` line search
266: `
267: Input Parameters:
268: . linesearch - the `SNESLineSearch` context
269: + func - function evaluation routine, this is usually the function provided with `SNESSetFunction()`
271: Level: developer
273: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESSetFunction()`
274: @*/
275: PetscErrorCode SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES, Vec, Vec))
276: {
278: linesearch->ops->snesfunc = func;
279: return 0;
280: }
282: /*@C
283: SNESLineSearchSetPreCheck - Sets a user function that is called after the initial search direction has been computed but
284: before the line search routine has been applied. Allows the user to adjust the result of (usually a linear solve) that
285: determined the search direction.
287: Logically Collective
289: Input Parameters:
290: + linesearch - the `SNESLineSearch` context
291: . func - [optional] function evaluation routine, see `SNESLineSearchPreCheck()` for the calling sequence
292: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
294: Level: intermediate
296: Note:
297: Use `SNESLineSearchSetPostCheck()` to change the step after the line search.
298: search is complete.
300: Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
302: .seealso: `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
303: `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()
305: @*/
306: PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void *ctx)
307: {
309: if (func) linesearch->ops->precheck = func;
310: if (ctx) linesearch->precheckctx = ctx;
311: return 0;
312: }
314: /*@C
315: SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.
317: Input Parameter:
318: . linesearch - the `SNESLineSearch` context
320: Output Parameters:
321: + func - [optional] function evaluation routine, see `SNESLineSearchPreCheck` for calling sequence
322: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
324: Level: intermediate
326: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
327: @*/
328: PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void **ctx)
329: {
331: if (func) *func = linesearch->ops->precheck;
332: if (ctx) *ctx = linesearch->precheckctx;
333: return 0;
334: }
336: /*@C
337: SNESLineSearchSetPostCheck - Sets a user function that is called after the line search has been applied to determine the step
338: direction and length. Allows the user a chance to change or override the decision of the line search routine
340: Logically Collective linesearch
342: Input Parameters:
343: + linesearch - the `SNESLineSearch` context
344: . func - [optional] function evaluation routine, see `SNESLineSearchPostCheck` for the calling sequence
345: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
347: Level: intermediate
349: Notes:
350: Use `SNESLineSearchSetPreCheck()` to change the step before the line search.
351: search is complete.
353: Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
355: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
356: `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()
357: @*/
358: PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void *ctx)
359: {
361: if (func) linesearch->ops->postcheck = func;
362: if (ctx) linesearch->postcheckctx = ctx;
363: return 0;
364: }
366: /*@C
367: SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.
369: Input Parameter:
370: . linesearch - the `SNESLineSearch` context
372: Output Parameters:
373: + func - [optional] function evaluation routine, see for the calling sequence `SNESLineSearchPostCheck`
374: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
376: Level: intermediate
378: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
379: @*/
380: PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void **ctx)
381: {
383: if (func) *func = linesearch->ops->postcheck;
384: if (ctx) *ctx = linesearch->postcheckctx;
385: return 0;
386: }
388: /*@
389: SNESLineSearchPreCheck - Prepares the line search for being applied.
391: Logically Collective
393: Input Parameters:
394: + linesearch - The linesearch instance.
395: . X - The current solution
396: - Y - The step direction
398: Output Parameters:
399: . changed - Indicator that the precheck routine has changed anything
401: Level: advanced
403: Note:
404: This calls any function provided with `SNESLineSearchSetPreCheck()`
406: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
407: `SNESLineSearchGetPostCheck()``
408: @*/
409: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed)
410: {
411: *changed = PETSC_FALSE;
412: if (linesearch->ops->precheck) {
413: PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
415: }
416: return 0;
417: }
419: /*@
420: SNESLineSearchPostCheck - Hook to modify step direction or updated solution after a successful linesearch
422: Logically Collective
424: Input Parameters:
425: + linesearch - The linesearch context
426: . X - The last solution
427: . Y - The step direction
428: - W - The updated solution, W = X + lambda*Y for some lambda
430: Output Parameters:
431: + changed_Y - Indicator if the direction Y has been changed.
432: - changed_W - Indicator if the new candidate solution W has been changed.
434: Note:
435: This calls any function provided with `SNESLineSearchSetPreCheck()`
437: Level: developer
439: .seealso: `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
440: @*/
441: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W)
442: {
443: *changed_Y = PETSC_FALSE;
444: *changed_W = PETSC_FALSE;
445: if (linesearch->ops->postcheck) {
446: PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
449: }
450: return 0;
451: }
453: /*@C
454: SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration
456: Logically Collective
458: Input Parameters:
459: + linesearch - linesearch context
460: . X - base state for this step
461: - ctx - context for this function
463: Input/Output Parameter:
464: . Y - correction, possibly modified
466: Output Parameter:
467: . changed - flag indicating that Y was modified
469: Options Database Key:
470: + -snes_linesearch_precheck_picard - activate this routine
471: - -snes_linesearch_precheck_picard_angle - angle
473: Level: advanced
475: Notes:
476: This function should be passed to `SNESLineSearchSetPreCheck()`
478: The justification for this method involves the linear convergence of a Picard iteration
479: so the Picard linearization should be provided in place of the "Jacobian". This correction
480: is generally not useful when using a Newton linearization.
482: Reference:
483: . - * - Hindmarsh and Payne (1996) Time step limits for stable solutions of the ice sheet equation, Annals of Glaciology.
485: .seealso: `SNESLineSearch`, `SNESSetPicard()`, `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`
486: @*/
487: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, void *ctx)
488: {
489: PetscReal angle = *(PetscReal *)linesearch->precheckctx;
490: Vec Ylast;
491: PetscScalar dot;
492: PetscInt iter;
493: PetscReal ynorm, ylastnorm, theta, angle_radians;
494: SNES snes;
496: SNESLineSearchGetSNES(linesearch, &snes);
497: PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast);
498: if (!Ylast) {
499: VecDuplicate(Y, &Ylast);
500: PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast);
501: PetscObjectDereference((PetscObject)Ylast);
502: }
503: SNESGetIterationNumber(snes, &iter);
504: if (iter < 2) {
505: VecCopy(Y, Ylast);
506: *changed = PETSC_FALSE;
507: return 0;
508: }
510: VecDot(Y, Ylast, &dot);
511: VecNorm(Y, NORM_2, &ynorm);
512: VecNorm(Ylast, NORM_2, &ylastnorm);
513: /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
514: theta = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
515: angle_radians = angle * PETSC_PI / 180.;
516: if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
517: /* Modify the step Y */
518: PetscReal alpha, ydiffnorm;
519: VecAXPY(Ylast, -1.0, Y);
520: VecNorm(Ylast, NORM_2, &ydiffnorm);
521: alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
522: VecCopy(Y, Ylast);
523: VecScale(Y, alpha);
524: 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);
525: *changed = PETSC_TRUE;
526: } else {
527: PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180. / PETSC_PI), (double)angle);
528: VecCopy(Y, Ylast);
529: *changed = PETSC_FALSE;
530: }
531: return 0;
532: }
534: /*@
535: SNESLineSearchApply - Computes the line-search update.
537: Collective
539: Input Parameters:
540: + linesearch - The linesearch context
541: - Y - The search direction
543: Input/Output Parameters:
544: + X - The current solution, on output the new solution
545: . F - The current function, on output the new function
546: - fnorm - The current norm, on output the new function norm
548: Options Database Keys:
549: + -snes_linesearch_type - basic (or equivalently none), bt, l2, cp, nleqerr, shell
550: . -snes_linesearch_monitor [:filename] - Print progress of line searches
551: . -snes_linesearch_damping - The linesearch damping parameter, default is 1.0 (no damping)
552: . -snes_linesearch_norms - Turn on/off the linesearch norms computation (SNESLineSearchSetComputeNorms())
553: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
554: - -snes_linesearch_max_it - The number of iterations for iterative line searches
556: Notes:
557: This is typically called from within a `SNESSolve()` implementation in order to
558: help with convergence of the nonlinear method. Various `SNES` types use line searches
559: in different ways, but the overarching theme is that a line search is used to determine
560: an optimal damping parameter of a step at each iteration of the method. Each
561: application of the line search may invoke `SNESComputeFunction()` several times, and
562: therefore may be fairly expensive.
564: Level: Intermediate
566: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
567: `SNESLineSearchType`, `SNESLineSearchSetType()`
568: @*/
569: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y)
570: {
576: linesearch->result = SNES_LINESEARCH_SUCCEEDED;
578: linesearch->vec_sol = X;
579: linesearch->vec_update = Y;
580: linesearch->vec_func = F;
582: SNESLineSearchSetUp(linesearch);
584: if (!linesearch->keeplambda) linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */
586: if (fnorm) linesearch->fnorm = *fnorm;
587: else VecNorm(F, NORM_2, &linesearch->fnorm);
589: PetscLogEventBegin(SNESLINESEARCH_Apply, linesearch, X, F, Y);
591: PetscUseTypeMethod(linesearch, apply);
593: PetscLogEventEnd(SNESLINESEARCH_Apply, linesearch, X, F, Y);
595: if (fnorm) *fnorm = linesearch->fnorm;
596: return 0;
597: }
599: /*@
600: SNESLineSearchDestroy - Destroys the line search instance.
602: Collective
604: Input Parameters:
605: . linesearch - The linesearch context
607: Level: developer
609: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
610: @*/
611: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch)
612: {
613: if (!*linesearch) return 0;
615: if (--((PetscObject)(*linesearch))->refct > 0) {
616: *linesearch = NULL;
617: return 0;
618: }
619: PetscObjectSAWsViewOff((PetscObject)*linesearch);
620: SNESLineSearchReset(*linesearch);
621: if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
622: PetscViewerDestroy(&(*linesearch)->monitor);
623: SNESLineSearchMonitorCancel((*linesearch));
624: PetscHeaderDestroy(linesearch);
625: return 0;
626: }
628: /*@
629: SNESLineSearchSetDefaultMonitor - Turns on/off printing useful information and debugging output about the line search.
631: Logically Collective
633: Input Parameters:
634: + linesearch - the linesearch object
635: - viewer - an `PETSCVIEWERASCII` `PetscViewer` or NULL to turn off monitor
637: Options Database Key:
638: . -snes_linesearch_monitor [:filename] - enables the monitor
640: Level: intermediate
642: Developer Note:
643: This monitor is implemented differently than the other line search monitors that are set with
644: `SNESLineSearchMonitorSet()` since it is called in many locations of the line search routines to display aspects of the
645: line search that are not visible to the other monitors.
647: .seealso: `SNESLineSearch`, `PETSCVIEWERASCII`, `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`,
648: `SNESLineSearchMonitorSetFromOptions()`
649: @*/
650: PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
651: {
652: if (viewer) PetscObjectReference((PetscObject)viewer);
653: PetscViewerDestroy(&linesearch->monitor);
654: linesearch->monitor = viewer;
655: return 0;
656: }
658: /*@
659: SNESLineSearchGetDefaultMonitor - Gets the `PetscViewer` instance for the line search monitor.
661: Logically Collective
663: Input Parameter:
664: . linesearch - linesearch context
666: Output Parameter:
667: . monitor - monitor context
669: Level: intermediate
671: .seealso: `SNESLineSearch`, `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
672: @*/
673: PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
674: {
676: *monitor = linesearch->monitor;
677: return 0;
678: }
680: /*@C
681: SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
683: Collective
685: Input Parameters:
686: + ls - `SNESLineSearch` object you wish to monitor
687: . name - the monitor type one is seeking
688: . help - message indicating what monitoring is done
689: . manual - manual page for the monitor
690: . monitor - the monitor function
691: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNESLineSearch` or `PetscViewer`
693: Level: developer
695: .seealso: `SNESLineSearch`, `SNESLineSearchSetMonitor()`, `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
696: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
697: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
698: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
699: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
700: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
701: `PetscOptionsFList()`, `PetscOptionsEList()`
702: @*/
703: PetscErrorCode SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNESLineSearch, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(SNESLineSearch, PetscViewerAndFormat *))
704: {
705: PetscViewer viewer;
706: PetscViewerFormat format;
707: PetscBool flg;
709: PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg);
710: if (flg) {
711: PetscViewerAndFormat *vf;
712: PetscViewerAndFormatCreate(viewer, format, &vf);
713: PetscObjectDereference((PetscObject)viewer);
714: if (monitorsetup) (*monitorsetup)(ls, vf);
715: SNESLineSearchMonitorSet(ls, (PetscErrorCode(*)(SNESLineSearch, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
716: }
717: return 0;
718: }
720: /*@
721: SNESLineSearchSetFromOptions - Sets options for the line search
723: Logically Collective
725: Input Parameter:
726: . linesearch - linesearch context
728: Options Database Keys:
729: + -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
730: . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (bt supports 2 or 3)
731: . -snes_linesearch_norms - Turn on/off the linesearch norms for the basic linesearch typem (`SNESLineSearchSetComputeNorms()`)
732: . -snes_linesearch_minlambda - The minimum step length
733: . -snes_linesearch_maxstep - The maximum step size
734: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
735: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
736: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
737: . -snes_linesearch_max_it - The number of iterations for iterative line searches
738: . -snes_linesearch_monitor [:filename] - Print progress of line searches
739: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
740: . -snes_linesearch_damping - The linesearch damping parameter
741: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
742: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
743: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method
745: Level: intermediate
747: .seealso: `SNESLineSearch`, `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
748: `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
749: @*/
750: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
751: {
752: const char *deft = SNESLINESEARCHBASIC;
753: char type[256];
754: PetscBool flg, set;
755: PetscViewer viewer;
757: SNESLineSearchRegisterAll();
759: PetscObjectOptionsBegin((PetscObject)linesearch);
760: if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
761: PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg);
762: if (flg) {
763: SNESLineSearchSetType(linesearch, type);
764: } else if (!((PetscObject)linesearch)->type_name) {
765: SNESLineSearchSetType(linesearch, deft);
766: }
768: PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set);
769: if (set) {
770: SNESLineSearchSetDefaultMonitor(linesearch, viewer);
771: PetscViewerDestroy(&viewer);
772: }
773: SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL);
775: /* tolerances */
776: PetscOptionsReal("-snes_linesearch_minlambda", "Minimum step length", "SNESLineSearchSetTolerances", linesearch->steptol, &linesearch->steptol, NULL);
777: PetscOptionsReal("-snes_linesearch_maxstep", "Maximum step size", "SNESLineSearchSetTolerances", linesearch->maxstep, &linesearch->maxstep, NULL);
778: PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL);
779: PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL);
780: PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL);
781: PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_its, &linesearch->max_its, NULL);
783: /* damping parameters */
784: PetscOptionsReal("-snes_linesearch_damping", "Line search damping and initial step guess", "SNESLineSearchSetDamping", linesearch->damping, &linesearch->damping, NULL);
786: PetscOptionsBool("-snes_linesearch_keeplambda", "Use previous lambda as damping", "SNESLineSearchSetKeepLambda", linesearch->keeplambda, &linesearch->keeplambda, NULL);
788: /* precheck */
789: PetscOptionsBool("-snes_linesearch_precheck_picard", "Use a correction that sometimes improves convergence of Picard iteration", "SNESLineSearchPreCheckPicard", flg, &flg, &set);
790: if (set) {
791: if (flg) {
792: linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */
794: PetscOptionsReal("-snes_linesearch_precheck_picard_angle", "Maximum angle at which to activate the correction", "none", linesearch->precheck_picard_angle, &linesearch->precheck_picard_angle, NULL);
795: SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle);
796: } else {
797: SNESLineSearchSetPreCheck(linesearch, NULL, NULL);
798: }
799: }
800: PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL);
801: PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL);
803: PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);
805: PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject);
806: PetscOptionsEnd();
807: return 0;
808: }
810: /*@
811: SNESLineSearchView - Prints useful information about the line search
813: Input Parameters:
814: . linesearch - linesearch context
816: Logically Collective
818: Level: intermediate
820: .seealso: `SNESLineSearch`, `PetscViewer`, `SNESLineSearchCreate()`
821: @*/
822: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
823: {
824: PetscBool iascii;
827: if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer);
831: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
832: if (iascii) {
833: PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer);
834: PetscViewerASCIIPushTab(viewer);
835: PetscTryTypeMethod(linesearch, view, viewer);
836: PetscViewerASCIIPopTab(viewer);
837: PetscViewerASCIIPrintf(viewer, " maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep, (double)linesearch->steptol);
838: PetscViewerASCIIPrintf(viewer, " tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol);
839: PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT "\n", linesearch->max_its);
840: if (linesearch->ops->precheck) {
841: if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
842: PetscViewerASCIIPrintf(viewer, " using precheck step to speed up Picard convergence\n");
843: } else {
844: PetscViewerASCIIPrintf(viewer, " using user-defined precheck step\n");
845: }
846: }
847: if (linesearch->ops->postcheck) PetscViewerASCIIPrintf(viewer, " using user-defined postcheck step\n");
848: }
849: return 0;
850: }
852: /*@C
853: SNESLineSearchGetType - Gets the linesearch type
855: Logically Collective
857: Input Parameters:
858: . linesearch - linesearch context
860: Output Parameters:
861: - type - The type of line search, or NULL if not set
863: Level: intermediate
865: .seealso: `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
866: @*/
867: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
868: {
871: *type = ((PetscObject)linesearch)->type_name;
872: return 0;
873: }
875: /*@C
876: SNESLineSearchSetType - Sets the linesearch type
878: Logically Collective
880: Input Parameters:
881: + linesearch - linesearch context
882: - type - The type of line search to be used
884: Available Types:
885: + `SNESLINESEARCHBASIC` - (or equivalently `SNESLINESEARCHNONE`) Simple damping line search, defaults to using the full Newton step
886: . `SNESLINESEARCHBT` - Backtracking line search over the L2 norm of the function
887: . `SNESLINESEARCHL2` - Secant line search over the L2 norm of the function
888: . `SNESLINESEARCHCP` - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
889: . `SNESLINESEARCHNLEQERR` - Affine-covariant error-oriented linesearch
890: - `SNESLINESEARCHSHELL` - User provided `SNESLineSearch` implementation
892: Options Database Key:
893: . -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
895: Level: intermediate
897: .seealso: `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`
898: @*/
899: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
900: {
901: PetscBool match;
902: PetscErrorCode (*r)(SNESLineSearch);
907: PetscObjectTypeCompare((PetscObject)linesearch, type, &match);
908: if (match) return 0;
910: PetscFunctionListFind(SNESLineSearchList, type, &r);
912: /* Destroy the previous private linesearch context */
913: if (linesearch->ops->destroy) {
914: (*(linesearch)->ops->destroy)(linesearch);
915: linesearch->ops->destroy = NULL;
916: }
917: /* Reinitialize function pointers in SNESLineSearchOps structure */
918: linesearch->ops->apply = NULL;
919: linesearch->ops->view = NULL;
920: linesearch->ops->setfromoptions = NULL;
921: linesearch->ops->destroy = NULL;
923: PetscObjectChangeTypeName((PetscObject)linesearch, type);
924: (*r)(linesearch);
925: return 0;
926: }
928: /*@
929: SNESLineSearchSetSNES - Sets the `SNES` for the linesearch for function evaluation.
931: Input Parameters:
932: + linesearch - linesearch context
933: - snes - The snes instance
935: Level: developer
937: Note:
938: This happens automatically when the line search is obtained/created with
939: `SNESGetLineSearch()`. This routine is therefore mainly called within `SNES`
940: implementations.
942: Level: developer
944: .seealso: `SNESLineSearch`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
945: @*/
946: PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
947: {
950: linesearch->snes = snes;
951: return 0;
952: }
954: /*@
955: SNESLineSearchGetSNES - Gets the `SNES` instance associated with the line search.
956: Having an associated `SNES` is necessary because most line search implementations must be able to
957: evaluate the function using `SNESComputeFunction()` for the associated `SNES`. This routine
958: is used in the line search implementations when one must get this associated `SNES` instance.
960: Not Collective
962: Input Parameters:
963: . linesearch - linesearch context
965: Output Parameters:
966: . snes - The snes instance
968: Level: developer
970: .seealso: `SNESLineSearch`, `SNESType`, `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
971: @*/
972: PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
973: {
976: *snes = linesearch->snes;
977: return 0;
978: }
980: /*@
981: SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.
983: Not Collective
985: Input Parameters:
986: . linesearch - linesearch context
988: Output Parameters:
989: . lambda - The last steplength computed during `SNESLineSearchApply()`
991: Level: advanced
993: Note:
994: This is useful in methods where the solver is ill-scaled and
995: requires some adaptive notion of the difference in scale between the
996: solution and the function. For instance, `SNESQN` may be scaled by the
997: line search lambda using the argument -snes_qn_scaling ls.
999: .seealso: `SNESLineSearch`, `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1000: @*/
1001: PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda)
1002: {
1005: *lambda = linesearch->lambda;
1006: return 0;
1007: }
1009: /*@
1010: SNESLineSearchSetLambda - Sets the linesearch steplength
1012: Input Parameters:
1013: + linesearch - linesearch context
1014: - lambda - The last steplength.
1016: Note:
1017: This routine is typically used within implementations of `SNESLineSearchApply()`
1018: to set the final steplength. This routine (and `SNESLineSearchGetLambda()`) were
1019: added in order to facilitate Quasi-Newton methods that use the previous steplength
1020: as an inner scaling parameter.
1022: Level: advanced
1024: .seealso: `SNESLineSearch`, `SNESLineSearchGetLambda()`
1025: @*/
1026: PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1027: {
1029: linesearch->lambda = lambda;
1030: return 0;
1031: }
1033: /*@
1034: SNESLineSearchGetTolerances - Gets the tolerances for the linesearch. These include
1035: tolerances for the relative and absolute change in the function norm, the change
1036: in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1037: and the maximum number of iterations the line search procedure may take.
1039: Not Collective
1041: Input Parameter:
1042: . linesearch - linesearch context
1044: Output Parameters:
1045: + steptol - The minimum steplength
1046: . maxstep - The maximum steplength
1047: . rtol - The relative tolerance for iterative line searches
1048: . atol - The absolute tolerance for iterative line searches
1049: . ltol - The change in lambda tolerance for iterative line searches
1050: - max_it - The maximum number of iterations of the line search
1052: Level: intermediate
1054: Note:
1055: Different line searches may implement these parameters slightly differently as
1056: the type requires.
1058: .seealso: `SNESLineSearch`, `SNESLineSearchSetTolerances()`
1059: @*/
1060: PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *steptol, PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1061: {
1063: if (steptol) {
1065: *steptol = linesearch->steptol;
1066: }
1067: if (maxstep) {
1069: *maxstep = linesearch->maxstep;
1070: }
1071: if (rtol) {
1073: *rtol = linesearch->rtol;
1074: }
1075: if (atol) {
1077: *atol = linesearch->atol;
1078: }
1079: if (ltol) {
1081: *ltol = linesearch->ltol;
1082: }
1083: if (max_its) {
1085: *max_its = linesearch->max_its;
1086: }
1087: return 0;
1088: }
1090: /*@
1091: SNESLineSearchSetTolerances - Gets the tolerances for the linesearch. These include
1092: tolerances for the relative and absolute change in the function norm, the change
1093: in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1094: and the maximum number of iterations the line search procedure may take.
1096: Collective
1098: Input Parameters:
1099: + linesearch - linesearch context
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_it - The maximum number of iterations of the line search
1107: Note:
1108: The user may choose to not set any of the tolerances using `PETSC_DEFAULT` in
1109: place of an argument.
1111: Level: intermediate
1113: .seealso: `SNESLineSearch`, `SNESLineSearchGetTolerances()`
1114: @*/
1115: PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal steptol, PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
1116: {
1125: if (steptol != PETSC_DEFAULT) {
1127: linesearch->steptol = steptol;
1128: }
1130: if (maxstep != PETSC_DEFAULT) {
1132: linesearch->maxstep = maxstep;
1133: }
1135: if (rtol != PETSC_DEFAULT) {
1137: linesearch->rtol = rtol;
1138: }
1140: if (atol != PETSC_DEFAULT) {
1142: linesearch->atol = atol;
1143: }
1145: if (ltol != PETSC_DEFAULT) {
1147: linesearch->ltol = ltol;
1148: }
1150: if (max_its != PETSC_DEFAULT) {
1152: linesearch->max_its = max_its;
1153: }
1154: return 0;
1155: }
1157: /*@
1158: SNESLineSearchGetDamping - Gets the line search damping parameter.
1160: Input Parameters:
1161: . linesearch - linesearch context
1163: Output Parameters:
1164: . damping - The damping parameter
1166: Level: advanced
1168: .seealso: `SNESLineSearchGetStepTolerance()`, `SNESQN`
1169: @*/
1171: PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping)
1172: {
1175: *damping = linesearch->damping;
1176: return 0;
1177: }
1179: /*@
1180: SNESLineSearchSetDamping - Sets the line search damping parameter.
1182: Input Parameters:
1183: + linesearch - linesearch context
1184: - damping - The damping parameter
1186: Options Database Key:
1187: . -snes_linesearch_damping <damping> - the damping value
1189: Level: intermediate
1191: Note:
1192: The `SNESLINESEARCHNONE` line search merely takes the update step scaled by the damping parameter.
1193: The use of the damping parameter in the l2 and cp line searches is much more subtle;
1194: it is used as a starting point in calculating the secant step. However, the eventual
1195: step may be of greater length than the damping parameter. In the bt line search it is
1196: used as the maximum possible step length, as the bt line search only backtracks.
1198: .seealso: `SNESLineSearch`, `SNESLineSearchGetDamping()`
1199: @*/
1200: PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping)
1201: {
1203: linesearch->damping = damping;
1204: return 0;
1205: }
1207: /*@
1208: SNESLineSearchGetOrder - Gets the line search approximation order.
1210: Input Parameter:
1211: . linesearch - linesearch context
1213: Output Parameter:
1214: . order - The order
1216: Possible Values for order:
1217: + 1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1218: . 2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1219: - 3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order
1221: Level: intermediate
1223: .seealso: `SNESLineSearch`, `SNESLineSearchSetOrder()`
1224: @*/
1226: PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order)
1227: {
1230: *order = linesearch->order;
1231: return 0;
1232: }
1234: /*@
1235: SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search
1237: Input Parameters:
1238: + linesearch - linesearch context
1239: - order - The damping parameter
1241: Level: intermediate
1243: Possible Values for order:
1244: + 1 or `SNES_LINESEARCH_ORDER_LINEAR` - linear order
1245: . 2 or `SNES_LINESEARCH_ORDER_QUADRATIC` - quadratic order
1246: - 3 or `SNES_LINESEARCH_ORDER_CUBIC` - cubic order
1248: Notes:
1249: Variable orders are supported by the following line searches:
1250: + bt - cubic and quadratic
1251: - cp - linear and quadratic
1253: .seealso: `SNESLineSearch`, `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1254: @*/
1255: PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order)
1256: {
1258: linesearch->order = order;
1259: return 0;
1260: }
1262: /*@
1263: SNESLineSearchGetNorms - Gets the norms for for X, Y, and F.
1265: Not Collective
1267: Input Parameter:
1268: . linesearch - linesearch context
1270: Output Parameters:
1271: + xnorm - The norm of the current solution
1272: . fnorm - The norm of the current function
1273: - ynorm - The norm of the current update
1275: Level: developer
1277: .seealso: `SNESLineSearch`, `SNESLineSearchSetNorms()` `SNESLineSearchGetVecs()`
1278: @*/
1279: PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm)
1280: {
1282: if (xnorm) *xnorm = linesearch->xnorm;
1283: if (fnorm) *fnorm = linesearch->fnorm;
1284: if (ynorm) *ynorm = linesearch->ynorm;
1285: return 0;
1286: }
1288: /*@
1289: SNESLineSearchSetNorms - Gets the computed norms for for X, Y, and F.
1291: Collective
1293: Input Parameters:
1294: + linesearch - linesearch context
1295: . xnorm - The norm of the current solution
1296: . fnorm - The norm of the current function
1297: - ynorm - The norm of the current update
1299: Level: developer
1301: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1302: @*/
1303: PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1304: {
1306: linesearch->xnorm = xnorm;
1307: linesearch->fnorm = fnorm;
1308: linesearch->ynorm = ynorm;
1309: return 0;
1310: }
1312: /*@
1313: SNESLineSearchComputeNorms - Computes the norms of X, F, and Y.
1315: Input Parameters:
1316: . linesearch - linesearch context
1318: Options Database Keys:
1319: . -snes_linesearch_norms - turn norm computation on or off
1321: Level: intermediate
1323: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1324: @*/
1325: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1326: {
1327: SNES snes;
1329: if (linesearch->norms) {
1330: if (linesearch->ops->vinorm) {
1331: SNESLineSearchGetSNES(linesearch, &snes);
1332: VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1333: VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1334: (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
1335: } else {
1336: VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm);
1337: VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1338: VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1339: VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm);
1340: VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1341: VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1342: }
1343: }
1344: return 0;
1345: }
1347: /*@
1348: SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.
1350: Input Parameters:
1351: + linesearch - linesearch context
1352: - flg - indicates whether or not to compute norms
1354: Options Database Keys:
1355: . -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic (none) linesearch
1357: Note:
1358: This is most relevant to the `SNESLINESEARCHBASIC` (or equivalently `SNESLINESEARCHNONE`) line search type since most line searches have a stopping criteria involving the norm.
1360: Level: intermediate
1362: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1363: @*/
1364: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1365: {
1366: linesearch->norms = flg;
1367: return 0;
1368: }
1370: /*@
1371: SNESLineSearchGetVecs - Gets the vectors from the `SNESLineSearch` context
1373: Not Collective on but the vectors are parallel
1375: Input Parameter:
1376: . linesearch - linesearch context
1378: Output Parameters:
1379: + X - Solution vector
1380: . F - Function vector
1381: . Y - Search direction vector
1382: . W - Solution work vector
1383: - G - Function work vector
1385: Notes:
1386: At the beginning of a line search application, X should contain a
1387: solution and the vector F the function computed at X. At the end of the
1388: line search application, X should contain the new solution, and F the
1389: function evaluated at the new solution.
1391: These vectors are owned by the `SNESLineSearch` and should not be destroyed by the caller
1393: Level: advanced
1395: .seealso: `SNESLineSearch`, `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1396: @*/
1397: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G)
1398: {
1400: if (X) {
1402: *X = linesearch->vec_sol;
1403: }
1404: if (F) {
1406: *F = linesearch->vec_func;
1407: }
1408: if (Y) {
1410: *Y = linesearch->vec_update;
1411: }
1412: if (W) {
1414: *W = linesearch->vec_sol_new;
1415: }
1416: if (G) {
1418: *G = linesearch->vec_func_new;
1419: }
1420: return 0;
1421: }
1423: /*@
1424: SNESLineSearchSetVecs - Sets the vectors on the `SNESLineSearch` context
1426: Logically Collective
1428: Input Parameters:
1429: + linesearch - linesearch context
1430: . X - Solution vector
1431: . F - Function vector
1432: . Y - Search direction vector
1433: . W - Solution work vector
1434: - G - Function work vector
1436: Level: advanced
1438: .seealso: `SNESLineSearch`, `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1439: @*/
1440: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G)
1441: {
1443: if (X) {
1445: linesearch->vec_sol = X;
1446: }
1447: if (F) {
1449: linesearch->vec_func = F;
1450: }
1451: if (Y) {
1453: linesearch->vec_update = Y;
1454: }
1455: if (W) {
1457: linesearch->vec_sol_new = W;
1458: }
1459: if (G) {
1461: linesearch->vec_func_new = G;
1462: }
1463: return 0;
1464: }
1466: /*@C
1467: SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1468: `SNESLineSearch` options in the database.
1470: Logically Collective
1472: Input Parameters:
1473: + linesearch - the `SNESLineSearch` context
1474: - prefix - the prefix to prepend to all option names
1476: Note:
1477: A hyphen (-) must NOT be given at the beginning of the prefix name.
1478: The first character of all runtime options is AUTOMATICALLY the hyphen.
1480: Level: advanced
1482: .seealso: `SNESLineSearch()`, `SNESLineSearchSetFromOptions()`, `SNESGetOptionsPrefix()`
1483: @*/
1484: PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[])
1485: {
1487: PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix);
1488: return 0;
1489: }
1491: /*@C
1492: SNESLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1493: SNESLineSearch options in the database.
1495: Not Collective
1497: Input Parameter:
1498: . linesearch - the `SNESLineSearch` context
1500: Output Parameter:
1501: . prefix - pointer to the prefix string used
1503: Fortran Note:
1504: On the fortran side, the user should pass in a string 'prefix' of
1505: sufficient length to hold the prefix.
1507: Level: advanced
1509: .seealso: `SNESLineSearch`, `SNESAppendOptionsPrefix()`
1510: @*/
1511: PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[])
1512: {
1514: PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix);
1515: return 0;
1516: }
1518: /*@C
1519: SNESLineSearchSetWorkVecs - Sets work vectors for the line search.
1521: Input Parameters:
1522: + linesearch - the `SNESLineSearch` context
1523: - nwork - the number of work vectors
1525: Level: developer
1527: .seealso: `SNESLineSearch`, `SNESSetWorkVecs()`
1528: @*/
1529: PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1530: {
1531: if (linesearch->vec_sol) {
1532: VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
1533: } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1534: return 0;
1535: }
1537: /*@
1538: SNESLineSearchGetReason - Gets the success/failure status of the last line search application
1540: Input Parameters:
1541: . linesearch - linesearch context
1543: Output Parameters:
1544: . result - The success or failure status
1546: Note:
1547: This is typically called after `SNESLineSearchApply()` in order to determine if the line-search failed
1548: (and set the SNES convergence accordingly).
1550: Level: developer
1552: .seealso: `SNESLineSearch`, `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1553: @*/
1554: PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1555: {
1558: *result = linesearch->result;
1559: return 0;
1560: }
1562: /*@
1563: SNESLineSearchSetReason - Sets the success/failure status of the last line search application
1565: Input Parameters:
1566: + linesearch - linesearch context
1567: - result - The success or failure status
1569: Note:
1570: This is typically called in a `SNESLineSearchApply()` or a `SNESLINESEARCHSHELL` implementation to set
1571: the success or failure of the line search method.
1573: Level: developer
1575: .seealso: `SNESLineSearch`, `SNESLineSearchReason`, `SNESLineSearchGetSResult()`
1576: @*/
1577: PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1578: {
1580: linesearch->result = result;
1581: return 0;
1582: }
1584: /*@C
1585: SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.
1587: Logically Collective
1589: Input Parameters:
1590: + snes - nonlinear context obtained from `SNESCreate()`
1591: . projectfunc - function for projecting the function to the bounds
1592: - normfunc - function for computing the norm of an active set
1594: Calling sequence of projectfunc:
1595: .vb
1596: projectfunc (SNES snes, Vec X)
1597: .ve
1599: Input parameters for projectfunc:
1600: + snes - nonlinear context
1601: - X - current solution
1603: Output parameter for projectfunc:
1604: . X - Projected solution
1606: Calling sequence of normfunc:
1607: .vb
1608: projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
1609: .ve
1611: Input parameters for normfunc:
1612: + snes - nonlinear context
1613: . X - current solution
1614: - F - current residual
1616: Output parameter for normfunc:
1617: . fnorm - VI-specific norm of the function
1619: Note:
1620: The VI solvers require projection of the solution to the feasible set. projectfunc should implement this.
1622: The VI solvers require special evaluation of the function norm such that the norm is only calculated
1623: on the inactive set. This should be implemented by normfunc.
1625: Level: advanced
1627: .seealso: `SNESLineSearch`, `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`
1628: @*/
1629: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
1630: {
1632: if (projectfunc) linesearch->ops->viproject = projectfunc;
1633: if (normfunc) linesearch->ops->vinorm = normfunc;
1634: return 0;
1635: }
1637: /*@C
1638: SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.
1640: Not Collective
1642: Input Parameter:
1643: . linesearch - the line search context, obtain with `SNESGetLineSearch()`
1645: Output Parameters:
1646: + projectfunc - function for projecting the function to the bounds
1647: - normfunc - function for computing the norm of an active set
1649: Level: advanced
1651: .seealso: `SNESLineSearch`, `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`
1652: @*/
1653: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
1654: {
1655: if (projectfunc) *projectfunc = linesearch->ops->viproject;
1656: if (normfunc) *normfunc = linesearch->ops->vinorm;
1657: return 0;
1658: }
1660: /*@C
1661: SNESLineSearchRegister - register a line search method
1663: Level: advanced
1665: .seealso: `SNESLineSearch`, `SNESLineSearchType`, `SNESLineSearchSetType()`
1666: @*/
1667: PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch))
1668: {
1669: SNESInitializePackage();
1670: PetscFunctionListAdd(&SNESLineSearchList, sname, function);
1671: return 0;
1672: }