xref: /petsc/src/snes/linesearch/interface/linesearch.c (revision 71b4ebd2ce2057e5b43040295eb15ca8409a673f)
1 #include <private/linesearchimpl.h> /*I "petsclinesearch.h" I*/
2 
3 PetscBool  LineSearchRegisterAllCalled = PETSC_FALSE;
4 PetscFList LineSearchList              = PETSC_NULL;
5 
6 PetscClassId   LineSearch_CLASSID;
7 PetscLogEvent  LineSearch_Apply;
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "LineSearchCreate"
11 /*@
12    LineSearchCreate - Creates the line search.
13 
14    Collective on LineSearch
15 
16    Input Parameters:
17 .  comm - MPI communicator for the line search
18 
19    Output Parameters:
20 .  outlinesearch - the line search instance.
21 
22    Level: Beginner
23 
24    .keywords: LineSearch, Create
25 
26    .seealso: LineSearchDestroy()
27 @*/
28 
29 PetscErrorCode LineSearchCreate(MPI_Comm comm, LineSearch * outlinesearch) {
30   PetscErrorCode ierr;
31   LineSearch     linesearch;
32   PetscFunctionBegin;
33   ierr = PetscHeaderCreate(linesearch, _p_LineSearch,struct _LineSearchOps,LineSearch_CLASSID, 0,
34                            "LineSearch","Line-search method","LineSearch",comm,LineSearchDestroy,LineSearchView);CHKERRQ(ierr);
35 
36   linesearch->ops->precheckstep = PETSC_NULL;
37   linesearch->ops->postcheckstep = PETSC_NULL;
38 
39   linesearch->lambda        = 1.0;
40   linesearch->fnorm         = 1.0;
41   linesearch->ynorm         = 1.0;
42   linesearch->xnorm         = 1.0;
43   linesearch->success       = PETSC_TRUE;
44   linesearch->norms         = PETSC_TRUE;
45   linesearch->keeplambda    = PETSC_FALSE;
46   linesearch->damping       = 1.0;
47   linesearch->maxstep       = 1e8;
48   linesearch->steptol       = 1e-12;
49   linesearch->rtol          = 1e-8;
50   linesearch->atol          = 1e-15;
51   linesearch->ltol          = 1e-8;
52   linesearch->precheckctx   = PETSC_NULL;
53   linesearch->postcheckctx  = PETSC_NULL;
54   linesearch->max_its       = 3;
55   linesearch->setupcalled   = PETSC_FALSE;
56   *outlinesearch            = linesearch;
57   PetscFunctionReturn(0);
58 }
59 
60 #undef __FUNCT__
61 #define __FUNCT__ "LineSearchSetUp"
62 /*@
63    LineSearchSetUp - Prepares the line search for being applied.
64 
65    Collective on LineSearch
66 
67    Input Parameters:
68 .  linesearch - The LineSearch instance.
69 
70    Level: Intermediate
71 
72    .keywords: LineSearch, SetUp
73 
74    .seealso: LineSearchReset()
75 @*/
76 
77 PetscErrorCode LineSearchSetUp(LineSearch linesearch) {
78   PetscErrorCode ierr;
79   PetscFunctionBegin;
80 
81   if (!((PetscObject)linesearch)->type_name) {
82     ierr = LineSearchSetType(linesearch,LINESEARCHBASIC);CHKERRQ(ierr);
83   }
84 
85   if (!linesearch->setupcalled) {
86     ierr = VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);CHKERRQ(ierr);
87     ierr = VecDuplicate(linesearch->vec_func, &linesearch->vec_func_new);CHKERRQ(ierr);
88     if (linesearch->ops->setup) {
89       ierr = (*linesearch->ops->setup)(linesearch);CHKERRQ(ierr);
90     }
91     linesearch->lambda = linesearch->damping;
92     linesearch->setupcalled = PETSC_TRUE;
93   }
94   PetscFunctionReturn(0);
95 }
96 
97 #undef __FUNCT__
98 #define __FUNCT__ "LineSearchReset"
99 
100 /*@
101    LineSearchReset - Tears down the structures required for application
102 
103    Collective on LineSearch
104 
105    Input Parameters:
106 .  linesearch - The LineSearch instance.
107 
108    Level: Intermediate
109 
110    .keywords: LineSearch, Create
111 
112    .seealso: LineSearchSetUp()
113 @*/
114 
115 PetscErrorCode LineSearchReset(LineSearch linesearch) {
116   PetscErrorCode ierr;
117   PetscFunctionBegin;
118   if (linesearch->ops->reset) {
119     (*linesearch->ops->reset)(linesearch);
120   }
121   ierr = VecDestroy(&linesearch->vec_sol_new);CHKERRQ(ierr);
122   ierr = VecDestroy(&linesearch->vec_func_new);CHKERRQ(ierr);
123 
124   ierr = VecDestroyVecs(linesearch->nwork, &linesearch->work);CHKERRQ(ierr);
125   linesearch->nwork = 0;
126   linesearch->setupcalled = PETSC_FALSE;
127   PetscFunctionReturn(0);
128 }
129 
130 #undef __FUNCT__
131 #define __FUNCT__ "LineSearchPreCheck"
132 /*@
133    LineSearchPreCheck - Prepares the line search for being applied.
134 
135    Collective on LineSearch
136 
137    Input Parameters:
138 .  linesearch - The linesearch instance.
139 
140    Output Parameters:
141 .  changed - Indicator if the pre-check has changed anything.
142 
143    Level: Beginner
144 
145    .keywords: LineSearch, Create
146 
147    .seealso: LineSearchPostCheck()
148 @*/
149 PetscErrorCode LineSearchPreCheck(LineSearch linesearch, PetscBool * changed)
150 {
151   PetscErrorCode ierr;
152   PetscFunctionBegin;
153   *changed = PETSC_FALSE;
154   if (linesearch->ops->precheckstep) {
155     ierr = (*linesearch->ops->precheckstep)(linesearch, linesearch->vec_sol, linesearch->vec_update, changed);CHKERRQ(ierr);
156   }
157   PetscFunctionReturn(0);
158 }
159 
160 #undef __FUNCT__
161 #define __FUNCT__ "LineSearchPostCheck"
162 /*@
163    LineSearchPostCheck - Prepares the line search for being applied.
164 
165    Collective on LineSearch
166 
167    Input Parameters:
168 .  linesearch - The linesearch instance.
169 
170    Output Parameters:
171 +  changed_W - Indicator if the solution has been changed.
172 -  changed_Y - Indicator if the direction has been changed.
173 
174    Level: Intermediate
175 
176    .keywords: LineSearch, Create
177 
178    .seealso: LineSearchPreCheck()
179 @*/
180 PetscErrorCode LineSearchPostCheck(LineSearch linesearch, PetscBool * changed_W, PetscBool * changed_Y)
181 {
182   PetscErrorCode ierr;
183   PetscFunctionBegin;
184   *changed_Y = PETSC_FALSE;
185   *changed_W = PETSC_FALSE;
186   if (linesearch->ops->postcheckstep) {
187     ierr = (*linesearch->ops->postcheckstep)(linesearch, linesearch->vec_sol, linesearch->vec_sol_new, linesearch->vec_update, changed_W, changed_Y);CHKERRQ(ierr);
188   }
189   PetscFunctionReturn(0);
190 }
191 
192 #undef __FUNCT__
193 #define __FUNCT__ "LineSearchApply"
194 /*@
195    LineSearchApply - Computes the line-search update
196 
197    Collective on LineSearch
198 
199    Input Parameters:
200 +  linesearch - The linesearch instance.
201 .  X - The current solution.
202 .  F - The current function.
203 .  fnorm - The current norm.
204 .  Y - The search direction.
205 
206    Output Parameters:
207 +  X - The new solution.
208 .  F - The new function.
209 -  fnorm - The new function norm.
210 
211    Level: Intermediate
212 
213    .keywords: LineSearch, Create
214 
215    .seealso: LineSearchCreate(), LineSearchPreCheck(), LineSearchPostCheck()
216 @*/
217 PetscErrorCode LineSearchApply(LineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y) {
218   PetscErrorCode ierr;
219   PetscFunctionBegin;
220 
221   /* check the pointers */
222   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
223   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
224   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
225   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
226 
227   linesearch->success = PETSC_TRUE;
228 
229   linesearch->vec_sol = X;
230   linesearch->vec_update = Y;
231   linesearch->vec_func = F;
232 
233   ierr = LineSearchSetUp(linesearch);CHKERRQ(ierr);
234 
235   if (!linesearch->keeplambda)
236     linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */
237 
238   if (fnorm) {
239     linesearch->fnorm = *fnorm;
240   } else {
241     ierr = VecNorm(F, NORM_2, &linesearch->fnorm);CHKERRQ(ierr);
242   }
243 
244   ierr = PetscLogEventBegin(LineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr);
245 
246   ierr = (*linesearch->ops->apply)(linesearch);CHKERRQ(ierr);
247 
248   ierr = PetscLogEventEnd(LineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr);
249 
250   if (fnorm)
251     *fnorm = linesearch->fnorm;
252   PetscFunctionReturn(0);
253 }
254 
255 #undef __FUNCT__
256 #define __FUNCT__ "LineSearchDestroy"
257 /*@
258    LineSearchDestroy - Destroys the line search instance.
259 
260    Collective on LineSearch
261 
262    Input Parameters:
263 .  linesearch - The linesearch instance.
264 
265    Level: Intermediate
266 
267    .keywords: LineSearch, Create
268 
269    .seealso: LineSearchCreate(), LineSearchReset()
270 @*/
271 PetscErrorCode LineSearchDestroy(LineSearch * linesearch) {
272   PetscErrorCode ierr;
273   PetscFunctionBegin;
274   if (!*linesearch) PetscFunctionReturn(0);
275   PetscValidHeaderSpecific((*linesearch),LineSearch_CLASSID,1);
276   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = 0; PetscFunctionReturn(0);}
277   ierr = PetscObjectDepublish((*linesearch));CHKERRQ(ierr);
278   ierr = LineSearchReset(*linesearch);
279   if ((*linesearch)->ops->destroy) {
280     (*linesearch)->ops->destroy(*linesearch);
281   }
282   ierr = PetscViewerDestroy(&(*linesearch)->monitor);CHKERRQ(ierr);
283   ierr = PetscHeaderDestroy(linesearch);CHKERRQ(ierr);
284   PetscFunctionReturn(0);
285 }
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "LineSearchSetMonitor"
289 /*@
290    LineSearchSetMonitor - Turns on/off printing useful things about the line search.
291 
292    Input Parameters:
293 +  snes - nonlinear context obtained from SNESCreate()
294 -  flg - PETSC_TRUE to monitor the line search
295 
296    Logically Collective on SNES
297 
298    Options Database:
299 .   -linesearch_monitor - enables the monitor.
300 
301    Level: intermediate
302 
303 
304 .seealso: LineSearchGetMonitor()
305 @*/
306 PetscErrorCode  LineSearchSetMonitor(LineSearch linesearch, PetscBool flg)
307 {
308 
309   PetscErrorCode ierr;
310   PetscFunctionBegin;
311   if (flg && !linesearch->monitor) {
312     ierr = PetscViewerASCIIOpen(((PetscObject)linesearch)->comm,"stdout",&linesearch->monitor);CHKERRQ(ierr);
313   } else if (!flg && linesearch->monitor) {
314     ierr = PetscViewerDestroy(&linesearch->monitor);CHKERRQ(ierr);
315   }
316   PetscFunctionReturn(0);
317 }
318 
319 #undef __FUNCT__
320 #define __FUNCT__ "LineSearchGetMonitor"
321 /*@
322    LineSearchGetMonitor - Gets the monitor instance for the line search
323 
324    Input Parameters:
325 .  linesearch - linesearch context.
326 
327    Input Parameters:
328 .  monitor - monitor context.
329 
330    Logically Collective on SNES
331 
332 
333    Options Database Keys:
334 .   -linesearch_monitor - enables the monitor.
335 
336    Level: intermediate
337 
338 
339 .seealso: LineSearchSetMonitor()
340 @*/
341 PetscErrorCode  LineSearchGetMonitor(LineSearch linesearch, PetscViewer *monitor)
342 {
343 
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
346   if (monitor) {
347     PetscValidPointer(monitor, 2);
348     *monitor = linesearch->monitor;
349   }
350   PetscFunctionReturn(0);
351 }
352 
353 #undef __FUNCT__
354 #define __FUNCT__ "LineSearchSetFromOptions"
355 /*@
356    LineSearchSetFromOptions - Sets options for the line search
357 
358    Input Parameters:
359 .  linesearch - linesearch context.
360 
361    Options Database Keys:
362 + -linesearch_type - The Line search method
363 . -linesearch_monitor - Print progress of line searches
364 . -linesearch_damping - The linesearch damping parameter.
365 . -linesearch_norms   - Turn on/off the linesearch norms
366 . -linesearch_keeplambda - Keep the previous search length as the initial guess.
367 - -linesearch_max_it - The number of iterations for iterative line searches.
368 
369    Logically Collective on LineSearch
370 
371    Level: intermediate
372 
373 
374 .seealso: LineSearchCreate()
375 @*/
376 PetscErrorCode LineSearchSetFromOptions(LineSearch linesearch) {
377   PetscErrorCode ierr;
378   const char     *deft = LINESEARCHBASIC;
379   char           type[256];
380   PetscBool      flg, set;
381   PetscFunctionBegin;
382   if (!LineSearchRegisterAllCalled) {ierr = LineSearchRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
383 
384   ierr = PetscObjectOptionsBegin((PetscObject)linesearch);CHKERRQ(ierr);
385   if (((PetscObject)linesearch)->type_name) {
386     deft = ((PetscObject)linesearch)->type_name;
387   }
388   ierr = PetscOptionsList("-linesearch_type","Line-search method","LineSearchSetType",LineSearchList,deft,type,256,&flg);CHKERRQ(ierr);
389   if (flg) {
390     ierr = LineSearchSetType(linesearch,type);CHKERRQ(ierr);
391   } else if (!((PetscObject)linesearch)->type_name) {
392     ierr = LineSearchSetType(linesearch,deft);CHKERRQ(ierr);
393   }
394   if (linesearch->ops->setfromoptions) {
395     (*linesearch->ops->setfromoptions)(linesearch);CHKERRQ(ierr);
396   }
397 
398   ierr = PetscOptionsBool("-linesearch_monitor","Print progress of line searches","SNESLineSearchSetMonitor",
399                           linesearch->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
400   if (set) {ierr = LineSearchSetMonitor(linesearch,flg);CHKERRQ(ierr);}
401 
402   ierr = PetscOptionsReal("-linesearch_damping","Line search damping and initial step guess","LineSearchSetDamping",linesearch->damping,&linesearch->damping,0);CHKERRQ(ierr);
403   ierr = PetscOptionsReal("-linesearch_rtol","Tolerance for iterative line search","LineSearchSetRTolerance",linesearch->rtol,&linesearch->rtol,0);CHKERRQ(ierr);
404   ierr = PetscOptionsBool("-linesearch_norms","Compute final norms in line search","LineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,0);CHKERRQ(ierr);
405   ierr = PetscOptionsBool("-linesearch_keeplambda","Use previous lambda as damping","LineSearchSetKeepLambda",linesearch->keeplambda,&linesearch->keeplambda,0);CHKERRQ(ierr);
406   ierr = PetscOptionsInt("-linesearch_max_it","Maximum iterations for iterative line searches","",linesearch->max_its,&linesearch->max_its,0);CHKERRQ(ierr);
407   ierr = PetscObjectProcessOptionsHandlers((PetscObject)linesearch);CHKERRQ(ierr);
408   ierr = PetscOptionsEnd();CHKERRQ(ierr);
409   PetscFunctionReturn(0);
410 }
411 
412 #undef __FUNCT__
413 #define __FUNCT__ "LineSearchView"
414 /*@
415    LineSearchView - Views useful information for the line search.
416 
417    Input Parameters:
418 .  linesearch - linesearch context.
419 
420    Logically Collective on LineSearch
421 
422    Level: intermediate
423 
424 
425 .seealso: LineSearchCreate()
426 @*/
427 PetscErrorCode LineSearchView(LineSearch linesearch) {
428   PetscFunctionBegin;
429 
430   PetscFunctionReturn(0);
431 }
432 
433 #undef __FUNCT__
434 #define __FUNCT__ "LineSearchSetType"
435 /*@
436    LineSearchSetType - Sets the linesearch type
437 
438    Input Parameters:
439 +  linesearch - linesearch context.
440 -  type - The type of line search to be used
441 
442    Logically Collective on LineSearch
443 
444    Level: intermediate
445 
446 
447 .seealso: LineSearchCreate()
448 @*/
449 PetscErrorCode LineSearchSetType(LineSearch linesearch, const LineSearchType type)
450 {
451 
452   PetscErrorCode ierr,(*r)(LineSearch);
453   PetscBool      match;
454 
455   PetscFunctionBegin;
456   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
457   PetscValidCharPointer(type,2);
458 
459   ierr = PetscTypeCompare((PetscObject)linesearch,type,&match);CHKERRQ(ierr);
460   if (match) PetscFunctionReturn(0);
461 
462   ierr =  PetscFListFind(LineSearchList,((PetscObject)linesearch)->comm,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr);
463   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type);
464   /* Destroy the previous private linesearch context */
465   if (linesearch->ops->destroy) {
466     ierr = (*(linesearch)->ops->destroy)(linesearch);CHKERRQ(ierr);
467     linesearch->ops->destroy = PETSC_NULL;
468   }
469   /* Reinitialize function pointers in LineSearchOps structure */
470   linesearch->ops->apply          = 0;
471   linesearch->ops->view           = 0;
472   linesearch->ops->setfromoptions = 0;
473   linesearch->ops->destroy        = 0;
474 
475   ierr = PetscObjectChangeTypeName((PetscObject)linesearch,type);CHKERRQ(ierr);
476   ierr = (*r)(linesearch);CHKERRQ(ierr);
477 #if defined(PETSC_HAVE_AMS)
478   if (PetscAMSPublishAll) {
479     ierr = PetscObjectAMSPublish((PetscObject)linesearch);CHKERRQ(ierr);
480   }
481 #endif
482   PetscFunctionReturn(0);
483 }
484 
485 #undef __FUNCT__
486 #define __FUNCT__ "LineSearchSetSNES"
487 /*@
488    LineSearchSetSNES - Sets the SNES for the linesearch for function evaluation
489 
490    Input Parameters:
491 +  linesearch - linesearch context.
492 -  snes - The snes instance
493 
494    Level: intermediate
495 
496 
497 .seealso: LineSearchGetSNES(), LineSearchSetVecs()
498 @*/
499 PetscErrorCode  LineSearchSetSNES(LineSearch linesearch, SNES snes){
500   PetscFunctionBegin;
501   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
502   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
503   linesearch->snes = snes;
504   PetscFunctionReturn(0);
505 }
506 
507 #undef __FUNCT__
508 #define __FUNCT__ "LineSearchGetSNES"
509 /*@
510    LineSearchGetSNES - Gets the SNES for the linesearch for function evaluation
511 
512    Input Parameters:
513 .  linesearch - linesearch context.
514 
515    Output Parameters:
516 .  snes - The snes instance
517 
518    Level: intermediate
519 
520 .seealso: LineSearchGetSNES(), LineSearchSetVecs()
521 @*/
522 PetscErrorCode  LineSearchGetSNES(LineSearch linesearch, SNES *snes){
523   PetscFunctionBegin;
524   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
525   PetscValidPointer(snes, 2);
526   *snes = linesearch->snes;
527   PetscFunctionReturn(0);
528 }
529 
530 #undef __FUNCT__
531 #define __FUNCT__ "LineSearchGetLambda"
532 /*@
533    LineSearchGetLambda - Gets the last linesearch steplength discovered.
534 
535    Input Parameters:
536 .  linesearch - linesearch context.
537 
538    Output Parameters:
539 .  lambda - The last steplength.
540 
541    Level: intermediate
542 
543 .seealso: LineSearchGetSNES(), LineSearchSetVecs()
544 @*/
545 PetscErrorCode  LineSearchGetLambda(LineSearch linesearch,PetscReal *lambda)
546 {
547   PetscFunctionBegin;
548   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
549   PetscValidPointer(lambda, 2);
550   *lambda = linesearch->lambda;
551   PetscFunctionReturn(0);
552 }
553 
554 #undef __FUNCT__
555 #define __FUNCT__ "LineSearchSetLambda"
556 /*@
557    LineSearchSetLambda - Sets the linesearch steplength.
558 
559    Input Parameters:
560 +  linesearch - linesearch context.
561 -  lambda - The last steplength.
562 
563    Level: intermediate
564 
565 .seealso: LineSearchGetLambda()
566 @*/
567 PetscErrorCode  LineSearchSetLambda(LineSearch linesearch, PetscReal lambda)
568 {
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
571   linesearch->lambda = lambda;
572   PetscFunctionReturn(0);
573 }
574 
575 #undef  __FUNCT__
576 #define __FUNCT__ "LineSearchGetTolerances"
577 /*@
578    LineSearchGetTolerances - Gets the tolerances for the method
579 
580    Input Parameters:
581 .  linesearch - linesearch context.
582 
583    Output Parameters:
584 +  steptol - The minimum steplength
585 .  rtol    - The relative tolerance for iterative line searches
586 .  atol    - The absolute tolerance for iterative line searches
587 .  ltol    - The change in lambda tolerance for iterative line searches
588 -  max_it  - The maximum number of iterations of the line search
589 
590 
591    Level: advanced
592 
593 .seealso: LineSearchSetTolerances()
594 @*/
595 PetscErrorCode  LineSearchGetTolerances(LineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
596 {
597   PetscFunctionBegin;
598   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
599   if (steptol) {
600     PetscValidPointer(steptol, 2);
601     *steptol = linesearch->steptol;
602   }
603   if (maxstep) {
604     PetscValidPointer(maxstep, 3);
605     *maxstep = linesearch->maxstep;
606   }
607   if (rtol) {
608     PetscValidPointer(rtol, 4);
609     *rtol = linesearch->rtol;
610   }
611   if (atol) {
612     PetscValidPointer(atol, 5);
613     *atol = linesearch->atol;
614   }
615   if (ltol) {
616     PetscValidPointer(ltol, 6);
617     *ltol = linesearch->ltol;
618   }
619   if (max_its) {
620     PetscValidPointer(max_its, 7);
621     *max_its = linesearch->max_its;
622   }
623   PetscFunctionReturn(0);
624 }
625 
626 #undef  __FUNCT__
627 #define __FUNCT__ "LineSearchSetTolerances"
628 /*@
629    LineSearchSetTolerances - Sets the tolerances for the method
630 
631    Input Parameters:
632 +  linesearch - linesearch context.
633 .  steptol - The minimum steplength
634 .  rtol    - The relative tolerance for iterative line searches
635 .  atol    - The absolute tolerance for iterative line searches
636 .  ltol    - The change in lambda tolerance for iterative line searches
637 -  max_it  - The maximum number of iterations of the line search
638 
639 
640    Level: advanced
641 
642 .seealso: LineSearchGetTolerances()
643 @*/
644 PetscErrorCode  LineSearchSetTolerances(LineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
645 {
646   PetscFunctionBegin;
647   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
648   linesearch->steptol = steptol;
649   linesearch->maxstep = maxstep;
650   linesearch->rtol = rtol;
651   linesearch->atol = atol;
652   linesearch->ltol = ltol;
653   linesearch->max_its = max_its;
654   PetscFunctionReturn(0);
655 }
656 
657 
658 #undef __FUNCT__
659 #define __FUNCT__ "LineSearchGetDamping"
660 /*@
661    LineSearchGetDamping - Gets the line search damping parameter.
662 
663    Input Parameters:
664 .  linesearch - linesearch context.
665 
666    Output Parameters:
667 .  damping - The damping parameter.
668 
669    Level: intermediate
670 
671 .seealso: LineSearchGetStepTolerance()
672 @*/
673 
674 PetscErrorCode  LineSearchGetDamping(LineSearch linesearch,PetscReal *damping)
675 {
676   PetscFunctionBegin;
677   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
678   PetscValidPointer(damping, 2);
679   *damping = linesearch->damping;
680   PetscFunctionReturn(0);
681 }
682 
683 #undef __FUNCT__
684 #define __FUNCT__ "LineSearchSetDamping"
685 /*@
686    LineSearchSetDamping - Sets the line search damping paramter.
687 
688    Input Parameters:
689 .  linesearch - linesearch context.
690 .  damping - The damping parameter.
691 
692    Level: intermediate
693 
694 .seealso: LineSearchGetDamping()
695 @*/
696 PetscErrorCode  LineSearchSetDamping(LineSearch linesearch,PetscReal damping)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
700   linesearch->damping = damping;
701   PetscFunctionReturn(0);
702 }
703 
704 #undef __FUNCT__
705 #define __FUNCT__ "LineSearchGetNorms"
706 /*@
707    LineSearchGetNorms - Gets the norms for for X, Y, and F.
708 
709    Input Parameters:
710 .  linesearch - linesearch context.
711 
712    Output Parameters:
713 +  xnorm - The norm of the current solution
714 .  fnorm - The norm of the current function
715 -  ynorm - The norm of the current update
716 
717    Level: intermediate
718 
719 .seealso: LineSearchSetNorms() LineSearchGetVecs()
720 @*/
721 PetscErrorCode  LineSearchGetNorms(LineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
722 {
723   PetscFunctionBegin;
724   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
725   if (xnorm) {
726     *xnorm = linesearch->xnorm;
727   }
728   if (fnorm) {
729     *fnorm = linesearch->fnorm;
730   }
731   if (ynorm) {
732     *ynorm = linesearch->ynorm;
733   }
734   PetscFunctionReturn(0);
735 }
736 
737 #undef __FUNCT__
738 #define __FUNCT__ "LineSearchSetNorms"
739 /*@
740    LineSearchSetNorms - Gets the computed norms for for X, Y, and F.
741 
742    Input Parameters:
743 +  linesearch - linesearch context.
744 .  xnorm - The norm of the current solution
745 .  fnorm - The norm of the current function
746 -  ynorm - The norm of the current update
747 
748    Level: intermediate
749 
750 .seealso: LineSearchGetNorms(), LineSearchSetVecs()
751 @*/
752 PetscErrorCode  LineSearchSetNorms(LineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
753 {
754   PetscFunctionBegin;
755   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
756   if (xnorm) {
757     linesearch->xnorm = xnorm;
758   }
759   if (fnorm) {
760     linesearch->fnorm = fnorm;
761   }
762   if (ynorm) {
763     linesearch->ynorm = ynorm;
764   }
765   PetscFunctionReturn(0);
766 }
767 
768 #undef __FUNCT__
769 #define __FUNCT__ "LineSearchComputeNorms"
770 /*@
771    LineSearchComputeNorms - Computes the norms of X, F, and Y.
772 
773    Input Parameters:
774 .  linesearch - linesearch context.
775 
776    Options Database Keys:
777 .   -linesearch_norms - turn norm computation on or off.
778 
779    Level: intermediate
780 
781 .seealso: LineSearchGetNorms, LineSearchSetNorms()
782 @*/
783 PetscErrorCode LineSearchComputeNorms(LineSearch linesearch)
784 {
785   PetscErrorCode ierr;
786   PetscFunctionBegin;
787   if (linesearch->norms) {
788     ierr = VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm);CHKERRQ(ierr);
789     ierr = VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm);CHKERRQ(ierr);
790     ierr = VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);CHKERRQ(ierr);
791     ierr = VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm);CHKERRQ(ierr);
792     ierr = VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm);CHKERRQ(ierr);
793     ierr = VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm);CHKERRQ(ierr);
794   }
795   PetscFunctionReturn(0);
796 }
797 
798 #undef __FUNCT__
799 #define __FUNCT__ "LineSearchGetVecs"
800 /*@
801    LineSearchGetVecs - Gets the vectors from the LineSearch context
802 
803    Input Parameters:
804 .  linesearch - linesearch context.
805 
806    Output Parameters:
807 +  X - The old solution
808 .  F - The old function
809 .  Y - The search direction
810 .  W - The new solution
811 -  G - The new function
812 
813    Level: intermediate
814 
815 .seealso: LineSearchGetNorms(), LineSearchSetVecs()
816 @*/
817 PetscErrorCode LineSearchGetVecs(LineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G) {
818   PetscFunctionBegin;
819   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
820   if (X) {
821     PetscValidPointer(X, 2);
822     *X = linesearch->vec_sol;
823   }
824   if (F) {
825     PetscValidPointer(F, 3);
826     *F = linesearch->vec_func;
827   }
828   if (Y) {
829     PetscValidPointer(Y, 4);
830     *Y = linesearch->vec_update;
831   }
832   if (W) {
833     PetscValidPointer(W, 5);
834     *W = linesearch->vec_sol_new;
835   }
836   if (G) {
837     PetscValidPointer(G, 6);
838     *G = linesearch->vec_func_new;
839   }
840 
841   PetscFunctionReturn(0);
842 }
843 
844 #undef __FUNCT__
845 #define __FUNCT__ "LineSearchSetVecs"
846 /*@
847    LineSearchSetVecs - Sets the vectors on the LineSearch context
848 
849    Input Parameters:
850 +  linesearch - linesearch context.
851 .  X - The old solution
852 .  F - The old function
853 .  Y - The search direction
854 .  W - The new solution
855 -  G - The new function
856 
857    Level: intermediate
858 
859 .seealso: LineSearchSetNorms(), LineSearchGetVecs()
860 @*/
861 PetscErrorCode LineSearchSetVecs(LineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G) {
862   PetscFunctionBegin;
863   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
864   if (X) {
865     PetscValidHeaderSpecific(X,VEC_CLASSID,2);
866     linesearch->vec_sol = X;
867   }
868   if (F) {
869     PetscValidHeaderSpecific(F,VEC_CLASSID,3);
870     linesearch->vec_func = F;
871   }
872   if (Y) {
873     PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
874     linesearch->vec_update = Y;
875   }
876   if (W) {
877     PetscValidHeaderSpecific(W,VEC_CLASSID,5);
878     linesearch->vec_sol_new = W;
879   }
880   if (G) {
881     PetscValidHeaderSpecific(G,VEC_CLASSID,6);
882     linesearch->vec_func_new = G;
883   }
884 
885   PetscFunctionReturn(0);
886 }
887 
888 #undef __FUNCT__
889 #define __FUNCT__ "LineSearchAppendOptionsPrefix"
890 /*@C
891    LineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
892    SNES options in the database.
893 
894    Logically Collective on SNES
895 
896    Input Parameters:
897 +  snes - the SNES context
898 -  prefix - the prefix to prepend to all option names
899 
900    Notes:
901    A hyphen (-) must NOT be given at the beginning of the prefix name.
902    The first character of all runtime options is AUTOMATICALLY the hyphen.
903 
904    Level: advanced
905 
906 .keywords: LineSearch, append, options, prefix, database
907 
908 .seealso: SNESGetOptionsPrefix()
909 @*/
910 PetscErrorCode  LineSearchAppendOptionsPrefix(LineSearch linesearch,const char prefix[])
911 {
912   PetscErrorCode ierr;
913 
914   PetscFunctionBegin;
915   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
916   ierr = PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr);
917   PetscFunctionReturn(0);
918 }
919 
920 #undef __FUNCT__
921 #define __FUNCT__ "LineSearchGetOptionsPrefix"
922 /*@C
923    LineSearchGetOptionsPrefix - Sets the prefix used for searching for all
924    LineSearch options in the database.
925 
926    Not Collective
927 
928    Input Parameter:
929 .  snes - the SNES context
930 
931    Output Parameter:
932 .  prefix - pointer to the prefix string used
933 
934    Notes: On the fortran side, the user should pass in a string 'prefix' of
935    sufficient length to hold the prefix.
936 
937    Level: advanced
938 
939 .keywords: LineSearch, get, options, prefix, database
940 
941 .seealso: SNESAppendOptionsPrefix()
942 @*/
943 PetscErrorCode  LineSearchGetOptionsPrefix(LineSearch linesearch,const char *prefix[])
944 {
945   PetscErrorCode ierr;
946 
947   PetscFunctionBegin;
948   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
949   ierr = PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr);
950   PetscFunctionReturn(0);
951 }
952 
953 #undef __FUNCT__
954 #define __FUNCT__ "LineSearchGetWork"
955 /*@
956    LineSearchGetWork - Gets work vectors for the line search.
957 
958    Input Parameter:
959 +  linesearch - the LineSearch context
960 -  nwork - the number of work vectors
961 
962    Level: developer
963 
964 .keywords: LineSearch, work, vector
965 
966 .seealso: SNESDefaultGetWork()
967 @*/
968 PetscErrorCode  LineSearchGetWork(LineSearch linesearch, PetscInt nwork)
969 {
970   PetscErrorCode ierr;
971   PetscFunctionBegin;
972   if (linesearch->vec_sol) {
973     ierr = VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);CHKERRQ(ierr);
974   } else {
975     SETERRQ(((PetscObject)linesearch)->comm, PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
976   }
977   PetscFunctionReturn(0);
978 }
979 
980 
981 #undef __FUNCT__
982 #define __FUNCT__ "LineSearchGetSuccess"
983 /*@
984    LineSearchGetSuccess - Gets the success/failure status of the last line search application
985 
986    Input Parameters:
987 .  linesearch - linesearch context.
988 
989    Output Parameters:
990 .  success - The success or failure status.
991 
992    Level: intermediate
993 
994 .seealso: LineSearchSetSuccess()
995 @*/
996 PetscErrorCode  LineSearchGetSuccess(LineSearch linesearch, PetscBool *success)
997 {
998   PetscFunctionBegin;
999   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
1000   PetscValidPointer(success, 2);
1001   if (success) {
1002     *success = linesearch->success;
1003   }
1004   PetscFunctionReturn(0);
1005 }
1006 
1007 #undef __FUNCT__
1008 #define __FUNCT__ "LineSearchSetSuccess"
1009 /*@
1010    LineSearchSetSuccess - Sets the success/failure status of the last line search application
1011 
1012    Input Parameters:
1013 +  linesearch - linesearch context.
1014 -  success - The success or failure status.
1015 
1016    Level: intermediate
1017 
1018 .seealso: LineSearchGetSuccess()
1019 @*/
1020 PetscErrorCode  LineSearchSetSuccess(LineSearch linesearch, PetscBool success)
1021 {
1022   PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1);
1023   PetscFunctionBegin;
1024   linesearch->success = success;
1025   PetscFunctionReturn(0);
1026 }
1027 
1028 #undef __FUNCT__
1029 #define __FUNCT__ "LineSearchRegister"
1030 /*@C
1031   LineSearchRegister - See LineSearchRegisterDynamic()
1032 
1033   Level: advanced
1034 @*/
1035 PetscErrorCode  LineSearchRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(LineSearch))
1036 {
1037   char           fullname[PETSC_MAX_PATH_LEN];
1038   PetscErrorCode ierr;
1039 
1040   PetscFunctionBegin;
1041   ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr);
1042   ierr = PetscFListAdd(&LineSearchList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
1043   PetscFunctionReturn(0);
1044 }
1045