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