xref: /petsc/src/snes/linesearch/interface/linesearch.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1 #include <petsc/private/linesearchimpl.h> /*I "petscsnes.h" I*/
2 
3 PetscBool         SNESLineSearchRegisterAllCalled = PETSC_FALSE;
4 PetscFunctionList SNESLineSearchList              = NULL;
5 
6 PetscClassId  SNESLINESEARCH_CLASSID;
7 PetscLogEvent SNESLINESEARCH_Apply;
8 
9 /*@
10    SNESLineSearchMonitorCancel - Clears all the monitor functions for a SNESLineSearch object.
11 
12    Logically Collective on SNESLineSearch
13 
14    Input Parameters:
15 .  ls - the SNESLineSearch context
16 
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
21 
22    Notes:
23    There is no way to clear one specific monitor from a SNESLineSearch object.
24 
25    This does not clear the monitor set with SNESLineSearchSetDefaultMonitor() use SNESLineSearchSetDefaultMonitor(ls,NULL) to cancel
26    that one.
27 
28    Level: intermediate
29 
30 .seealso: `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorSet()`
31 @*/
32 PetscErrorCode SNESLineSearchMonitorCancel(SNESLineSearch ls) {
33   PetscInt i;
34 
35   PetscFunctionBegin;
36   PetscValidHeaderSpecific(ls, SNESLINESEARCH_CLASSID, 1);
37   for (i = 0; i < ls->numbermonitors; i++) {
38     if (ls->monitordestroy[i]) { PetscCall((*ls->monitordestroy[i])(&ls->monitorcontext[i])); }
39   }
40   ls->numbermonitors = 0;
41   PetscFunctionReturn(0);
42 }
43 
44 /*@
45    SNESLineSearchMonitor - runs the user provided monitor routines, if they exist
46 
47    Collective on SNES
48 
49    Input Parameters:
50 .  ls - the linesearch object
51 
52    Notes:
53    This routine is called by the SNES implementations.
54    It does not typically need to be called by the user.
55 
56    Level: developer
57 
58 .seealso: `SNESGetLineSearch()`, `SNESLineSearchMonitorSet()`
59 @*/
60 PetscErrorCode SNESLineSearchMonitor(SNESLineSearch ls) {
61   PetscInt i, n = ls->numbermonitors;
62 
63   PetscFunctionBegin;
64   for (i = 0; i < n; i++) { PetscCall((*ls->monitorftns[i])(ls, ls->monitorcontext[i])); }
65   PetscFunctionReturn(0);
66 }
67 
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.
72 
73    Logically Collective on SNESLineSearch
74 
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)
82 
83    Notes:
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.
87 
88    Fortran Notes:
89     Only a single monitor function can be set for each SNESLineSearch object
90 
91    Level: intermediate
92 
93 .seealso: `SNESGetLineSearch()`, `SNESLineSearchMonitorDefault()`, `SNESLineSearchMonitorCancel()`
94 @*/
95 PetscErrorCode SNESLineSearchMonitorSet(SNESLineSearch ls, PetscErrorCode (*f)(SNESLineSearch, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **)) {
96   PetscInt  i;
97   PetscBool identical;
98 
99   PetscFunctionBegin;
100   PetscValidHeaderSpecific(ls, SNESLINESEARCH_CLASSID, 1);
101   for (i = 0; i < ls->numbermonitors; i++) {
102     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))ls->monitorftns[i], ls->monitorcontext[i], ls->monitordestroy[i], &identical));
103     if (identical) PetscFunctionReturn(0);
104   }
105   PetscCheck(ls->numbermonitors < MAXSNESLSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
106   ls->monitorftns[ls->numbermonitors]      = f;
107   ls->monitordestroy[ls->numbermonitors]   = monitordestroy;
108   ls->monitorcontext[ls->numbermonitors++] = (void *)mctx;
109   PetscFunctionReturn(0);
110 }
111 
112 /*@C
113    SNESLineSearchMonitorSolutionUpdate - Monitors each update a new function value the linesearch tries
114 
115    Collective on SNESLineSearch
116 
117    Input Parameters:
118 +  ls - the SNES linesearch object
119 -  vf - the context for the monitor, in this case it is an ASCII PetscViewer and format
120 
121    Level: intermediate
122 
123 .seealso: `SNESGetLineSearch()`, `SNESMonitorSet()`, `SNESMonitorSolution()`
124 @*/
125 PetscErrorCode SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls, PetscViewerAndFormat *vf) {
126   PetscViewer viewer = vf->viewer;
127   Vec         Y, W, G;
128 
129   PetscFunctionBegin;
130   PetscCall(SNESLineSearchGetVecs(ls, NULL, NULL, &Y, &W, &G));
131   PetscCall(PetscViewerPushFormat(viewer, vf->format));
132   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted update to solution \n"));
133   PetscCall(VecView(Y, viewer));
134   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted new solution \n"));
135   PetscCall(VecView(W, viewer));
136   PetscCall(PetscViewerASCIIPrintf(viewer, "LineSearch attempted updated function value\n"));
137   PetscCall(VecView(G, viewer));
138   PetscCall(PetscViewerPopFormat(viewer));
139   PetscFunctionReturn(0);
140 }
141 
142 /*@
143    SNESLineSearchCreate - Creates the line search context.
144 
145    Logically Collective on Comm
146 
147    Input Parameters:
148 .  comm - MPI communicator for the line search (typically from the associated SNES context).
149 
150    Output Parameters:
151 .  outlinesearch - the new linesearch context
152 
153    Level: developer
154 
155    Notes:
156    The preferred calling sequence for users is to use SNESGetLineSearch() to acquire the SNESLineSearch instance
157    already associated with the SNES.  This function is for developer use.
158 
159 .seealso: `LineSearchDestroy()`, `SNESGetLineSearch()`
160 @*/
161 
162 PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch) {
163   SNESLineSearch linesearch;
164 
165   PetscFunctionBegin;
166   PetscValidPointer(outlinesearch, 2);
167   PetscCall(SNESInitializePackage());
168   *outlinesearch = NULL;
169 
170   PetscCall(PetscHeaderCreate(linesearch, SNESLINESEARCH_CLASSID, "SNESLineSearch", "Linesearch", "SNESLineSearch", comm, SNESLineSearchDestroy, SNESLineSearchView));
171 
172   linesearch->vec_sol_new  = NULL;
173   linesearch->vec_func_new = NULL;
174   linesearch->vec_sol      = NULL;
175   linesearch->vec_func     = NULL;
176   linesearch->vec_update   = NULL;
177 
178   linesearch->lambda       = 1.0;
179   linesearch->fnorm        = 1.0;
180   linesearch->ynorm        = 1.0;
181   linesearch->xnorm        = 1.0;
182   linesearch->result       = SNES_LINESEARCH_SUCCEEDED;
183   linesearch->norms        = PETSC_TRUE;
184   linesearch->keeplambda   = PETSC_FALSE;
185   linesearch->damping      = 1.0;
186   linesearch->maxstep      = 1e8;
187   linesearch->steptol      = 1e-12;
188   linesearch->rtol         = 1e-8;
189   linesearch->atol         = 1e-15;
190   linesearch->ltol         = 1e-8;
191   linesearch->precheckctx  = NULL;
192   linesearch->postcheckctx = NULL;
193   linesearch->max_its      = 1;
194   linesearch->setupcalled  = PETSC_FALSE;
195   linesearch->monitor      = NULL;
196   *outlinesearch           = linesearch;
197   PetscFunctionReturn(0);
198 }
199 
200 /*@
201    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
202    any required vectors.
203 
204    Collective on SNESLineSearch
205 
206    Input Parameters:
207 .  linesearch - The LineSearch instance.
208 
209    Notes:
210    For most cases, this needn't be called by users or outside of SNESLineSearchApply().
211    The only current case where this is called outside of this is for the VI
212    solvers, which modify the solution and work vectors before the first call
213    of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be
214    allocated upfront.
215 
216    Level: advanced
217 
218 .seealso: `SNESGetLineSearch()`, `SNESLineSearchReset()`
219 @*/
220 
221 PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch) {
222   PetscFunctionBegin;
223   if (!((PetscObject)linesearch)->type_name) { PetscCall(SNESLineSearchSetType(linesearch, SNESLINESEARCHBASIC)); }
224   if (!linesearch->setupcalled) {
225     if (!linesearch->vec_sol_new) { PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new)); }
226     if (!linesearch->vec_func_new) { PetscCall(VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new)); }
227     if (linesearch->ops->setup) PetscUseTypeMethod(linesearch, setup);
228     if (!linesearch->ops->snesfunc) PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunction));
229     linesearch->lambda      = linesearch->damping;
230     linesearch->setupcalled = PETSC_TRUE;
231   }
232   PetscFunctionReturn(0);
233 }
234 
235 /*@
236    SNESLineSearchReset - Undoes the SNESLineSearchSetUp() and deletes any Vecs or Mats allocated by the line search.
237 
238    Collective on SNESLineSearch
239 
240    Input Parameters:
241 .  linesearch - The LineSearch instance.
242 
243    Notes:
244     Usually only called by SNESReset()
245 
246    Level: developer
247 
248 .seealso: `SNESGetLineSearch()`, `SNESLineSearchSetUp()`
249 @*/
250 
251 PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch) {
252   PetscFunctionBegin;
253   if (linesearch->ops->reset) PetscUseTypeMethod(linesearch, reset);
254 
255   PetscCall(VecDestroy(&linesearch->vec_sol_new));
256   PetscCall(VecDestroy(&linesearch->vec_func_new));
257 
258   PetscCall(VecDestroyVecs(linesearch->nwork, &linesearch->work));
259 
260   linesearch->nwork       = 0;
261   linesearch->setupcalled = PETSC_FALSE;
262   PetscFunctionReturn(0);
263 }
264 
265 /*@C
266    SNESLineSearchSetFunction - Sets the function evaluation used by the SNES line search
267 
268    Input Parameters:
269 .  linesearch - the SNESLineSearch context
270 +  func       - function evaluation routine
271 
272    Level: developer
273 
274    Notes:
275     This is used internally by PETSc and not called by users
276 
277 .seealso: `SNESGetLineSearch()`, `SNESSetFunction()`
278 @*/
279 PetscErrorCode SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES, Vec, Vec)) {
280   PetscFunctionBegin;
281   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
282   linesearch->ops->snesfunc = func;
283   PetscFunctionReturn(0);
284 }
285 
286 /*@C
287    SNESLineSearchSetPreCheck - Sets a user function that is called after the initial search direction has been computed but
288          before the line search routine has been applied. Allows the user to adjust the result of (usually a linear solve) that
289          determined the search direction.
290 
291    Logically Collective on SNESLineSearch
292 
293    Input Parameters:
294 +  linesearch - the SNESLineSearch context
295 .  func - [optional] function evaluation routine, see SNESLineSearchPreCheck() for the calling sequence
296 -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
297 
298    Level: intermediate
299 
300    Notes:
301    Use `SNESLineSearchSetPostCheck()` to change the step after the line search.
302    search is complete.
303 
304    Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
305 
306 .seealso: `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`,
307           `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()
308 
309 @*/
310 PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void *ctx) {
311   PetscFunctionBegin;
312   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
313   if (func) linesearch->ops->precheck = func;
314   if (ctx) linesearch->precheckctx = ctx;
315   PetscFunctionReturn(0);
316 }
317 
318 /*@C
319    SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.
320 
321    Input Parameter:
322 .  linesearch - the SNESLineSearch context
323 
324    Output Parameters:
325 +  func       - [optional] function evaluation routine, see SNESLineSearchPreCheck() for calling sequence
326 -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
327 
328    Level: intermediate
329 
330 .seealso: `SNESGetLineSearch()`, `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
331 @*/
332 PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, PetscBool *, void *), void **ctx) {
333   PetscFunctionBegin;
334   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
335   if (func) *func = linesearch->ops->precheck;
336   if (ctx) *ctx = linesearch->precheckctx;
337   PetscFunctionReturn(0);
338 }
339 
340 /*@C
341    SNESLineSearchSetPostCheck - Sets a user function that is called after the line search has been applied to determine the step
342        direction and length. Allows the user a chance to change or override the decision of the line search routine
343 
344    Logically Collective on SNESLineSearch
345 
346    Input Parameters:
347 +  linesearch - the SNESLineSearch context
348 .  func - [optional] function evaluation routine, see SNESLineSearchPostCheck()  for the calling sequence
349 -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
350 
351    Level: intermediate
352 
353    Notes:
354    Use `SNESLineSearchSetPreCheck()` to change the step before the line search.
355    search is complete.
356 
357    Use `SNESVISetVariableBounds()` and `SNESVISetComputeVariableBounds()` to cause `SNES` to automatically control the ranges of variables allowed.
358 
359 .seealso: `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchGetPostCheck()`,
360           `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()`, `SNESSetFunctionDomainError()`, `SNESSetJacobianDomainError()
361 @*/
362 PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void *ctx) {
363   PetscFunctionBegin;
364   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
365   if (func) linesearch->ops->postcheck = func;
366   if (ctx) linesearch->postcheckctx = ctx;
367   PetscFunctionReturn(0);
368 }
369 
370 /*@C
371    SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.
372 
373    Input Parameter:
374 .  linesearch - the SNESLineSearch context
375 
376    Output Parameters:
377 +  func - [optional] function evaluation routine, see for the calling sequence SNESLineSearchPostCheck()
378 -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
379 
380    Level: intermediate
381 
382 .seealso: `SNESGetLineSearch()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`
383 @*/
384 PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void **ctx) {
385   PetscFunctionBegin;
386   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
387   if (func) *func = linesearch->ops->postcheck;
388   if (ctx) *ctx = linesearch->postcheckctx;
389   PetscFunctionReturn(0);
390 }
391 
392 /*@
393    SNESLineSearchPreCheck - Prepares the line search for being applied.
394 
395    Logically Collective on SNESLineSearch
396 
397    Input Parameters:
398 +  linesearch - The linesearch instance.
399 .  X - The current solution
400 -  Y - The step direction
401 
402    Output Parameters:
403 .  changed - Indicator that the precheck routine has changed anything
404 
405    Level: advanced
406 
407 .seealso: `SNESGetLineSearch()`, `SNESLineSearchPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESLineSearchSetPostCheck()`,
408           `SNESLineSearchGetPostCheck()``
409 @*/
410 PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed) {
411   PetscFunctionBegin;
412   *changed = PETSC_FALSE;
413   if (linesearch->ops->precheck) {
414     PetscUseTypeMethod(linesearch, precheck, X, Y, changed, linesearch->precheckctx);
415     PetscValidLogicalCollectiveBool(linesearch, *changed, 4);
416   }
417   PetscFunctionReturn(0);
418 }
419 
420 /*@
421    SNESLineSearchPostCheck - Hook to modify step direction or updated solution after a successful linesearch
422 
423    Logically Collective on SNESLineSearch
424 
425    Input Parameters:
426 +  linesearch - The linesearch context
427 .  X - The last solution
428 .  Y - The step direction
429 -  W - The updated solution, W = X + lambda*Y for some lambda
430 
431    Output Parameters:
432 +  changed_Y - Indicator if the direction Y has been changed.
433 -  changed_W - Indicator if the new candidate solution W has been changed.
434 
435    Level: developer
436 
437 .seealso: `SNESGetLineSearch()`, `SNESLineSearchPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPrecheck()`, `SNESLineSearchGetPrecheck()`
438 @*/
439 PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch, Vec X, Vec Y, Vec W, PetscBool *changed_Y, PetscBool *changed_W) {
440   PetscFunctionBegin;
441   *changed_Y = PETSC_FALSE;
442   *changed_W = PETSC_FALSE;
443   if (linesearch->ops->postcheck) {
444     PetscUseTypeMethod(linesearch, postcheck, X, Y, W, changed_Y, changed_W, linesearch->postcheckctx);
445     PetscValidLogicalCollectiveBool(linesearch, *changed_Y, 5);
446     PetscValidLogicalCollectiveBool(linesearch, *changed_W, 6);
447   }
448   PetscFunctionReturn(0);
449 }
450 
451 /*@C
452    SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration
453 
454    Logically Collective on SNESLineSearch
455 
456    Input Parameters:
457 +  linesearch - linesearch context
458 .  X - base state for this step
459 -  ctx - context for this function
460 
461    Input/Output Parameter:
462 .  Y - correction, possibly modified
463 
464    Output Parameter:
465 .  changed - flag indicating that Y was modified
466 
467    Options Database Key:
468 +  -snes_linesearch_precheck_picard - activate this routine
469 -  -snes_linesearch_precheck_picard_angle - angle
470 
471    Level: advanced
472 
473    Notes:
474    This function should be passed to SNESLineSearchSetPreCheck()
475 
476    The justification for this method involves the linear convergence of a Picard iteration
477    so the Picard linearization should be provided in place of the "Jacobian". This correction
478    is generally not useful when using a Newton linearization.
479 
480    Reference:
481    Hindmarsh and Payne (1996) Time step limits for stable solutions of the ice sheet equation, Annals of Glaciology.
482 
483 .seealso: `SNESGetLineSearch()`, `SNESLineSearchSetPreCheck()`
484 @*/
485 PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch, Vec X, Vec Y, PetscBool *changed, void *ctx) {
486   PetscReal   angle = *(PetscReal *)linesearch->precheckctx;
487   Vec         Ylast;
488   PetscScalar dot;
489   PetscInt    iter;
490   PetscReal   ynorm, ylastnorm, theta, angle_radians;
491   SNES        snes;
492 
493   PetscFunctionBegin;
494   PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
495   PetscCall(PetscObjectQuery((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject *)&Ylast));
496   if (!Ylast) {
497     PetscCall(VecDuplicate(Y, &Ylast));
498     PetscCall(PetscObjectCompose((PetscObject)snes, "SNESLineSearchPreCheckPicard_Ylast", (PetscObject)Ylast));
499     PetscCall(PetscObjectDereference((PetscObject)Ylast));
500   }
501   PetscCall(SNESGetIterationNumber(snes, &iter));
502   if (iter < 2) {
503     PetscCall(VecCopy(Y, Ylast));
504     *changed = PETSC_FALSE;
505     PetscFunctionReturn(0);
506   }
507 
508   PetscCall(VecDot(Y, Ylast, &dot));
509   PetscCall(VecNorm(Y, NORM_2, &ynorm));
510   PetscCall(VecNorm(Ylast, NORM_2, &ylastnorm));
511   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
512   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm), -1.0, 1.0));
513   angle_radians = angle * PETSC_PI / 180.;
514   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
515     /* Modify the step Y */
516     PetscReal alpha, ydiffnorm;
517     PetscCall(VecAXPY(Ylast, -1.0, Y));
518     PetscCall(VecNorm(Ylast, NORM_2, &ydiffnorm));
519     alpha = (ydiffnorm > .001 * ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
520     PetscCall(VecCopy(Y, Ylast));
521     PetscCall(VecScale(Y, alpha));
522     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));
523     *changed = PETSC_TRUE;
524   } else {
525     PetscCall(PetscInfo(snes, "Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n", (double)(theta * 180. / PETSC_PI), (double)angle));
526     PetscCall(VecCopy(Y, Ylast));
527     *changed = PETSC_FALSE;
528   }
529   PetscFunctionReturn(0);
530 }
531 
532 /*@
533    SNESLineSearchApply - Computes the line-search update.
534 
535    Collective on SNESLineSearch
536 
537    Input Parameters:
538 +  linesearch - The linesearch context
539 -  Y - The search direction
540 
541    Input/Output Parameters:
542 +  X - The current solution, on output the new solution
543 .  F - The current function, on output the new function
544 -  fnorm - The current norm, on output the new function norm
545 
546    Options Database Keys:
547 + -snes_linesearch_type - basic (or equivalently none), bt, l2, cp, nleqerr, shell
548 . -snes_linesearch_monitor [:filename] - Print progress of line searches
549 . -snes_linesearch_damping - The linesearch damping parameter, default is 1.0 (no damping)
550 . -snes_linesearch_norms   - Turn on/off the linesearch norms computation (SNESLineSearchSetComputeNorms())
551 . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
552 - -snes_linesearch_max_it - The number of iterations for iterative line searches
553 
554    Notes:
555    This is typically called from within a SNESSolve() implementation in order to
556    help with convergence of the nonlinear method.  Various SNES types use line searches
557    in different ways, but the overarching theme is that a line search is used to determine
558    an optimal damping parameter of a step at each iteration of the method.  Each
559    application of the line search may invoke SNESComputeFunction() several times, and
560    therefore may be fairly expensive.
561 
562    Level: Intermediate
563 
564 .seealso: `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchPreCheck()`, `SNESLineSearchPostCheck()`, `SNESSolve()`, `SNESComputeFunction()`, `SNESLineSearchSetComputeNorms()`,
565           `SNESLineSearchType`, `SNESLineSearchSetType()`
566 @*/
567 PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal *fnorm, Vec Y) {
568   PetscFunctionBegin;
569   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
570   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
571   PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
572   PetscValidHeaderSpecific(Y, VEC_CLASSID, 5);
573 
574   linesearch->result = SNES_LINESEARCH_SUCCEEDED;
575 
576   linesearch->vec_sol    = X;
577   linesearch->vec_update = Y;
578   linesearch->vec_func   = F;
579 
580   PetscCall(SNESLineSearchSetUp(linesearch));
581 
582   if (!linesearch->keeplambda) linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */
583 
584   if (fnorm) linesearch->fnorm = *fnorm;
585   else { PetscCall(VecNorm(F, NORM_2, &linesearch->fnorm)); }
586 
587   PetscCall(PetscLogEventBegin(SNESLINESEARCH_Apply, linesearch, X, F, Y));
588 
589   PetscUseTypeMethod(linesearch, apply);
590 
591   PetscCall(PetscLogEventEnd(SNESLINESEARCH_Apply, linesearch, X, F, Y));
592 
593   if (fnorm) *fnorm = linesearch->fnorm;
594   PetscFunctionReturn(0);
595 }
596 
597 /*@
598    SNESLineSearchDestroy - Destroys the line search instance.
599 
600    Collective on SNESLineSearch
601 
602    Input Parameters:
603 .  linesearch - The linesearch context
604 
605    Level: developer
606 
607 .seealso: `SNESGetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchReset()`, `SNESDestroy()`
608 @*/
609 PetscErrorCode SNESLineSearchDestroy(SNESLineSearch *linesearch) {
610   PetscFunctionBegin;
611   if (!*linesearch) PetscFunctionReturn(0);
612   PetscValidHeaderSpecific((*linesearch), SNESLINESEARCH_CLASSID, 1);
613   if (--((PetscObject)(*linesearch))->refct > 0) {
614     *linesearch = NULL;
615     PetscFunctionReturn(0);
616   }
617   PetscCall(PetscObjectSAWsViewOff((PetscObject)*linesearch));
618   PetscCall(SNESLineSearchReset(*linesearch));
619   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
620   PetscCall(PetscViewerDestroy(&(*linesearch)->monitor));
621   PetscCall(SNESLineSearchMonitorCancel((*linesearch)));
622   PetscCall(PetscHeaderDestroy(linesearch));
623   PetscFunctionReturn(0);
624 }
625 
626 /*@
627    SNESLineSearchSetDefaultMonitor - Turns on/off printing useful information and debugging output about the line search.
628 
629    Input Parameters:
630 +  linesearch - the linesearch object
631 -  viewer - an ASCII PetscViewer or NULL to turn off monitor
632 
633    Logically Collective on SNESLineSearch
634 
635    Options Database:
636 .   -snes_linesearch_monitor [:filename] - enables the monitor
637 
638    Level: intermediate
639 
640    Developer Note: This monitor is implemented differently than the other SNESLineSearchMonitors that are set with
641      SNESLineSearchMonitorSet() since it is called in many locations of the line search routines to display aspects of the
642      line search that are not visible to the other monitors.
643 
644 .seealso: `SNESGetLineSearch()`, `SNESLineSearchGetDefaultMonitor()`, `PetscViewer`, `SNESLineSearchSetMonitor()`
645 @*/
646 PetscErrorCode SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer) {
647   PetscFunctionBegin;
648   if (viewer) PetscCall(PetscObjectReference((PetscObject)viewer));
649   PetscCall(PetscViewerDestroy(&linesearch->monitor));
650   linesearch->monitor = viewer;
651   PetscFunctionReturn(0);
652 }
653 
654 /*@
655    SNESLineSearchGetDefaultMonitor - Gets the PetscViewer instance for the line search monitor.
656 
657    Input Parameter:
658 .  linesearch - linesearch context
659 
660    Output Parameter:
661 .  monitor - monitor context
662 
663    Logically Collective on SNES
664 
665    Options Database Keys:
666 .   -snes_linesearch_monitor - enables the monitor
667 
668    Level: intermediate
669 
670 .seealso: `SNESGetLineSearch()`, `SNESLineSearchSetDefaultMonitor()`, `PetscViewer`
671 @*/
672 PetscErrorCode SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor) {
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
675   *monitor = linesearch->monitor;
676   PetscFunctionReturn(0);
677 }
678 
679 /*@C
680    SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
681 
682    Collective on SNESLineSearch
683 
684    Input Parameters:
685 +  ls - LineSearch object you wish to monitor
686 .  name - the monitor type one is seeking
687 .  help - message indicating what monitoring is done
688 .  manual - manual page for the monitor
689 .  monitor - the monitor function
690 -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the SNESLineSearch or PetscViewer objects
691 
692    Level: developer
693 
694 .seealso: `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
695           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
696           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
697           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
698           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
699           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
700           `PetscOptionsFList()`, `PetscOptionsEList()`
701 @*/
702 PetscErrorCode SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNESLineSearch, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(SNESLineSearch, PetscViewerAndFormat *)) {
703   PetscViewer       viewer;
704   PetscViewerFormat format;
705   PetscBool         flg;
706 
707   PetscFunctionBegin;
708   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls), ((PetscObject)ls)->options, ((PetscObject)ls)->prefix, name, &viewer, &format, &flg));
709   if (flg) {
710     PetscViewerAndFormat *vf;
711     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
712     PetscCall(PetscObjectDereference((PetscObject)viewer));
713     if (monitorsetup) PetscCall((*monitorsetup)(ls, vf));
714     PetscCall(SNESLineSearchMonitorSet(ls, (PetscErrorCode(*)(SNESLineSearch, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
715   }
716   PetscFunctionReturn(0);
717 }
718 
719 /*@
720    SNESLineSearchSetFromOptions - Sets options for the line search
721 
722    Input Parameter:
723 .  linesearch - linesearch context
724 
725    Options Database Keys:
726 + -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
727 . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
728 . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch typem (SNESLineSearchSetComputeNorms())
729 . -snes_linesearch_minlambda - The minimum step length
730 . -snes_linesearch_maxstep - The maximum step size
731 . -snes_linesearch_rtol - Relative tolerance for iterative line searches
732 . -snes_linesearch_atol - Absolute tolerance for iterative line searches
733 . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
734 . -snes_linesearch_max_it - The number of iterations for iterative line searches
735 . -snes_linesearch_monitor [:filename] - Print progress of line searches
736 . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
737 . -snes_linesearch_damping - The linesearch damping parameter
738 . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
739 . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
740 - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method
741 
742    Logically Collective on SNESLineSearch
743 
744    Level: intermediate
745 
746 .seealso: `SNESLineSearchCreate()`, `SNESLineSearchSetOrder()`, `SNESLineSearchSetType()`, `SNESLineSearchSetTolerances()`, `SNESLineSearchSetDamping()`, `SNESLineSearchPreCheckPicard()`,
747           `SNESLineSearchType`, `SNESLineSearchSetComputeNorms()`
748 @*/
749 PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch) {
750   const char *deft = SNESLINESEARCHBASIC;
751   char        type[256];
752   PetscBool   flg, set;
753   PetscViewer viewer;
754 
755   PetscFunctionBegin;
756   PetscCall(SNESLineSearchRegisterAll());
757 
758   PetscObjectOptionsBegin((PetscObject)linesearch);
759   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
760   PetscCall(PetscOptionsFList("-snes_linesearch_type", "Linesearch type", "SNESLineSearchSetType", SNESLineSearchList, deft, type, 256, &flg));
761   if (flg) {
762     PetscCall(SNESLineSearchSetType(linesearch, type));
763   } else if (!((PetscObject)linesearch)->type_name) {
764     PetscCall(SNESLineSearchSetType(linesearch, deft));
765   }
766 
767   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch), ((PetscObject)linesearch)->options, ((PetscObject)linesearch)->prefix, "-snes_linesearch_monitor", &viewer, NULL, &set));
768   if (set) {
769     PetscCall(SNESLineSearchSetDefaultMonitor(linesearch, viewer));
770     PetscCall(PetscViewerDestroy(&viewer));
771   }
772   PetscCall(SNESLineSearchMonitorSetFromOptions(linesearch, "-snes_linesearch_monitor_solution_update", "View correction at each iteration", "SNESLineSearchMonitorSolutionUpdate", SNESLineSearchMonitorSolutionUpdate, NULL));
773 
774   /* tolerances */
775   PetscCall(PetscOptionsReal("-snes_linesearch_minlambda", "Minimum step length", "SNESLineSearchSetTolerances", linesearch->steptol, &linesearch->steptol, NULL));
776   PetscCall(PetscOptionsReal("-snes_linesearch_maxstep", "Maximum step size", "SNESLineSearchSetTolerances", linesearch->maxstep, &linesearch->maxstep, NULL));
777   PetscCall(PetscOptionsReal("-snes_linesearch_rtol", "Relative tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->rtol, &linesearch->rtol, NULL));
778   PetscCall(PetscOptionsReal("-snes_linesearch_atol", "Absolute tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->atol, &linesearch->atol, NULL));
779   PetscCall(PetscOptionsReal("-snes_linesearch_ltol", "Change in lambda tolerance for iterative line search", "SNESLineSearchSetTolerances", linesearch->ltol, &linesearch->ltol, NULL));
780   PetscCall(PetscOptionsInt("-snes_linesearch_max_it", "Maximum iterations for iterative line searches", "SNESLineSearchSetTolerances", linesearch->max_its, &linesearch->max_its, NULL));
781 
782   /* damping parameters */
783   PetscCall(PetscOptionsReal("-snes_linesearch_damping", "Line search damping and initial step guess", "SNESLineSearchSetDamping", linesearch->damping, &linesearch->damping, NULL));
784 
785   PetscCall(PetscOptionsBool("-snes_linesearch_keeplambda", "Use previous lambda as damping", "SNESLineSearchSetKeepLambda", linesearch->keeplambda, &linesearch->keeplambda, NULL));
786 
787   /* precheck */
788   PetscCall(PetscOptionsBool("-snes_linesearch_precheck_picard", "Use a correction that sometimes improves convergence of Picard iteration", "SNESLineSearchPreCheckPicard", flg, &flg, &set));
789   if (set) {
790     if (flg) {
791       linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */
792 
793       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));
794       PetscCall(SNESLineSearchSetPreCheck(linesearch, SNESLineSearchPreCheckPicard, &linesearch->precheck_picard_angle));
795     } else {
796       PetscCall(SNESLineSearchSetPreCheck(linesearch, NULL, NULL));
797     }
798   }
799   PetscCall(PetscOptionsInt("-snes_linesearch_order", "Order of approximation used in the line search", "SNESLineSearchSetOrder", linesearch->order, &linesearch->order, NULL));
800   PetscCall(PetscOptionsBool("-snes_linesearch_norms", "Compute final norms in line search", "SNESLineSearchSetComputeNorms", linesearch->norms, &linesearch->norms, NULL));
801 
802   PetscTryTypeMethod(linesearch, setfromoptions, PetscOptionsObject);
803 
804   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)linesearch, PetscOptionsObject));
805   PetscOptionsEnd();
806   PetscFunctionReturn(0);
807 }
808 
809 /*@
810    SNESLineSearchView - Prints useful information about the line search
811 
812    Input Parameters:
813 .  linesearch - linesearch context
814 
815    Logically Collective on SNESLineSearch
816 
817    Level: intermediate
818 
819 .seealso: `SNESLineSearchCreate()`
820 @*/
821 PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer) {
822   PetscBool iascii;
823 
824   PetscFunctionBegin;
825   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
826   if (!viewer) { PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch), &viewer)); }
827   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
828   PetscCheckSameComm(linesearch, 1, viewer, 2);
829 
830   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
831   if (iascii) {
832     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)linesearch, viewer));
833     PetscCall(PetscViewerASCIIPushTab(viewer));
834     PetscTryTypeMethod(linesearch, view, viewer);
835     PetscCall(PetscViewerASCIIPopTab(viewer));
836     PetscCall(PetscViewerASCIIPrintf(viewer, "  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep, (double)linesearch->steptol));
837     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol, (double)linesearch->atol, (double)linesearch->ltol));
838     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT "\n", linesearch->max_its));
839     if (linesearch->ops->precheck) {
840       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
841         PetscCall(PetscViewerASCIIPrintf(viewer, "  using precheck step to speed up Picard convergence\n"));
842       } else {
843         PetscCall(PetscViewerASCIIPrintf(viewer, "  using user-defined precheck step\n"));
844       }
845     }
846     if (linesearch->ops->postcheck) { PetscCall(PetscViewerASCIIPrintf(viewer, "  using user-defined postcheck step\n")); }
847   }
848   PetscFunctionReturn(0);
849 }
850 
851 /*@C
852    SNESLineSearchGetType - Gets the linesearch type
853 
854    Logically Collective on SNESLineSearch
855 
856    Input Parameters:
857 .  linesearch - linesearch context
858 
859    Output Parameters:
860 -  type - The type of line search, or NULL if not set
861 
862    Level: intermediate
863 
864 .seealso: `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
865 @*/
866 PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type) {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
869   PetscValidPointer(type, 2);
870   *type = ((PetscObject)linesearch)->type_name;
871   PetscFunctionReturn(0);
872 }
873 
874 /*@C
875    SNESLineSearchSetType - Sets the linesearch type
876 
877    Logically Collective on SNESLineSearch
878 
879    Input Parameters:
880 +  linesearch - linesearch context
881 -  type - The type of line search to be used
882 
883    Available Types:
884 +  SNESLINESEARCHBASIC - (or equivalently SNESLINESEARCHNONE) Simple damping line search, defaults to using the full Newton step
885 .  SNESLINESEARCHBT - Backtracking line search over the L2 norm of the function
886 .  SNESLINESEARCHL2 - Secant line search over the L2 norm of the function
887 .  SNESLINESEARCHCP - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
888 .  SNESLINESEARCHNLEQERR - Affine-covariant error-oriented linesearch
889 -  SNESLINESEARCHSHELL - User provided SNESLineSearch implementation
890 
891    Options Database:
892 .  -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
893 
894    Level: intermediate
895 
896 .seealso: `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`
897 @*/
898 PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type) {
899   PetscBool match;
900   PetscErrorCode (*r)(SNESLineSearch);
901 
902   PetscFunctionBegin;
903   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
904   PetscValidCharPointer(type, 2);
905 
906   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch, type, &match));
907   if (match) PetscFunctionReturn(0);
908 
909   PetscCall(PetscFunctionListFind(SNESLineSearchList, type, &r));
910   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested Line Search type %s", type);
911   /* Destroy the previous private linesearch context */
912   if (linesearch->ops->destroy) {
913     PetscCall((*(linesearch)->ops->destroy)(linesearch));
914     linesearch->ops->destroy = NULL;
915   }
916   /* Reinitialize function pointers in SNESLineSearchOps structure */
917   linesearch->ops->apply          = NULL;
918   linesearch->ops->view           = NULL;
919   linesearch->ops->setfromoptions = NULL;
920   linesearch->ops->destroy        = NULL;
921 
922   PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch, type));
923   PetscCall((*r)(linesearch));
924   PetscFunctionReturn(0);
925 }
926 
927 /*@
928    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.
929 
930    Input Parameters:
931 +  linesearch - linesearch context
932 -  snes - The snes instance
933 
934    Level: developer
935 
936    Notes:
937    This happens automatically when the line search is obtained/created with
938    SNESGetLineSearch().  This routine is therefore mainly called within SNES
939    implementations.
940 
941    Level: developer
942 
943 .seealso: `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
944 @*/
945 PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes) {
946   PetscFunctionBegin;
947   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
948   PetscValidHeaderSpecific(snes, SNES_CLASSID, 2);
949   linesearch->snes = snes;
950   PetscFunctionReturn(0);
951 }
952 
953 /*@
954    SNESLineSearchGetSNES - Gets the SNES instance associated with the line search.
955    Having an associated SNES is necessary because most line search implementations must be able to
956    evaluate the function using SNESComputeFunction() for the associated SNES.  This routine
957    is used in the line search implementations when one must get this associated SNES instance.
958 
959    Input Parameters:
960 .  linesearch - linesearch context
961 
962    Output Parameters:
963 .  snes - The snes instance
964 
965    Level: developer
966 
967 .seealso: `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
968 @*/
969 PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes) {
970   PetscFunctionBegin;
971   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
972   PetscValidPointer(snes, 2);
973   *snes = linesearch->snes;
974   PetscFunctionReturn(0);
975 }
976 
977 /*@
978    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.
979 
980    Input Parameters:
981 .  linesearch - linesearch context
982 
983    Output Parameters:
984 .  lambda - The last steplength computed during SNESLineSearchApply()
985 
986    Level: advanced
987 
988    Notes:
989    This is useful in methods where the solver is ill-scaled and
990    requires some adaptive notion of the difference in scale between the
991    solution and the function.  For instance, SNESQN may be scaled by the
992    line search lambda using the argument -snes_qn_scaling ls.
993 
994 .seealso: `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
995 @*/
996 PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch, PetscReal *lambda) {
997   PetscFunctionBegin;
998   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
999   PetscValidRealPointer(lambda, 2);
1000   *lambda = linesearch->lambda;
1001   PetscFunctionReturn(0);
1002 }
1003 
1004 /*@
1005    SNESLineSearchSetLambda - Sets the linesearch steplength.
1006 
1007    Input Parameters:
1008 +  linesearch - linesearch context
1009 -  lambda - The last steplength.
1010 
1011    Notes:
1012    This routine is typically used within implementations of SNESLineSearchApply()
1013    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
1014    added in order to facilitate Quasi-Newton methods that use the previous steplength
1015    as an inner scaling parameter.
1016 
1017    Level: advanced
1018 
1019 .seealso: `SNESLineSearchGetLambda()`
1020 @*/
1021 PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda) {
1022   PetscFunctionBegin;
1023   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1024   linesearch->lambda = lambda;
1025   PetscFunctionReturn(0);
1026 }
1027 
1028 /*@
1029    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
1030    tolerances for the relative and absolute change in the function norm, the change
1031    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1032    and the maximum number of iterations the line search procedure may take.
1033 
1034    Input Parameter:
1035 .  linesearch - linesearch context
1036 
1037    Output Parameters:
1038 +  steptol - The minimum steplength
1039 .  maxstep - The maximum steplength
1040 .  rtol    - The relative tolerance for iterative line searches
1041 .  atol    - The absolute tolerance for iterative line searches
1042 .  ltol    - The change in lambda tolerance for iterative line searches
1043 -  max_it  - The maximum number of iterations of the line search
1044 
1045    Level: intermediate
1046 
1047    Notes:
1048    Different line searches may implement these parameters slightly differently as
1049    the type requires.
1050 
1051 .seealso: `SNESLineSearchSetTolerances()`
1052 @*/
1053 PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch, PetscReal *steptol, PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its) {
1054   PetscFunctionBegin;
1055   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1056   if (steptol) {
1057     PetscValidRealPointer(steptol, 2);
1058     *steptol = linesearch->steptol;
1059   }
1060   if (maxstep) {
1061     PetscValidRealPointer(maxstep, 3);
1062     *maxstep = linesearch->maxstep;
1063   }
1064   if (rtol) {
1065     PetscValidRealPointer(rtol, 4);
1066     *rtol = linesearch->rtol;
1067   }
1068   if (atol) {
1069     PetscValidRealPointer(atol, 5);
1070     *atol = linesearch->atol;
1071   }
1072   if (ltol) {
1073     PetscValidRealPointer(ltol, 6);
1074     *ltol = linesearch->ltol;
1075   }
1076   if (max_its) {
1077     PetscValidIntPointer(max_its, 7);
1078     *max_its = linesearch->max_its;
1079   }
1080   PetscFunctionReturn(0);
1081 }
1082 
1083 /*@
1084    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
1085    tolerances for the relative and absolute change in the function norm, the change
1086    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1087    and the maximum number of iterations the line search procedure may take.
1088 
1089    Input Parameters:
1090 +  linesearch - linesearch context
1091 .  steptol - The minimum steplength
1092 .  maxstep - The maximum steplength
1093 .  rtol    - The relative tolerance for iterative line searches
1094 .  atol    - The absolute tolerance for iterative line searches
1095 .  ltol    - The change in lambda tolerance for iterative line searches
1096 -  max_it  - The maximum number of iterations of the line search
1097 
1098    Notes:
1099    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
1100    place of an argument.
1101 
1102    Level: intermediate
1103 
1104 .seealso: `SNESLineSearchGetTolerances()`
1105 @*/
1106 PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch, PetscReal steptol, PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its) {
1107   PetscFunctionBegin;
1108   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1109   PetscValidLogicalCollectiveReal(linesearch, steptol, 2);
1110   PetscValidLogicalCollectiveReal(linesearch, maxstep, 3);
1111   PetscValidLogicalCollectiveReal(linesearch, rtol, 4);
1112   PetscValidLogicalCollectiveReal(linesearch, atol, 5);
1113   PetscValidLogicalCollectiveReal(linesearch, ltol, 6);
1114   PetscValidLogicalCollectiveInt(linesearch, max_its, 7);
1115 
1116   if (steptol != PETSC_DEFAULT) {
1117     PetscCheck(steptol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Minimum step length %14.12e must be non-negative", (double)steptol);
1118     linesearch->steptol = steptol;
1119   }
1120 
1121   if (maxstep != PETSC_DEFAULT) {
1122     PetscCheck(maxstep >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum step length %14.12e must be non-negative", (double)maxstep);
1123     linesearch->maxstep = maxstep;
1124   }
1125 
1126   if (rtol != PETSC_DEFAULT) {
1127     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);
1128     linesearch->rtol = rtol;
1129   }
1130 
1131   if (atol != PETSC_DEFAULT) {
1132     PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %14.12e must be non-negative", (double)atol);
1133     linesearch->atol = atol;
1134   }
1135 
1136   if (ltol != PETSC_DEFAULT) {
1137     PetscCheck(ltol >= 0.0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Lambda tolerance %14.12e must be non-negative", (double)ltol);
1138     linesearch->ltol = ltol;
1139   }
1140 
1141   if (max_its != PETSC_DEFAULT) {
1142     PetscCheck(max_its >= 0, PetscObjectComm((PetscObject)linesearch), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", max_its);
1143     linesearch->max_its = max_its;
1144   }
1145   PetscFunctionReturn(0);
1146 }
1147 
1148 /*@
1149    SNESLineSearchGetDamping - Gets the line search damping parameter.
1150 
1151    Input Parameters:
1152 .  linesearch - linesearch context
1153 
1154    Output Parameters:
1155 .  damping - The damping parameter
1156 
1157    Level: advanced
1158 
1159 .seealso: `SNESLineSearchGetStepTolerance()`, `SNESQN`
1160 @*/
1161 
1162 PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch, PetscReal *damping) {
1163   PetscFunctionBegin;
1164   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1165   PetscValidRealPointer(damping, 2);
1166   *damping = linesearch->damping;
1167   PetscFunctionReturn(0);
1168 }
1169 
1170 /*@
1171    SNESLineSearchSetDamping - Sets the line search damping parameter.
1172 
1173    Input Parameters:
1174 +  linesearch - linesearch context
1175 -  damping - The damping parameter
1176 
1177    Options Database:
1178 .   -snes_linesearch_damping
1179    Level: intermediate
1180 
1181    Notes:
1182    The basic (also known as the none) line search merely takes the update step scaled by the damping parameter.
1183    The use of the damping parameter in the l2 and cp line searches is much more subtle;
1184    it is used as a starting point in calculating the secant step. However, the eventual
1185    step may be of greater length than the damping parameter.  In the bt line search it is
1186    used as the maximum possible step length, as the bt line search only backtracks.
1187 
1188 .seealso: `SNESLineSearchGetDamping()`
1189 @*/
1190 PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch, PetscReal damping) {
1191   PetscFunctionBegin;
1192   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1193   linesearch->damping = damping;
1194   PetscFunctionReturn(0);
1195 }
1196 
1197 /*@
1198    SNESLineSearchGetOrder - Gets the line search approximation order.
1199 
1200    Input Parameters:
1201 .  linesearch - linesearch context
1202 
1203    Output Parameters:
1204 .  order - The order
1205 
1206    Possible Values for order:
1207 +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
1208 .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
1209 -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order
1210 
1211    Level: intermediate
1212 
1213 .seealso: `SNESLineSearchSetOrder()`
1214 @*/
1215 
1216 PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch, PetscInt *order) {
1217   PetscFunctionBegin;
1218   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1219   PetscValidIntPointer(order, 2);
1220   *order = linesearch->order;
1221   PetscFunctionReturn(0);
1222 }
1223 
1224 /*@
1225    SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search
1226 
1227    Input Parameters:
1228 +  linesearch - linesearch context
1229 -  order - The damping parameter
1230 
1231    Level: intermediate
1232 
1233    Possible Values for order:
1234 +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
1235 .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
1236 -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order
1237 
1238    Notes:
1239    Variable orders are supported by the following line searches:
1240 +  bt - cubic and quadratic
1241 -  cp - linear and quadratic
1242 
1243 .seealso: `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1244 @*/
1245 PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch, PetscInt order) {
1246   PetscFunctionBegin;
1247   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1248   linesearch->order = order;
1249   PetscFunctionReturn(0);
1250 }
1251 
1252 /*@
1253    SNESLineSearchGetNorms - Gets the norms for for X, Y, and F.
1254 
1255    Input Parameter:
1256 .  linesearch - linesearch context
1257 
1258    Output Parameters:
1259 +  xnorm - The norm of the current solution
1260 .  fnorm - The norm of the current function
1261 -  ynorm - The norm of the current update
1262 
1263    Notes:
1264    This function is mainly called from SNES implementations.
1265 
1266    Level: developer
1267 
1268 .seealso: `SNESLineSearchSetNorms()` `SNESLineSearchGetVecs()`
1269 @*/
1270 PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal *xnorm, PetscReal *fnorm, PetscReal *ynorm) {
1271   PetscFunctionBegin;
1272   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1273   if (xnorm) *xnorm = linesearch->xnorm;
1274   if (fnorm) *fnorm = linesearch->fnorm;
1275   if (ynorm) *ynorm = linesearch->ynorm;
1276   PetscFunctionReturn(0);
1277 }
1278 
1279 /*@
1280    SNESLineSearchSetNorms - Gets the computed norms for for X, Y, and F.
1281 
1282    Input Parameters:
1283 +  linesearch - linesearch context
1284 .  xnorm - The norm of the current solution
1285 .  fnorm - The norm of the current function
1286 -  ynorm - The norm of the current update
1287 
1288    Level: advanced
1289 
1290 .seealso: `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1291 @*/
1292 PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm) {
1293   PetscFunctionBegin;
1294   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1295   linesearch->xnorm = xnorm;
1296   linesearch->fnorm = fnorm;
1297   linesearch->ynorm = ynorm;
1298   PetscFunctionReturn(0);
1299 }
1300 
1301 /*@
1302    SNESLineSearchComputeNorms - Computes the norms of X, F, and Y.
1303 
1304    Input Parameters:
1305 .  linesearch - linesearch context
1306 
1307    Options Database Keys:
1308 .   -snes_linesearch_norms - turn norm computation on or off
1309 
1310    Level: intermediate
1311 
1312 .seealso: `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1313 @*/
1314 PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch) {
1315   SNES snes;
1316 
1317   PetscFunctionBegin;
1318   if (linesearch->norms) {
1319     if (linesearch->ops->vinorm) {
1320       PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1321       PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1322       PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1323       PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1324     } else {
1325       PetscCall(VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1326       PetscCall(VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1327       PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1328       PetscCall(VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm));
1329       PetscCall(VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1330       PetscCall(VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1331     }
1332   }
1333   PetscFunctionReturn(0);
1334 }
1335 
1336 /*@
1337    SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.
1338 
1339    Input Parameters:
1340 +  linesearch  - linesearch context
1341 -  flg  - indicates whether or not to compute norms
1342 
1343    Options Database Keys:
1344 .   -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic (none) linesearch
1345 
1346    Notes:
1347    This is most relevant to the SNESLINESEARCHBASIC (or equivalently SNESLINESEARCHNONE) line search type since most line searches have a stopping criteria involving the norm.
1348 
1349    Level: intermediate
1350 
1351 .seealso: `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1352 @*/
1353 PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg) {
1354   PetscFunctionBegin;
1355   linesearch->norms = flg;
1356   PetscFunctionReturn(0);
1357 }
1358 
1359 /*@
1360    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context
1361 
1362    Input Parameter:
1363 .  linesearch - linesearch context
1364 
1365    Output Parameters:
1366 +  X - Solution vector
1367 .  F - Function vector
1368 .  Y - Search direction vector
1369 .  W - Solution work vector
1370 -  G - Function work vector
1371 
1372    Notes:
1373    At the beginning of a line search application, X should contain a
1374    solution and the vector F the function computed at X.  At the end of the
1375    line search application, X should contain the new solution, and F the
1376    function evaluated at the new solution.
1377 
1378    These vectors are owned by the SNESLineSearch and should not be destroyed by the caller
1379 
1380    Level: advanced
1381 
1382 .seealso: `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1383 @*/
1384 PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch, Vec *X, Vec *F, Vec *Y, Vec *W, Vec *G) {
1385   PetscFunctionBegin;
1386   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1387   if (X) {
1388     PetscValidPointer(X, 2);
1389     *X = linesearch->vec_sol;
1390   }
1391   if (F) {
1392     PetscValidPointer(F, 3);
1393     *F = linesearch->vec_func;
1394   }
1395   if (Y) {
1396     PetscValidPointer(Y, 4);
1397     *Y = linesearch->vec_update;
1398   }
1399   if (W) {
1400     PetscValidPointer(W, 5);
1401     *W = linesearch->vec_sol_new;
1402   }
1403   if (G) {
1404     PetscValidPointer(G, 6);
1405     *G = linesearch->vec_func_new;
1406   }
1407   PetscFunctionReturn(0);
1408 }
1409 
1410 /*@
1411    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context
1412 
1413    Input Parameters:
1414 +  linesearch - linesearch context
1415 .  X - Solution vector
1416 .  F - Function vector
1417 .  Y - Search direction vector
1418 .  W - Solution work vector
1419 -  G - Function work vector
1420 
1421    Level: advanced
1422 
1423 .seealso: `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1424 @*/
1425 PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch, Vec X, Vec F, Vec Y, Vec W, Vec G) {
1426   PetscFunctionBegin;
1427   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1428   if (X) {
1429     PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
1430     linesearch->vec_sol = X;
1431   }
1432   if (F) {
1433     PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
1434     linesearch->vec_func = F;
1435   }
1436   if (Y) {
1437     PetscValidHeaderSpecific(Y, VEC_CLASSID, 4);
1438     linesearch->vec_update = Y;
1439   }
1440   if (W) {
1441     PetscValidHeaderSpecific(W, VEC_CLASSID, 5);
1442     linesearch->vec_sol_new = W;
1443   }
1444   if (G) {
1445     PetscValidHeaderSpecific(G, VEC_CLASSID, 6);
1446     linesearch->vec_func_new = G;
1447   }
1448   PetscFunctionReturn(0);
1449 }
1450 
1451 /*@C
1452    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1453    SNES options in the database.
1454 
1455    Logically Collective on SNESLineSearch
1456 
1457    Input Parameters:
1458 +  snes - the SNES context
1459 -  prefix - the prefix to prepend to all option names
1460 
1461    Notes:
1462    A hyphen (-) must NOT be given at the beginning of the prefix name.
1463    The first character of all runtime options is AUTOMATICALLY the hyphen.
1464 
1465    Level: advanced
1466 
1467 .seealso: `SNESGetOptionsPrefix()`
1468 @*/
1469 PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch, const char prefix[]) {
1470   PetscFunctionBegin;
1471   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1472   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch, prefix));
1473   PetscFunctionReturn(0);
1474 }
1475 
1476 /*@C
1477    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
1478    SNESLineSearch options in the database.
1479 
1480    Not Collective
1481 
1482    Input Parameter:
1483 .  linesearch - the SNESLineSearch context
1484 
1485    Output Parameter:
1486 .  prefix - pointer to the prefix string used
1487 
1488    Notes:
1489    On the fortran side, the user should pass in a string 'prefix' of
1490    sufficient length to hold the prefix.
1491 
1492    Level: advanced
1493 
1494 .seealso: `SNESAppendOptionsPrefix()`
1495 @*/
1496 PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch, const char *prefix[]) {
1497   PetscFunctionBegin;
1498   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1499   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch, prefix));
1500   PetscFunctionReturn(0);
1501 }
1502 
1503 /*@C
1504    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.
1505 
1506    Input Parameters:
1507 +  linesearch - the SNESLineSearch context
1508 -  nwork - the number of work vectors
1509 
1510    Level: developer
1511 
1512 .seealso: `SNESSetWorkVecs()`
1513 @*/
1514 PetscErrorCode SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork) {
1515   PetscFunctionBegin;
1516   if (linesearch->vec_sol) {
1517     PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1518   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1519   PetscFunctionReturn(0);
1520 }
1521 
1522 /*@
1523    SNESLineSearchGetReason - Gets the success/failure status of the last line search application
1524 
1525    Input Parameters:
1526 .  linesearch - linesearch context
1527 
1528    Output Parameters:
1529 .  result - The success or failure status
1530 
1531    Notes:
1532    This is typically called after SNESLineSearchApply() in order to determine if the line-search failed
1533    (and set the SNES convergence accordingly).
1534 
1535    Level: intermediate
1536 
1537 .seealso: `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1538 @*/
1539 PetscErrorCode SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result) {
1540   PetscFunctionBegin;
1541   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1542   PetscValidPointer(result, 2);
1543   *result = linesearch->result;
1544   PetscFunctionReturn(0);
1545 }
1546 
1547 /*@
1548    SNESLineSearchSetReason - Sets the success/failure status of the last line search application
1549 
1550    Input Parameters:
1551 +  linesearch - linesearch context
1552 -  result - The success or failure status
1553 
1554    Notes:
1555    This is typically called in a SNESLineSearchApply() or SNESLineSearchShell implementation to set
1556    the success or failure of the line search method.
1557 
1558    Level: developer
1559 
1560 .seealso: `SNESLineSearchGetSResult()`
1561 @*/
1562 PetscErrorCode SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result) {
1563   PetscFunctionBegin;
1564   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1565   linesearch->result = result;
1566   PetscFunctionReturn(0);
1567 }
1568 
1569 /*@C
1570    SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.
1571 
1572    Input Parameters:
1573 +  snes - nonlinear context obtained from SNESCreate()
1574 .  projectfunc - function for projecting the function to the bounds
1575 -  normfunc - function for computing the norm of an active set
1576 
1577    Logically Collective on SNES
1578 
1579    Calling sequence of projectfunc:
1580 .vb
1581    projectfunc (SNES snes, Vec X)
1582 .ve
1583 
1584     Input parameters for projectfunc:
1585 +   snes - nonlinear context
1586 -   X - current solution
1587 
1588     Output parameters for projectfunc:
1589 .   X - Projected solution
1590 
1591    Calling sequence of normfunc:
1592 .vb
1593    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
1594 .ve
1595 
1596     Input parameters for normfunc:
1597 +   snes - nonlinear context
1598 .   X - current solution
1599 -   F - current residual
1600 
1601     Output parameters for normfunc:
1602 .   fnorm - VI-specific norm of the function
1603 
1604     Notes:
1605     The VI solvers require projection of the solution to the feasible set.  projectfunc should implement this.
1606 
1607     The VI solvers require special evaluation of the function norm such that the norm is only calculated
1608     on the inactive set.  This should be implemented by normfunc.
1609 
1610     Level: developer
1611 
1612 .seealso: `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`
1613 @*/
1614 PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc) {
1615   PetscFunctionBegin;
1616   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 1);
1617   if (projectfunc) linesearch->ops->viproject = projectfunc;
1618   if (normfunc) linesearch->ops->vinorm = normfunc;
1619   PetscFunctionReturn(0);
1620 }
1621 
1622 /*@C
1623    SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.
1624 
1625    Input Parameter:
1626 .  linesearch - the line search context, obtain with SNESGetLineSearch()
1627 
1628    Output Parameters:
1629 +  projectfunc - function for projecting the function to the bounds
1630 -  normfunc - function for computing the norm of an active set
1631 
1632    Logically Collective on SNES
1633 
1634     Level: developer
1635 
1636 .seealso: `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`
1637 @*/
1638 PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc) {
1639   PetscFunctionBegin;
1640   if (projectfunc) *projectfunc = linesearch->ops->viproject;
1641   if (normfunc) *normfunc = linesearch->ops->vinorm;
1642   PetscFunctionReturn(0);
1643 }
1644 
1645 /*@C
1646   SNESLineSearchRegister - See SNESLineSearchRegister()
1647 
1648   Level: advanced
1649 @*/
1650 PetscErrorCode SNESLineSearchRegister(const char sname[], PetscErrorCode (*function)(SNESLineSearch)) {
1651   PetscFunctionBegin;
1652   PetscCall(SNESInitializePackage());
1653   PetscCall(PetscFunctionListAdd(&SNESLineSearchList, sname, function));
1654   PetscFunctionReturn(0);
1655 }
1656