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