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