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