xref: /petsc/src/snes/linesearch/interface/linesearch.c (revision dbbe0bcd3f3a8fbab5a45420dc06f8387e5764c6)
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) PetscUseTypeMethod(linesearch,setup);
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) PetscUseTypeMethod(linesearch,reset);
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     PetscUseTypeMethod(linesearch,precheck , 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     PetscUseTypeMethod(linesearch,postcheck ,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   PetscUseTypeMethod(linesearch,apply);
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   PetscTryTypeMethod(linesearch,setfromoptions,PetscOptionsObject);
833 
834   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)linesearch,PetscOptionsObject));
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     PetscCall(PetscViewerASCIIPushTab(viewer));
867     PetscTryTypeMethod(linesearch,view ,viewer);
868     PetscCall(PetscViewerASCIIPopTab(viewer));
869     PetscCall(PetscViewerASCIIPrintf(viewer,"  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol));
870     PetscCall(PetscViewerASCIIPrintf(viewer,"  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol));
871     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum iterations=%" PetscInt_FMT "\n", linesearch->max_its));
872     if (linesearch->ops->precheck) {
873       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
874         PetscCall(PetscViewerASCIIPrintf(viewer,"  using precheck step to speed up Picard convergence\n"));
875       } else {
876         PetscCall(PetscViewerASCIIPrintf(viewer,"  using user-defined precheck step\n"));
877       }
878     }
879     if (linesearch->ops->postcheck) {
880       PetscCall(PetscViewerASCIIPrintf(viewer,"  using user-defined postcheck step\n"));
881     }
882   }
883   PetscFunctionReturn(0);
884 }
885 
886 /*@C
887    SNESLineSearchGetType - Gets the linesearch type
888 
889    Logically Collective on SNESLineSearch
890 
891    Input Parameters:
892 .  linesearch - linesearch context
893 
894    Output Parameters:
895 -  type - The type of line search, or NULL if not set
896 
897    Level: intermediate
898 
899 .seealso: `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchSetType()`
900 @*/
901 PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
902 {
903   PetscFunctionBegin;
904   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
905   PetscValidPointer(type,2);
906   *type = ((PetscObject)linesearch)->type_name;
907   PetscFunctionReturn(0);
908 }
909 
910 /*@C
911    SNESLineSearchSetType - Sets the linesearch type
912 
913    Logically Collective on SNESLineSearch
914 
915    Input Parameters:
916 +  linesearch - linesearch context
917 -  type - The type of line search to be used
918 
919    Available Types:
920 +  SNESLINESEARCHBASIC - (or equivalently SNESLINESEARCHNONE) Simple damping line search, defaults to using the full Newton step
921 .  SNESLINESEARCHBT - Backtracking line search over the L2 norm of the function
922 .  SNESLINESEARCHL2 - Secant line search over the L2 norm of the function
923 .  SNESLINESEARCHCP - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
924 .  SNESLINESEARCHNLEQERR - Affine-covariant error-oriented linesearch
925 -  SNESLINESEARCHSHELL - User provided SNESLineSearch implementation
926 
927    Options Database:
928 .  -snes_linesearch_type <type> - basic (or equivalently none), bt, l2, cp, nleqerr, shell
929 
930    Level: intermediate
931 
932 .seealso: `SNESLineSearchCreate()`, `SNESLineSearchType`, `SNESLineSearchSetFromOptions()`, `SNESLineSearchGetType()`
933 @*/
934 PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
935 {
936   PetscBool      match;
937   PetscErrorCode (*r)(SNESLineSearch);
938 
939   PetscFunctionBegin;
940   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
941   PetscValidCharPointer(type,2);
942 
943   PetscCall(PetscObjectTypeCompare((PetscObject)linesearch,type,&match));
944   if (match) PetscFunctionReturn(0);
945 
946   PetscCall(PetscFunctionListFind(SNESLineSearchList,type,&r));
947   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type);
948   /* Destroy the previous private linesearch context */
949   if (linesearch->ops->destroy) {
950     PetscCall((*(linesearch)->ops->destroy)(linesearch));
951     linesearch->ops->destroy = NULL;
952   }
953   /* Reinitialize function pointers in SNESLineSearchOps structure */
954   linesearch->ops->apply          = NULL;
955   linesearch->ops->view           = NULL;
956   linesearch->ops->setfromoptions = NULL;
957   linesearch->ops->destroy        = NULL;
958 
959   PetscCall(PetscObjectChangeTypeName((PetscObject)linesearch,type));
960   PetscCall((*r)(linesearch));
961   PetscFunctionReturn(0);
962 }
963 
964 /*@
965    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.
966 
967    Input Parameters:
968 +  linesearch - linesearch context
969 -  snes - The snes instance
970 
971    Level: developer
972 
973    Notes:
974    This happens automatically when the line search is obtained/created with
975    SNESGetLineSearch().  This routine is therefore mainly called within SNES
976    implementations.
977 
978    Level: developer
979 
980 .seealso: `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
981 @*/
982 PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
983 {
984   PetscFunctionBegin;
985   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
986   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
987   linesearch->snes = snes;
988   PetscFunctionReturn(0);
989 }
990 
991 /*@
992    SNESLineSearchGetSNES - Gets the SNES instance associated with the line search.
993    Having an associated SNES is necessary because most line search implementations must be able to
994    evaluate the function using SNESComputeFunction() for the associated SNES.  This routine
995    is used in the line search implementations when one must get this associated SNES instance.
996 
997    Input Parameters:
998 .  linesearch - linesearch context
999 
1000    Output Parameters:
1001 .  snes - The snes instance
1002 
1003    Level: developer
1004 
1005 .seealso: `SNESLineSearchGetSNES()`, `SNESLineSearchSetVecs()`, `SNES`
1006 @*/
1007 PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
1008 {
1009   PetscFunctionBegin;
1010   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1011   PetscValidPointer(snes,2);
1012   *snes = linesearch->snes;
1013   PetscFunctionReturn(0);
1014 }
1015 
1016 /*@
1017    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.
1018 
1019    Input Parameters:
1020 .  linesearch - linesearch context
1021 
1022    Output Parameters:
1023 .  lambda - The last steplength computed during SNESLineSearchApply()
1024 
1025    Level: advanced
1026 
1027    Notes:
1028    This is useful in methods where the solver is ill-scaled and
1029    requires some adaptive notion of the difference in scale between the
1030    solution and the function.  For instance, SNESQN may be scaled by the
1031    line search lambda using the argument -snes_qn_scaling ls.
1032 
1033 .seealso: `SNESLineSearchSetLambda()`, `SNESLineSearchGetDamping()`, `SNESLineSearchApply()`
1034 @*/
1035 PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
1036 {
1037   PetscFunctionBegin;
1038   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1039   PetscValidRealPointer(lambda, 2);
1040   *lambda = linesearch->lambda;
1041   PetscFunctionReturn(0);
1042 }
1043 
1044 /*@
1045    SNESLineSearchSetLambda - Sets the linesearch steplength.
1046 
1047    Input Parameters:
1048 +  linesearch - linesearch context
1049 -  lambda - The last steplength.
1050 
1051    Notes:
1052    This routine is typically used within implementations of SNESLineSearchApply()
1053    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
1054    added in order to facilitate Quasi-Newton methods that use the previous steplength
1055    as an inner scaling parameter.
1056 
1057    Level: advanced
1058 
1059 .seealso: `SNESLineSearchGetLambda()`
1060 @*/
1061 PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1062 {
1063   PetscFunctionBegin;
1064   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1065   linesearch->lambda = lambda;
1066   PetscFunctionReturn(0);
1067 }
1068 
1069 /*@
1070    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
1071    tolerances for the relative and absolute change in the function norm, the change
1072    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1073    and the maximum number of iterations the line search procedure may take.
1074 
1075    Input Parameter:
1076 .  linesearch - linesearch context
1077 
1078    Output Parameters:
1079 +  steptol - The minimum steplength
1080 .  maxstep - The maximum steplength
1081 .  rtol    - The relative tolerance for iterative line searches
1082 .  atol    - The absolute tolerance for iterative line searches
1083 .  ltol    - The change in lambda tolerance for iterative line searches
1084 -  max_it  - The maximum number of iterations of the line search
1085 
1086    Level: intermediate
1087 
1088    Notes:
1089    Different line searches may implement these parameters slightly differently as
1090    the type requires.
1091 
1092 .seealso: `SNESLineSearchSetTolerances()`
1093 @*/
1094 PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1095 {
1096   PetscFunctionBegin;
1097   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1098   if (steptol) {
1099     PetscValidRealPointer(steptol, 2);
1100     *steptol = linesearch->steptol;
1101   }
1102   if (maxstep) {
1103     PetscValidRealPointer(maxstep, 3);
1104     *maxstep = linesearch->maxstep;
1105   }
1106   if (rtol) {
1107     PetscValidRealPointer(rtol, 4);
1108     *rtol = linesearch->rtol;
1109   }
1110   if (atol) {
1111     PetscValidRealPointer(atol, 5);
1112     *atol = linesearch->atol;
1113   }
1114   if (ltol) {
1115     PetscValidRealPointer(ltol, 6);
1116     *ltol = linesearch->ltol;
1117   }
1118   if (max_its) {
1119     PetscValidIntPointer(max_its, 7);
1120     *max_its = linesearch->max_its;
1121   }
1122   PetscFunctionReturn(0);
1123 }
1124 
1125 /*@
1126    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
1127    tolerances for the relative and absolute change in the function norm, the change
1128    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
1129    and the maximum number of iterations the line search procedure may take.
1130 
1131    Input Parameters:
1132 +  linesearch - linesearch context
1133 .  steptol - The minimum steplength
1134 .  maxstep - The maximum steplength
1135 .  rtol    - The relative tolerance for iterative line searches
1136 .  atol    - The absolute tolerance for iterative line searches
1137 .  ltol    - The change in lambda tolerance for iterative line searches
1138 -  max_it  - The maximum number of iterations of the line search
1139 
1140    Notes:
1141    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
1142    place of an argument.
1143 
1144    Level: intermediate
1145 
1146 .seealso: `SNESLineSearchGetTolerances()`
1147 @*/
1148 PetscErrorCode  SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
1149 {
1150   PetscFunctionBegin;
1151   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1152   PetscValidLogicalCollectiveReal(linesearch,steptol,2);
1153   PetscValidLogicalCollectiveReal(linesearch,maxstep,3);
1154   PetscValidLogicalCollectiveReal(linesearch,rtol,4);
1155   PetscValidLogicalCollectiveReal(linesearch,atol,5);
1156   PetscValidLogicalCollectiveReal(linesearch,ltol,6);
1157   PetscValidLogicalCollectiveInt(linesearch,max_its,7);
1158 
1159   if (steptol!= PETSC_DEFAULT) {
1160     PetscCheck(steptol >= 0.0,PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Minimum step length %14.12e must be non-negative",(double)steptol);
1161     linesearch->steptol = steptol;
1162   }
1163 
1164   if (maxstep!= PETSC_DEFAULT) {
1165     PetscCheck(maxstep >= 0.0,PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Maximum step length %14.12e must be non-negative",(double)maxstep);
1166     linesearch->maxstep = maxstep;
1167   }
1168 
1169   if (rtol != PETSC_DEFAULT) {
1170     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);
1171     linesearch->rtol = rtol;
1172   }
1173 
1174   if (atol != PETSC_DEFAULT) {
1175     PetscCheck(atol >= 0.0,PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %14.12e must be non-negative",(double)atol);
1176     linesearch->atol = atol;
1177   }
1178 
1179   if (ltol != PETSC_DEFAULT) {
1180     PetscCheck(ltol >= 0.0,PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Lambda tolerance %14.12e must be non-negative",(double)ltol);
1181     linesearch->ltol = ltol;
1182   }
1183 
1184   if (max_its != PETSC_DEFAULT) {
1185     PetscCheck(max_its >= 0,PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %" PetscInt_FMT " must be non-negative",max_its);
1186     linesearch->max_its = max_its;
1187   }
1188   PetscFunctionReturn(0);
1189 }
1190 
1191 /*@
1192    SNESLineSearchGetDamping - Gets the line search damping parameter.
1193 
1194    Input Parameters:
1195 .  linesearch - linesearch context
1196 
1197    Output Parameters:
1198 .  damping - The damping parameter
1199 
1200    Level: advanced
1201 
1202 .seealso: `SNESLineSearchGetStepTolerance()`, `SNESQN`
1203 @*/
1204 
1205 PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
1206 {
1207   PetscFunctionBegin;
1208   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1209   PetscValidRealPointer(damping, 2);
1210   *damping = linesearch->damping;
1211   PetscFunctionReturn(0);
1212 }
1213 
1214 /*@
1215    SNESLineSearchSetDamping - Sets the line search damping parameter.
1216 
1217    Input Parameters:
1218 +  linesearch - linesearch context
1219 -  damping - The damping parameter
1220 
1221    Options Database:
1222 .   -snes_linesearch_damping
1223    Level: intermediate
1224 
1225    Notes:
1226    The basic (also known as the none) line search merely takes the update step scaled by the damping parameter.
1227    The use of the damping parameter in the l2 and cp line searches is much more subtle;
1228    it is used as a starting point in calculating the secant step. However, the eventual
1229    step may be of greater length than the damping parameter.  In the bt line search it is
1230    used as the maximum possible step length, as the bt line search only backtracks.
1231 
1232 .seealso: `SNESLineSearchGetDamping()`
1233 @*/
1234 PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
1235 {
1236   PetscFunctionBegin;
1237   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1238   linesearch->damping = damping;
1239   PetscFunctionReturn(0);
1240 }
1241 
1242 /*@
1243    SNESLineSearchGetOrder - Gets the line search approximation order.
1244 
1245    Input Parameters:
1246 .  linesearch - linesearch context
1247 
1248    Output Parameters:
1249 .  order - The order
1250 
1251    Possible Values for order:
1252 +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
1253 .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
1254 -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order
1255 
1256    Level: intermediate
1257 
1258 .seealso: `SNESLineSearchSetOrder()`
1259 @*/
1260 
1261 PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
1262 {
1263   PetscFunctionBegin;
1264   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1265   PetscValidIntPointer(order, 2);
1266   *order = linesearch->order;
1267   PetscFunctionReturn(0);
1268 }
1269 
1270 /*@
1271    SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search
1272 
1273    Input Parameters:
1274 +  linesearch - linesearch context
1275 -  order - The damping parameter
1276 
1277    Level: intermediate
1278 
1279    Possible Values for order:
1280 +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
1281 .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
1282 -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order
1283 
1284    Notes:
1285    Variable orders are supported by the following line searches:
1286 +  bt - cubic and quadratic
1287 -  cp - linear and quadratic
1288 
1289 .seealso: `SNESLineSearchGetOrder()`, `SNESLineSearchSetDamping()`
1290 @*/
1291 PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
1292 {
1293   PetscFunctionBegin;
1294   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1295   linesearch->order = order;
1296   PetscFunctionReturn(0);
1297 }
1298 
1299 /*@
1300    SNESLineSearchGetNorms - Gets the norms for for X, Y, and F.
1301 
1302    Input Parameter:
1303 .  linesearch - linesearch context
1304 
1305    Output Parameters:
1306 +  xnorm - The norm of the current solution
1307 .  fnorm - The norm of the current function
1308 -  ynorm - The norm of the current update
1309 
1310    Notes:
1311    This function is mainly called from SNES implementations.
1312 
1313    Level: developer
1314 
1315 .seealso: `SNESLineSearchSetNorms()` `SNESLineSearchGetVecs()`
1316 @*/
1317 PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
1318 {
1319   PetscFunctionBegin;
1320   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1321   if (xnorm) *xnorm = linesearch->xnorm;
1322   if (fnorm) *fnorm = linesearch->fnorm;
1323   if (ynorm) *ynorm = linesearch->ynorm;
1324   PetscFunctionReturn(0);
1325 }
1326 
1327 /*@
1328    SNESLineSearchSetNorms - Gets the computed norms for for X, Y, and F.
1329 
1330    Input Parameters:
1331 +  linesearch - linesearch context
1332 .  xnorm - The norm of the current solution
1333 .  fnorm - The norm of the current function
1334 -  ynorm - The norm of the current update
1335 
1336    Level: advanced
1337 
1338 .seealso: `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1339 @*/
1340 PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1341 {
1342   PetscFunctionBegin;
1343   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1344   linesearch->xnorm = xnorm;
1345   linesearch->fnorm = fnorm;
1346   linesearch->ynorm = ynorm;
1347   PetscFunctionReturn(0);
1348 }
1349 
1350 /*@
1351    SNESLineSearchComputeNorms - Computes the norms of X, F, and Y.
1352 
1353    Input Parameters:
1354 .  linesearch - linesearch context
1355 
1356    Options Database Keys:
1357 .   -snes_linesearch_norms - turn norm computation on or off
1358 
1359    Level: intermediate
1360 
1361 .seealso: `SNESLineSearchGetNorms`, `SNESLineSearchSetNorms()`, `SNESLineSearchSetComputeNorms()`
1362 @*/
1363 PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1364 {
1365   SNES           snes;
1366 
1367   PetscFunctionBegin;
1368   if (linesearch->norms) {
1369     if (linesearch->ops->vinorm) {
1370       PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
1371       PetscCall(VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm));
1372       PetscCall(VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1373       PetscCall((*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm));
1374     } else {
1375       PetscCall(VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm));
1376       PetscCall(VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm));
1377       PetscCall(VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm));
1378       PetscCall(VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm));
1379       PetscCall(VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm));
1380       PetscCall(VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm));
1381     }
1382   }
1383   PetscFunctionReturn(0);
1384 }
1385 
1386 /*@
1387    SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.
1388 
1389    Input Parameters:
1390 +  linesearch  - linesearch context
1391 -  flg  - indicates whether or not to compute norms
1392 
1393    Options Database Keys:
1394 .   -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic (none) linesearch
1395 
1396    Notes:
1397    This is most relevant to the SNESLINESEARCHBASIC (or equivalently SNESLINESEARCHNONE) line search type since most line searches have a stopping criteria involving the norm.
1398 
1399    Level: intermediate
1400 
1401 .seealso: `SNESLineSearchGetNorms()`, `SNESLineSearchSetNorms()`, `SNESLineSearchComputeNorms()`, `SNESLINESEARCHBASIC`
1402 @*/
1403 PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1404 {
1405   PetscFunctionBegin;
1406   linesearch->norms = flg;
1407   PetscFunctionReturn(0);
1408 }
1409 
1410 /*@
1411    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context
1412 
1413    Input Parameter:
1414 .  linesearch - linesearch context
1415 
1416    Output Parameters:
1417 +  X - Solution vector
1418 .  F - Function vector
1419 .  Y - Search direction vector
1420 .  W - Solution work vector
1421 -  G - Function work vector
1422 
1423    Notes:
1424    At the beginning of a line search application, X should contain a
1425    solution and the vector F the function computed at X.  At the end of the
1426    line search application, X should contain the new solution, and F the
1427    function evaluated at the new solution.
1428 
1429    These vectors are owned by the SNESLineSearch and should not be destroyed by the caller
1430 
1431    Level: advanced
1432 
1433 .seealso: `SNESLineSearchGetNorms()`, `SNESLineSearchSetVecs()`
1434 @*/
1435 PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
1436 {
1437   PetscFunctionBegin;
1438   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1439   if (X) {
1440     PetscValidPointer(X, 2);
1441     *X = linesearch->vec_sol;
1442   }
1443   if (F) {
1444     PetscValidPointer(F, 3);
1445     *F = linesearch->vec_func;
1446   }
1447   if (Y) {
1448     PetscValidPointer(Y, 4);
1449     *Y = linesearch->vec_update;
1450   }
1451   if (W) {
1452     PetscValidPointer(W, 5);
1453     *W = linesearch->vec_sol_new;
1454   }
1455   if (G) {
1456     PetscValidPointer(G, 6);
1457     *G = linesearch->vec_func_new;
1458   }
1459   PetscFunctionReturn(0);
1460 }
1461 
1462 /*@
1463    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context
1464 
1465    Input Parameters:
1466 +  linesearch - linesearch context
1467 .  X - Solution vector
1468 .  F - Function vector
1469 .  Y - Search direction vector
1470 .  W - Solution work vector
1471 -  G - Function work vector
1472 
1473    Level: advanced
1474 
1475 .seealso: `SNESLineSearchSetNorms()`, `SNESLineSearchGetVecs()`
1476 @*/
1477 PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
1478 {
1479   PetscFunctionBegin;
1480   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1481   if (X) {
1482     PetscValidHeaderSpecific(X,VEC_CLASSID,2);
1483     linesearch->vec_sol = X;
1484   }
1485   if (F) {
1486     PetscValidHeaderSpecific(F,VEC_CLASSID,3);
1487     linesearch->vec_func = F;
1488   }
1489   if (Y) {
1490     PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
1491     linesearch->vec_update = Y;
1492   }
1493   if (W) {
1494     PetscValidHeaderSpecific(W,VEC_CLASSID,5);
1495     linesearch->vec_sol_new = W;
1496   }
1497   if (G) {
1498     PetscValidHeaderSpecific(G,VEC_CLASSID,6);
1499     linesearch->vec_func_new = G;
1500   }
1501   PetscFunctionReturn(0);
1502 }
1503 
1504 /*@C
1505    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1506    SNES options in the database.
1507 
1508    Logically Collective on SNESLineSearch
1509 
1510    Input Parameters:
1511 +  snes - the SNES context
1512 -  prefix - the prefix to prepend to all option names
1513 
1514    Notes:
1515    A hyphen (-) must NOT be given at the beginning of the prefix name.
1516    The first character of all runtime options is AUTOMATICALLY the hyphen.
1517 
1518    Level: advanced
1519 
1520 .seealso: `SNESGetOptionsPrefix()`
1521 @*/
1522 PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
1523 {
1524   PetscFunctionBegin;
1525   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1526   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix));
1527   PetscFunctionReturn(0);
1528 }
1529 
1530 /*@C
1531    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
1532    SNESLineSearch options in the database.
1533 
1534    Not Collective
1535 
1536    Input Parameter:
1537 .  linesearch - the SNESLineSearch context
1538 
1539    Output Parameter:
1540 .  prefix - pointer to the prefix string used
1541 
1542    Notes:
1543    On the fortran side, the user should pass in a string 'prefix' of
1544    sufficient length to hold the prefix.
1545 
1546    Level: advanced
1547 
1548 .seealso: `SNESAppendOptionsPrefix()`
1549 @*/
1550 PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
1551 {
1552   PetscFunctionBegin;
1553   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1554   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix));
1555   PetscFunctionReturn(0);
1556 }
1557 
1558 /*@C
1559    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.
1560 
1561    Input Parameters:
1562 +  linesearch - the SNESLineSearch context
1563 -  nwork - the number of work vectors
1564 
1565    Level: developer
1566 
1567 .seealso: `SNESSetWorkVecs()`
1568 @*/
1569 PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1570 {
1571   PetscFunctionBegin;
1572   if (linesearch->vec_sol) {
1573     PetscCall(VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work));
1574   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1575   PetscFunctionReturn(0);
1576 }
1577 
1578 /*@
1579    SNESLineSearchGetReason - Gets the success/failure status of the last line search application
1580 
1581    Input Parameters:
1582 .  linesearch - linesearch context
1583 
1584    Output Parameters:
1585 .  result - The success or failure status
1586 
1587    Notes:
1588    This is typically called after SNESLineSearchApply() in order to determine if the line-search failed
1589    (and set the SNES convergence accordingly).
1590 
1591    Level: intermediate
1592 
1593 .seealso: `SNESLineSearchSetReason()`, `SNESLineSearchReason`
1594 @*/
1595 PetscErrorCode  SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1596 {
1597   PetscFunctionBegin;
1598   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1599   PetscValidPointer(result, 2);
1600   *result = linesearch->result;
1601   PetscFunctionReturn(0);
1602 }
1603 
1604 /*@
1605    SNESLineSearchSetReason - Sets the success/failure status of the last line search application
1606 
1607    Input Parameters:
1608 +  linesearch - linesearch context
1609 -  result - The success or failure status
1610 
1611    Notes:
1612    This is typically called in a SNESLineSearchApply() or SNESLineSearchShell implementation to set
1613    the success or failure of the line search method.
1614 
1615    Level: developer
1616 
1617 .seealso: `SNESLineSearchGetSResult()`
1618 @*/
1619 PetscErrorCode  SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1620 {
1621   PetscFunctionBegin;
1622   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1623   linesearch->result = result;
1624   PetscFunctionReturn(0);
1625 }
1626 
1627 /*@C
1628    SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.
1629 
1630    Input Parameters:
1631 +  snes - nonlinear context obtained from SNESCreate()
1632 .  projectfunc - function for projecting the function to the bounds
1633 -  normfunc - function for computing the norm of an active set
1634 
1635    Logically Collective on SNES
1636 
1637    Calling sequence of projectfunc:
1638 .vb
1639    projectfunc (SNES snes, Vec X)
1640 .ve
1641 
1642     Input parameters for projectfunc:
1643 +   snes - nonlinear context
1644 -   X - current solution
1645 
1646     Output parameters for projectfunc:
1647 .   X - Projected solution
1648 
1649    Calling sequence of normfunc:
1650 .vb
1651    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
1652 .ve
1653 
1654     Input parameters for normfunc:
1655 +   snes - nonlinear context
1656 .   X - current solution
1657 -   F - current residual
1658 
1659     Output parameters for normfunc:
1660 .   fnorm - VI-specific norm of the function
1661 
1662     Notes:
1663     The VI solvers require projection of the solution to the feasible set.  projectfunc should implement this.
1664 
1665     The VI solvers require special evaluation of the function norm such that the norm is only calculated
1666     on the inactive set.  This should be implemented by normfunc.
1667 
1668     Level: developer
1669 
1670 .seealso: `SNESLineSearchGetVIFunctions()`, `SNESLineSearchSetPostCheck()`, `SNESLineSearchSetPreCheck()`
1671 @*/
1672 PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
1673 {
1674   PetscFunctionBegin;
1675   PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1);
1676   if (projectfunc) linesearch->ops->viproject = projectfunc;
1677   if (normfunc) linesearch->ops->vinorm = normfunc;
1678   PetscFunctionReturn(0);
1679 }
1680 
1681 /*@C
1682    SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.
1683 
1684    Input Parameter:
1685 .  linesearch - the line search context, obtain with SNESGetLineSearch()
1686 
1687    Output Parameters:
1688 +  projectfunc - function for projecting the function to the bounds
1689 -  normfunc - function for computing the norm of an active set
1690 
1691    Logically Collective on SNES
1692 
1693     Level: developer
1694 
1695 .seealso: `SNESLineSearchSetVIFunctions()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchGetPreCheck()`
1696 @*/
1697 PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
1698 {
1699   PetscFunctionBegin;
1700   if (projectfunc) *projectfunc = linesearch->ops->viproject;
1701   if (normfunc) *normfunc = linesearch->ops->vinorm;
1702   PetscFunctionReturn(0);
1703 }
1704 
1705 /*@C
1706   SNESLineSearchRegister - See SNESLineSearchRegister()
1707 
1708   Level: advanced
1709 @*/
1710 PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
1711 {
1712   PetscFunctionBegin;
1713   PetscCall(SNESInitializePackage());
1714   PetscCall(PetscFunctionListAdd(&SNESLineSearchList,sname,function));
1715   PetscFunctionReturn(0);
1716 }
1717