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