xref: /petsc/src/tao/linesearch/interface/taolinesearch.c (revision ccb4e88a40f0b86eaeca07ff64c64e4de2fae686)
1 #include <petsctaolinesearch.h> /*I "petsctaolinesearch.h" I*/
2 #include <petsc/private/taolinesearchimpl.h>
3 
4 PetscFunctionList TaoLineSearchList = NULL;
5 
6 PetscClassId TAOLINESEARCH_CLASSID=0;
7 
8 PetscLogEvent TAOLINESEARCH_Apply;
9 PetscLogEvent TAOLINESEARCH_Eval;
10 
11 /*@C
12    TaoLineSearchViewFromOptions - View from Options
13 
14    Collective on TaoLineSearch
15 
16    Input Parameters:
17 +  A - the Tao context
18 .  obj - Optional object
19 -  name - command line option
20 
21    Level: intermediate
22 .seealso:  TaoLineSearch, TaoLineSearchView, PetscObjectViewFromOptions(), TaoLineSearchCreate()
23 @*/
24 PetscErrorCode  TaoLineSearchViewFromOptions(TaoLineSearch A,PetscObject obj,const char name[])
25 {
26   PetscErrorCode ierr;
27 
28   PetscFunctionBegin;
29   PetscValidHeaderSpecific(A,TAOLINESEARCH_CLASSID,1);
30   ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr);
31   PetscFunctionReturn(0);
32 }
33 
34 /*@C
35   TaoLineSearchView - Prints information about the TaoLineSearch
36 
37   Collective on TaoLineSearch
38 
39   InputParameters:
40 + ls - the Tao context
41 - viewer - visualization context
42 
43   Options Database Key:
44 . -tao_ls_view - Calls TaoLineSearchView() at the end of each line search
45 
46   Notes:
47   The available visualization contexts include
48 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
49 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
50          output where only the first processor opens
51          the file.  All other processors send their
52          data to the first processor to print.
53 
54   Level: beginner
55 
56 .seealso: PetscViewerASCIIOpen()
57 @*/
58 
59 PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
60 {
61   PetscErrorCode          ierr;
62   PetscBool               isascii, isstring;
63   TaoLineSearchType       type;
64 
65   PetscFunctionBegin;
66   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
67   if (!viewer) {
68     ierr = PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer);CHKERRQ(ierr);
69   }
70   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
71   PetscCheckSameComm(ls,1,viewer,2);
72 
73   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
74   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
75   if (isascii) {
76     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ls, viewer);CHKERRQ(ierr);
77     if (ls->ops->view) {
78       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
79       ierr = (*ls->ops->view)(ls,viewer);CHKERRQ(ierr);
80       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
81     }
82     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
83     ierr = PetscViewerASCIIPrintf(viewer,"maximum function evaluations=%D\n",ls->max_funcs);CHKERRQ(ierr);
84     ierr = PetscViewerASCIIPrintf(viewer,"tolerances: ftol=%g, rtol=%g, gtol=%g\n",(double)ls->ftol,(double)ls->rtol,(double)ls->gtol);CHKERRQ(ierr);
85     ierr = PetscViewerASCIIPrintf(viewer,"total number of function evaluations=%D\n",ls->nfeval);CHKERRQ(ierr);
86     ierr = PetscViewerASCIIPrintf(viewer,"total number of gradient evaluations=%D\n",ls->ngeval);CHKERRQ(ierr);
87     ierr = PetscViewerASCIIPrintf(viewer,"total number of function/gradient evaluations=%D\n",ls->nfgeval);CHKERRQ(ierr);
88 
89     if (ls->bounded) {
90       ierr = PetscViewerASCIIPrintf(viewer,"using variable bounds\n");CHKERRQ(ierr);
91     }
92     ierr = PetscViewerASCIIPrintf(viewer,"Termination reason: %d\n",(int)ls->reason);CHKERRQ(ierr);
93     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
94   } else if (isstring) {
95     ierr = TaoLineSearchGetType(ls,&type);CHKERRQ(ierr);
96     ierr = PetscViewerStringSPrintf(viewer," %-3.3s",type);CHKERRQ(ierr);
97   }
98   PetscFunctionReturn(0);
99 }
100 
101 /*@C
102   TaoLineSearchCreate - Creates a TAO Line Search object.  Algorithms in TAO that use
103   line-searches will automatically create one.
104 
105   Collective
106 
107   Input Parameter:
108 . comm - MPI communicator
109 
110   Output Parameter:
111 . newls - the new TaoLineSearch context
112 
113   Available methods include:
114 + more-thuente
115 . gpcg
116 - unit - Do not perform any line search
117 
118    Options Database Keys:
119 .   -tao_ls_type - select which method TAO should use
120 
121    Level: beginner
122 
123 .seealso: TaoLineSearchSetType(), TaoLineSearchApply(), TaoLineSearchDestroy()
124 @*/
125 
126 PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
127 {
128   PetscErrorCode ierr;
129   TaoLineSearch  ls;
130 
131   PetscFunctionBegin;
132   PetscValidPointer(newls,2);
133   *newls = NULL;
134 
135   ierr = TaoLineSearchInitializePackage();CHKERRQ(ierr);
136 
137   ierr = PetscHeaderCreate(ls,TAOLINESEARCH_CLASSID,"TaoLineSearch","Linesearch","Tao",comm,TaoLineSearchDestroy,TaoLineSearchView);CHKERRQ(ierr);
138   ls->bounded = 0;
139   ls->max_funcs=30;
140   ls->ftol = 0.0001;
141   ls->gtol = 0.9;
142 #if defined(PETSC_USE_REAL_SINGLE)
143   ls->rtol = 1.0e-5;
144 #else
145   ls->rtol = 1.0e-10;
146 #endif
147   ls->stepmin=1.0e-20;
148   ls->stepmax=1.0e+20;
149   ls->step=1.0;
150   ls->nfeval=0;
151   ls->ngeval=0;
152   ls->nfgeval=0;
153 
154   ls->ops->computeobjective = NULL;
155   ls->ops->computegradient = NULL;
156   ls->ops->computeobjectiveandgradient = NULL;
157   ls->ops->computeobjectiveandgts = NULL;
158   ls->ops->setup = NULL;
159   ls->ops->apply = NULL;
160   ls->ops->view = NULL;
161   ls->ops->setfromoptions = NULL;
162   ls->ops->reset = NULL;
163   ls->ops->destroy = NULL;
164   ls->ops->monitor = NULL;
165   ls->usemonitor=PETSC_FALSE;
166   ls->setupcalled=PETSC_FALSE;
167   ls->usetaoroutines=PETSC_FALSE;
168   *newls = ls;
169   PetscFunctionReturn(0);
170 }
171 
172 /*@
173   TaoLineSearchSetUp - Sets up the internal data structures for the later use
174   of a Tao solver
175 
176   Collective on ls
177 
178   Input Parameters:
179 . ls - the TaoLineSearch context
180 
181   Notes:
182   The user will not need to explicitly call TaoLineSearchSetUp(), as it will
183   automatically be called in TaoLineSearchSolve().  However, if the user
184   desires to call it explicitly, it should come after TaoLineSearchCreate()
185   but before TaoLineSearchApply().
186 
187   Level: developer
188 
189 .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
190 @*/
191 
192 PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
193 {
194   PetscErrorCode ierr;
195   const char     *default_type=TAOLINESEARCHMT;
196   PetscBool      flg;
197 
198   PetscFunctionBegin;
199   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
200   if (ls->setupcalled) PetscFunctionReturn(0);
201   if (!((PetscObject)ls)->type_name) {
202     ierr = TaoLineSearchSetType(ls,default_type);CHKERRQ(ierr);
203   }
204   if (ls->ops->setup) {
205     ierr = (*ls->ops->setup)(ls);CHKERRQ(ierr);
206   }
207   if (ls->usetaoroutines) {
208     ierr = TaoIsObjectiveDefined(ls->tao,&flg);CHKERRQ(ierr);
209     ls->hasobjective = flg;
210     ierr = TaoIsGradientDefined(ls->tao,&flg);CHKERRQ(ierr);
211     ls->hasgradient = flg;
212     ierr = TaoIsObjectiveAndGradientDefined(ls->tao,&flg);CHKERRQ(ierr);
213     ls->hasobjectiveandgradient = flg;
214   } else {
215     if (ls->ops->computeobjective) {
216       ls->hasobjective = PETSC_TRUE;
217     } else {
218       ls->hasobjective = PETSC_FALSE;
219     }
220     if (ls->ops->computegradient) {
221       ls->hasgradient = PETSC_TRUE;
222     } else {
223       ls->hasgradient = PETSC_FALSE;
224     }
225     if (ls->ops->computeobjectiveandgradient) {
226       ls->hasobjectiveandgradient = PETSC_TRUE;
227     } else {
228       ls->hasobjectiveandgradient = PETSC_FALSE;
229     }
230   }
231   ls->setupcalled = PETSC_TRUE;
232   PetscFunctionReturn(0);
233 }
234 
235 /*@
236   TaoLineSearchReset - Some line searches may carry state information
237   from one TaoLineSearchApply() to the next.  This function resets this
238   state information.
239 
240   Collective on TaoLineSearch
241 
242   Input Parameter:
243 . ls - the TaoLineSearch context
244 
245   Level: developer
246 
247 .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
248 @*/
249 PetscErrorCode TaoLineSearchReset(TaoLineSearch ls)
250 {
251   PetscErrorCode ierr;
252 
253   PetscFunctionBegin;
254   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
255   if (ls->ops->reset) {
256     ierr = (*ls->ops->reset)(ls);CHKERRQ(ierr);
257   }
258   PetscFunctionReturn(0);
259 }
260 
261 /*@
262   TaoLineSearchDestroy - Destroys the TAO context that was created with
263   TaoLineSearchCreate()
264 
265   Collective on TaoLineSearch
266 
267   Input Parameter:
268 . ls - the TaoLineSearch context
269 
270   Level: beginner
271 
272 .seealse: TaoLineSearchCreate(), TaoLineSearchSolve()
273 @*/
274 PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
275 {
276   PetscErrorCode ierr;
277 
278   PetscFunctionBegin;
279   if (!*ls) PetscFunctionReturn(0);
280   PetscValidHeaderSpecific(*ls,TAOLINESEARCH_CLASSID,1);
281   if (--((PetscObject)*ls)->refct > 0) {*ls = NULL; PetscFunctionReturn(0);}
282   ierr = VecDestroy(&(*ls)->stepdirection);CHKERRQ(ierr);
283   ierr = VecDestroy(&(*ls)->start_x);CHKERRQ(ierr);
284   if ((*ls)->ops->destroy) {
285     ierr = (*(*ls)->ops->destroy)(*ls);CHKERRQ(ierr);
286   }
287   if ((*ls)->usemonitor) {
288     ierr = PetscViewerDestroy(&(*ls)->viewer);CHKERRQ(ierr);
289   }
290   ierr = PetscHeaderDestroy(ls);CHKERRQ(ierr);
291   PetscFunctionReturn(0);
292 }
293 
294 /*@
295   TaoLineSearchApply - Performs a line-search in a given step direction.  Criteria for acceptable step length depends on the line-search algorithm chosen
296 
297   Collective on TaoLineSearch
298 
299   Input Parameters:
300 + ls - the Tao context
301 - s - search direction
302 
303   Input/Output Parameters:
304 + x - The current solution (on output x contains the new solution determined by the line search)
305 . f - objective function value at current solution (on output contains the objective function value at new solution)
306 - g - gradient evaluated at x (on output contains the gradient at new solution)
307 
308   Output Parameters:
309 + steplength - scalar multiplier of s used ( x = x0 + steplength * x)
310 - reason - reason why the line-search stopped
311 
312   Notes:
313   reason will be set to one of:
314 
315 + TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
316 . TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
317 . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
318 . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
319 . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
320 . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
321 . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
322 . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
323 . TAOLINESEARCH_HALTED_OTHER - any other reason
324 - TAOLINESEARCH_SUCCESS - successful line search
325 
326   The algorithm developer must set up the TaoLineSearch with calls to
327   TaoLineSearchSetObjectiveRoutine() and TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), or TaoLineSearchUseTaoRoutines()
328 
329   You may or may not need to follow this with a call to
330   TaoAddLineSearchCounts(), depending on whether you want these
331   evaluations to count toward the total function/gradient evaluations.
332 
333   Level: beginner
334 
335   .seealso: TaoLineSearchCreate(), TaoLineSearchSetType(), TaoLineSearchSetInitialStepLength(), TaoAddLineSearchCounts()
336  @*/
337 
338 PetscErrorCode TaoLineSearchApply(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
339 {
340   PetscErrorCode ierr;
341   PetscInt       low1,low2,low3,high1,high2,high3;
342 
343   PetscFunctionBegin;
344   *reason = TAOLINESEARCH_CONTINUE_ITERATING;
345   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
346   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
347   PetscValidRealPointer(f,3);
348   PetscValidHeaderSpecific(g,VEC_CLASSID,4);
349   PetscValidHeaderSpecific(s,VEC_CLASSID,5);
350   PetscValidPointer(reason,7);
351   PetscCheckSameComm(ls,1,x,2);
352   PetscCheckSameTypeAndComm(x,2,g,4);
353   PetscCheckSameTypeAndComm(x,2,s,5);
354   ierr = VecGetOwnershipRange(x, &low1, &high1);CHKERRQ(ierr);
355   ierr = VecGetOwnershipRange(g, &low2, &high2);CHKERRQ(ierr);
356   ierr = VecGetOwnershipRange(s, &low3, &high3);CHKERRQ(ierr);
357   if (low1!= low2 || low1!= low3 || high1!= high2 || high1!= high3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible vector local lengths");
358 
359   ierr = PetscObjectReference((PetscObject)s);CHKERRQ(ierr);
360   ierr = VecDestroy(&ls->stepdirection);CHKERRQ(ierr);
361   ls->stepdirection = s;
362 
363   ierr = TaoLineSearchSetUp(ls);CHKERRQ(ierr);
364   if (!ls->ops->apply) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search Object does not have 'apply' routine");
365   ls->nfeval=0;
366   ls->ngeval=0;
367   ls->nfgeval=0;
368   /* Check parameter values */
369   if (ls->ftol < 0.0) {
370     ierr = PetscInfo1(ls,"Bad Line Search Parameter: ftol (%g) < 0\n",(double)ls->ftol);CHKERRQ(ierr);
371     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
372   }
373   if (ls->rtol < 0.0) {
374     ierr = PetscInfo1(ls,"Bad Line Search Parameter: rtol (%g) < 0\n",(double)ls->rtol);CHKERRQ(ierr);
375     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
376   }
377   if (ls->gtol < 0.0) {
378     ierr = PetscInfo1(ls,"Bad Line Search Parameter: gtol (%g) < 0\n",(double)ls->gtol);CHKERRQ(ierr);
379     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
380   }
381   if (ls->stepmin < 0.0) {
382     ierr = PetscInfo1(ls,"Bad Line Search Parameter: stepmin (%g) < 0\n",(double)ls->stepmin);CHKERRQ(ierr);
383     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
384   }
385   if (ls->stepmax < ls->stepmin) {
386     ierr = PetscInfo2(ls,"Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n",(double)ls->stepmin,(double)ls->stepmax);CHKERRQ(ierr);
387     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
388   }
389   if (ls->max_funcs < 0) {
390     ierr = PetscInfo1(ls,"Bad Line Search Parameter: max_funcs (%D) < 0\n",ls->max_funcs);CHKERRQ(ierr);
391     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
392   }
393   if (PetscIsInfOrNanReal(*f)) {
394     ierr = PetscInfo1(ls,"Initial Line Search Function Value is Inf or Nan (%g)\n",(double)*f);CHKERRQ(ierr);
395     *reason=TAOLINESEARCH_FAILED_INFORNAN;
396   }
397 
398   ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
399   ierr = VecDestroy(&ls->start_x);CHKERRQ(ierr);
400   ls->start_x = x;
401 
402   ierr = PetscLogEventBegin(TAOLINESEARCH_Apply,ls,0,0,0);CHKERRQ(ierr);
403   ierr = (*ls->ops->apply)(ls,x,f,g,s);CHKERRQ(ierr);
404   ierr = PetscLogEventEnd(TAOLINESEARCH_Apply, ls, 0,0,0);CHKERRQ(ierr);
405   *reason=ls->reason;
406   ls->new_f = *f;
407 
408   if (steplength) {
409     *steplength=ls->step;
410   }
411 
412   ierr = TaoLineSearchViewFromOptions(ls,NULL,"-tao_ls_view");CHKERRQ(ierr);
413   PetscFunctionReturn(0);
414 }
415 
416 /*@C
417    TaoLineSearchSetType - Sets the algorithm used in a line search
418 
419    Collective on TaoLineSearch
420 
421    Input Parameters:
422 +  ls - the TaoLineSearch context
423 -  type - the TaoLineSearchType selection
424 
425   Available methods include:
426 +  more-thuente - line search with a cubic model enforcing the strong Wolfe/curvature condition
427 .  armijo - simple backtracking line search enforcing only the sufficient decrease condition
428 -  unit - do not perform a line search and always accept unit step length
429 
430   Options Database Keys:
431 .  -tao_ls_type <more-thuente, armijo, unit> - select which method TAO should use at runtime
432 
433   Level: beginner
434 
435 .seealso: TaoLineSearchCreate(), TaoLineSearchGetType(), TaoLineSearchApply()
436 
437 @*/
438 
439 PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, TaoLineSearchType type)
440 {
441   PetscErrorCode ierr;
442   PetscErrorCode (*r)(TaoLineSearch);
443   PetscBool      flg;
444 
445   PetscFunctionBegin;
446   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
447   PetscValidCharPointer(type,2);
448   ierr = PetscObjectTypeCompare((PetscObject)ls, type, &flg);CHKERRQ(ierr);
449   if (flg) PetscFunctionReturn(0);
450 
451   ierr = PetscFunctionListFind(TaoLineSearchList,type, (void (**)(void)) &r);CHKERRQ(ierr);
452   if (!r) SETERRQ1(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested TaoLineSearch type %s",type);
453   if (ls->ops->destroy) {
454     ierr = (*(ls)->ops->destroy)(ls);CHKERRQ(ierr);
455   }
456   ls->max_funcs=30;
457   ls->ftol = 0.0001;
458   ls->gtol = 0.9;
459 #if defined(PETSC_USE_REAL_SINGLE)
460   ls->rtol = 1.0e-5;
461 #else
462   ls->rtol = 1.0e-10;
463 #endif
464   ls->stepmin=1.0e-20;
465   ls->stepmax=1.0e+20;
466 
467   ls->nfeval=0;
468   ls->ngeval=0;
469   ls->nfgeval=0;
470   ls->ops->setup = NULL;
471   ls->ops->apply = NULL;
472   ls->ops->view = NULL;
473   ls->ops->setfromoptions = NULL;
474   ls->ops->destroy = NULL;
475   ls->setupcalled = PETSC_FALSE;
476   ierr = (*r)(ls);CHKERRQ(ierr);
477   ierr = PetscObjectChangeTypeName((PetscObject)ls, type);CHKERRQ(ierr);
478   PetscFunctionReturn(0);
479 }
480 
481 /*@C
482   TaoLineSearchMonitor - Monitor the line search steps. This routine will otuput the
483   iteration number, step length, and function value before calling the implementation
484   specific monitor.
485 
486    Input Parameters:
487 +  ls - the TaoLineSearch context
488 .  its - the current iterate number (>=0)
489 .  f - the current objective function value
490 -  step - the step length
491 
492    Options Database Key:
493 .  -tao_ls_monitor - Use the default monitor, which prints statistics to standard output
494 
495    Level: developer
496 
497 @*/
498 PetscErrorCode TaoLineSearchMonitor(TaoLineSearch ls, PetscInt its, PetscReal f, PetscReal step)
499 {
500   PetscErrorCode ierr;
501   PetscInt       tabs;
502 
503   PetscFunctionBegin;
504   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
505   if (ls->usemonitor) {
506     ierr = PetscViewerASCIIGetTab(ls->viewer, &tabs);CHKERRQ(ierr);
507     ierr = PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel);CHKERRQ(ierr);
508     ierr = PetscViewerASCIIPrintf(ls->viewer, "%3D LS", its);CHKERRQ(ierr);
509     ierr = PetscViewerASCIIPrintf(ls->viewer, "  Function value: %g,", (double)f);CHKERRQ(ierr);
510     ierr = PetscViewerASCIIPrintf(ls->viewer, "  Step length: %g\n", (double)step);CHKERRQ(ierr);
511     if (ls->ops->monitor && its > 0) {
512       ierr = PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel + 3);CHKERRQ(ierr);
513       ierr = (*ls->ops->monitor)(ls);CHKERRQ(ierr);
514     }
515     ierr = PetscViewerASCIISetTab(ls->viewer, tabs);CHKERRQ(ierr);
516   }
517   PetscFunctionReturn(0);
518 }
519 
520 /*@
521   TaoLineSearchSetFromOptions - Sets various TaoLineSearch parameters from user
522   options.
523 
524   Collective on TaoLineSearch
525 
526   Input Parameter:
527 . ls - the TaoLineSearch context
528 
529   Options Database Keys:
530 + -tao_ls_type <type> - The algorithm that TAO uses (more-thuente, gpcg, unit)
531 . -tao_ls_ftol <tol> - tolerance for sufficient decrease
532 . -tao_ls_gtol <tol> - tolerance for curvature condition
533 . -tao_ls_rtol <tol> - relative tolerance for acceptable step
534 . -tao_ls_stepmin <step> - minimum steplength allowed
535 . -tao_ls_stepmax <step> - maximum steplength allowed
536 . -tao_ls_max_funcs <n> - maximum number of function evaluations allowed
537 - -tao_ls_view - display line-search results to standard output
538 
539   Level: beginner
540 @*/
541 PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
542 {
543   PetscErrorCode ierr;
544   const char     *default_type=TAOLINESEARCHMT;
545   char           type[256],monfilename[PETSC_MAX_PATH_LEN];
546   PetscViewer    monviewer;
547   PetscBool      flg;
548 
549   PetscFunctionBegin;
550   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
551   ierr = PetscObjectOptionsBegin((PetscObject)ls);CHKERRQ(ierr);
552   if (((PetscObject)ls)->type_name) {
553     default_type = ((PetscObject)ls)->type_name;
554   }
555   /* Check for type from options */
556   ierr = PetscOptionsFList("-tao_ls_type","Tao Line Search type","TaoLineSearchSetType",TaoLineSearchList,default_type,type,256,&flg);CHKERRQ(ierr);
557   if (flg) {
558     ierr = TaoLineSearchSetType(ls,type);CHKERRQ(ierr);
559   } else if (!((PetscObject)ls)->type_name) {
560     ierr = TaoLineSearchSetType(ls,default_type);CHKERRQ(ierr);
561   }
562 
563   ierr = PetscOptionsInt("-tao_ls_max_funcs","max function evals in line search","",ls->max_funcs,&ls->max_funcs,NULL);CHKERRQ(ierr);
564   ierr = PetscOptionsReal("-tao_ls_ftol","tol for sufficient decrease","",ls->ftol,&ls->ftol,NULL);CHKERRQ(ierr);
565   ierr = PetscOptionsReal("-tao_ls_gtol","tol for curvature condition","",ls->gtol,&ls->gtol,NULL);CHKERRQ(ierr);
566   ierr = PetscOptionsReal("-tao_ls_rtol","relative tol for acceptable step","",ls->rtol,&ls->rtol,NULL);CHKERRQ(ierr);
567   ierr = PetscOptionsReal("-tao_ls_stepmin","lower bound for step","",ls->stepmin,&ls->stepmin,NULL);CHKERRQ(ierr);
568   ierr = PetscOptionsReal("-tao_ls_stepmax","upper bound for step","",ls->stepmax,&ls->stepmax,NULL);CHKERRQ(ierr);
569   ierr = PetscOptionsString("-tao_ls_monitor","enable the basic monitor","TaoLineSearchSetMonitor","stdout",monfilename,sizeof(monfilename),&flg);CHKERRQ(ierr);
570   if (flg) {
571     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ls),monfilename,&monviewer);CHKERRQ(ierr);
572     ls->viewer = monviewer;
573     ls->usemonitor = PETSC_TRUE;
574   }
575   if (ls->ops->setfromoptions) {
576     ierr = (*ls->ops->setfromoptions)(PetscOptionsObject,ls);CHKERRQ(ierr);
577   }
578   ierr = PetscOptionsEnd();CHKERRQ(ierr);
579   PetscFunctionReturn(0);
580 }
581 
582 /*@C
583   TaoLineSearchGetType - Gets the current line search algorithm
584 
585   Not Collective
586 
587   Input Parameter:
588 . ls - the TaoLineSearch context
589 
590   Output Parameter:
591 . type - the line search algorithm in effect
592 
593   Level: developer
594 
595 @*/
596 PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, TaoLineSearchType *type)
597 {
598   PetscFunctionBegin;
599   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
600   PetscValidPointer(type,2);
601   *type = ((PetscObject)ls)->type_name;
602   PetscFunctionReturn(0);
603 }
604 
605 /*@
606   TaoLineSearchGetNumberFunctionEvaluations - Gets the number of function and gradient evaluation
607   routines used by the line search in last application (not cumulative).
608 
609   Not Collective
610 
611   Input Parameter:
612 . ls - the TaoLineSearch context
613 
614   Output Parameters:
615 + nfeval   - number of function evaluations
616 . ngeval   - number of gradient evaluations
617 - nfgeval  - number of function/gradient evaluations
618 
619   Level: intermediate
620 
621   Note:
622   If the line search is using the Tao objective and gradient
623   routines directly (see TaoLineSearchUseTaoRoutines()), then TAO
624   is already counting the number of evaluations.
625 
626 @*/
627 PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
628 {
629   PetscFunctionBegin;
630   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
631   *nfeval = ls->nfeval;
632   *ngeval = ls->ngeval;
633   *nfgeval = ls->nfgeval;
634   PetscFunctionReturn(0);
635 }
636 
637 /*@
638   TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
639   Tao evaluation routines.
640 
641   Not Collective
642 
643   Input Parameter:
644 . ls - the TaoLineSearch context
645 
646   Output Parameter:
647 . flg - PETSC_TRUE if the line search is using Tao evaluation routines,
648         otherwise PETSC_FALSE
649 
650   Level: developer
651 @*/
652 PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
653 {
654   PetscFunctionBegin;
655   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
656   *flg = ls->usetaoroutines;
657   PetscFunctionReturn(0);
658 }
659 
660 /*@C
661   TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search
662 
663   Logically Collective on TaoLineSearch
664 
665   Input Parameters:
666 + ls - the TaoLineSearch context
667 . func - the objective function evaluation routine
668 - ctx - the (optional) user-defined context for private data
669 
670   Calling sequence of func:
671 $      func (TaoLinesearch ls, Vec x, PetscReal *f, void *ctx);
672 
673 + x - input vector
674 . f - function value
675 - ctx (optional) user-defined context
676 
677   Level: beginner
678 
679   Note:
680   Use this routine only if you want the line search objective
681   evaluation routine to be different from the Tao's objective
682   evaluation routine. If you use this routine you must also set
683   the line search gradient and/or function/gradient routine.
684 
685   Note:
686   Some algorithms (lcl, gpcg) set their own objective routine for the
687   line search, application programmers should be wary of overriding the
688   default objective routine.
689 
690 .seealso: TaoLineSearchCreate(), TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
691 @*/
692 PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal*, void*), void *ctx)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
696 
697   ls->ops->computeobjective=func;
698   if (ctx) ls->userctx_func=ctx;
699   ls->usetaoroutines=PETSC_FALSE;
700   PetscFunctionReturn(0);
701 }
702 
703 /*@C
704   TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search
705 
706   Logically Collective on TaoLineSearch
707 
708   Input Parameters:
709 + ls - the TaoLineSearch context
710 . func - the gradient evaluation routine
711 - ctx - the (optional) user-defined context for private data
712 
713   Calling sequence of func:
714 $      func (TaoLinesearch ls, Vec x, Vec g, void *ctx);
715 
716 + x - input vector
717 . g - gradient vector
718 - ctx (optional) user-defined context
719 
720   Level: beginner
721 
722   Note:
723   Use this routine only if you want the line search gradient
724   evaluation routine to be different from the Tao's gradient
725   evaluation routine. If you use this routine you must also set
726   the line search function and/or function/gradient routine.
727 
728   Note:
729   Some algorithms (lcl, gpcg) set their own gradient routine for the
730   line search, application programmers should be wary of overriding the
731   default gradient routine.
732 
733 .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
734 @*/
735 PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec g, void*), void *ctx)
736 {
737   PetscFunctionBegin;
738   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
739   ls->ops->computegradient=func;
740   if (ctx) ls->userctx_grad=ctx;
741   ls->usetaoroutines=PETSC_FALSE;
742   PetscFunctionReturn(0);
743 }
744 
745 /*@C
746   TaoLineSearchSetObjectiveAndGradientRoutine - Sets the objective/gradient evaluation routine for the line search
747 
748   Logically Collective on TaoLineSearch
749 
750   Input Parameters:
751 + ls - the TaoLineSearch context
752 . func - the objective and gradient evaluation routine
753 - ctx - the (optional) user-defined context for private data
754 
755   Calling sequence of func:
756 $      func (TaoLinesearch ls, Vec x, PetscReal *f, Vec g, void *ctx);
757 
758 + x - input vector
759 . f - function value
760 . g - gradient vector
761 - ctx (optional) user-defined context
762 
763   Level: beginner
764 
765   Note:
766   Use this routine only if you want the line search objective and gradient
767   evaluation routines to be different from the Tao's objective
768   and gradient evaluation routines.
769 
770   Note:
771   Some algorithms (lcl, gpcg) set their own objective routine for the
772   line search, application programmers should be wary of overriding the
773   default objective routine.
774 
775 .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetGradientRoutine(), TaoLineSearchUseTaoRoutines()
776 @*/
777 PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal *, Vec g, void*), void *ctx)
778 {
779   PetscFunctionBegin;
780   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
781   ls->ops->computeobjectiveandgradient=func;
782   if (ctx) ls->userctx_funcgrad=ctx;
783   ls->usetaoroutines = PETSC_FALSE;
784   PetscFunctionReturn(0);
785 }
786 
787 /*@C
788   TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
789   (gradient'*stepdirection) evaluation routine for the line search.
790   Sometimes it is more efficient to compute the inner product of the gradient
791   and the step direction than it is to compute the gradient, and this is all
792   the line search typically needs of the gradient.
793 
794   Logically Collective on TaoLineSearch
795 
796   Input Parameters:
797 + ls - the TaoLineSearch context
798 . func - the objective and gradient evaluation routine
799 - ctx - the (optional) user-defined context for private data
800 
801   Calling sequence of func:
802 $      func (TaoLinesearch ls, Vec x, PetscReal *f, PetscReal *gts, void *ctx);
803 
804 + x - input vector
805 . s - step direction
806 . f - function value
807 . gts - inner product of gradient and step direction vectors
808 - ctx (optional) user-defined context
809 
810   Note: The gradient will still need to be computed at the end of the line
811   search, so you will still need to set a line search gradient evaluation
812   routine
813 
814   Note: Bounded line searches (those used in bounded optimization algorithms)
815   don't use g's directly, but rather (g'x - g'x0)/steplength.  You can get the
816   x0 and steplength with TaoLineSearchGetStartingVector() and TaoLineSearchGetStepLength()
817 
818   Level: advanced
819 
820   Note:
821   Some algorithms (lcl, gpcg) set their own objective routine for the
822   line search, application programmers should be wary of overriding the
823   default objective routine.
824 
825 .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjective(), TaoLineSearchSetGradient(), TaoLineSearchUseTaoRoutines()
826 @*/
827 PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec s, PetscReal *, PetscReal *, void*), void *ctx)
828 {
829   PetscFunctionBegin;
830   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
831   ls->ops->computeobjectiveandgts=func;
832   if (ctx) ls->userctx_funcgts=ctx;
833   ls->usegts = PETSC_TRUE;
834   ls->usetaoroutines=PETSC_FALSE;
835   PetscFunctionReturn(0);
836 }
837 
838 /*@C
839   TaoLineSearchUseTaoRoutines - Informs the TaoLineSearch to use the
840   objective and gradient evaluation routines from the given Tao object.
841 
842   Logically Collective on TaoLineSearch
843 
844   Input Parameters:
845 + ls - the TaoLineSearch context
846 - ts - the Tao context with defined objective/gradient evaluation routines
847 
848   Level: developer
849 
850 .seealso: TaoLineSearchCreate()
851 @*/
852 PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
853 {
854   PetscFunctionBegin;
855   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
856   PetscValidHeaderSpecific(ts,TAO_CLASSID,2);
857   ls->tao = ts;
858   ls->usetaoroutines=PETSC_TRUE;
859   PetscFunctionReturn(0);
860 }
861 
862 /*@
863   TaoLineSearchComputeObjective - Computes the objective function value at a given point
864 
865   Collective on TaoLineSearch
866 
867   Input Parameters:
868 + ls - the TaoLineSearch context
869 - x - input vector
870 
871   Output Parameter:
872 . f - Objective value at X
873 
874   Notes:
875     TaoLineSearchComputeObjective() is typically used within line searches
876   so most users would not generally call this routine themselves.
877 
878   Level: developer
879 
880 .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
881 @*/
882 PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
883 {
884   PetscErrorCode ierr;
885   Vec            gdummy;
886   PetscReal      gts;
887 
888   PetscFunctionBegin;
889   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
890   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
891   PetscValidPointer(f,3);
892   PetscCheckSameComm(ls,1,x,2);
893   if (ls->usetaoroutines) {
894     ierr = TaoComputeObjective(ls->tao,x,f);CHKERRQ(ierr);
895   } else {
896     if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient && !ls->ops->computeobjectiveandgts) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
897     ierr = PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
898     PetscStackPush("TaoLineSearch user objective routine");
899     if (ls->ops->computeobjective) {
900       ierr = (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);CHKERRQ(ierr);
901     } else if (ls->ops->computeobjectiveandgradient) {
902       ierr = VecDuplicate(x,&gdummy);CHKERRQ(ierr);
903       ierr = (*ls->ops->computeobjectiveandgradient)(ls,x,f,gdummy,ls->userctx_funcgrad);CHKERRQ(ierr);
904       ierr = VecDestroy(&gdummy);CHKERRQ(ierr);
905     } else {
906       ierr = (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,&gts,ls->userctx_funcgts);CHKERRQ(ierr);
907     }
908     PetscStackPop;
909     ierr = PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
910   }
911   ls->nfeval++;
912   PetscFunctionReturn(0);
913 }
914 
915 /*@
916   TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point
917 
918   Collective on Tao
919 
920   Input Parameters:
921 + ls - the TaoLineSearch context
922 - x - input vector
923 
924   Output Parameters:
925 + f - Objective value at X
926 - g - Gradient vector at X
927 
928   Notes:
929     TaoLineSearchComputeObjectiveAndGradient() is typically used within line searches
930   so most users would not generally call this routine themselves.
931 
932   Level: developer
933 
934 .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
935 @*/
936 PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
937 {
938   PetscErrorCode ierr;
939 
940   PetscFunctionBegin;
941   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
942   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
943   PetscValidPointer(f,3);
944   PetscValidHeaderSpecific(g,VEC_CLASSID,4);
945   PetscCheckSameComm(ls,1,x,2);
946   PetscCheckSameComm(ls,1,g,4);
947   if (ls->usetaoroutines) {
948     ierr = TaoComputeObjectiveAndGradient(ls->tao,x,f,g);CHKERRQ(ierr);
949   } else {
950     if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
951     if (!ls->ops->computegradient  && !ls->ops->computeobjectiveandgradient) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient function set");
952     ierr = PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
953     if (ls->ops->computeobjectiveandgradient) {
954       PetscStackPush("TaoLineSearch user objective/gradient routine");
955       ierr = (*ls->ops->computeobjectiveandgradient)(ls,x,f,g,ls->userctx_funcgrad);CHKERRQ(ierr);
956       PetscStackPop;
957     } else {
958       PetscStackPush("TaoLineSearch user objective routine");
959       ierr = (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);CHKERRQ(ierr);
960       PetscStackPop;
961       PetscStackPush("TaoLineSearch user gradient routine");
962       ierr = (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);CHKERRQ(ierr);
963       PetscStackPop;
964     }
965     ierr = PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
966     ierr = PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));CHKERRQ(ierr);
967   }
968   ls->nfgeval++;
969   PetscFunctionReturn(0);
970 }
971 
972 /*@
973   TaoLineSearchComputeGradient - Computes the gradient of the objective function
974 
975   Collective on TaoLineSearch
976 
977   Input Parameters:
978 + ls - the TaoLineSearch context
979 - x - input vector
980 
981   Output Parameter:
982 . g - gradient vector
983 
984   Notes:
985     TaoComputeGradient() is typically used within line searches
986   so most users would not generally call this routine themselves.
987 
988   Level: developer
989 
990 .seealso: TaoLineSearchComputeObjective(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetGradient()
991 @*/
992 PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
993 {
994   PetscErrorCode ierr;
995   PetscReal      fdummy;
996 
997   PetscFunctionBegin;
998   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
999   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
1000   PetscValidHeaderSpecific(g,VEC_CLASSID,3);
1001   PetscCheckSameComm(ls,1,x,2);
1002   PetscCheckSameComm(ls,1,g,3);
1003   if (ls->usetaoroutines) {
1004     ierr = TaoComputeGradient(ls->tao,x,g);CHKERRQ(ierr);
1005   } else {
1006     if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient functions set");
1007     ierr = PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
1008     PetscStackPush("TaoLineSearch user gradient routine");
1009     if (ls->ops->computegradient) {
1010       ierr = (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);CHKERRQ(ierr);
1011     } else {
1012       ierr = (*ls->ops->computeobjectiveandgradient)(ls,x,&fdummy,g,ls->userctx_funcgrad);CHKERRQ(ierr);
1013     }
1014     PetscStackPop;
1015     ierr = PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
1016   }
1017   ls->ngeval++;
1018   PetscFunctionReturn(0);
1019 }
1020 
1021 /*@
1022   TaoLineSearchComputeObjectiveAndGTS - Computes the objective function value and inner product of gradient and step direction at a given point
1023 
1024   Collective on Tao
1025 
1026   Input Parameters:
1027 + ls - the TaoLineSearch context
1028 - x - input vector
1029 
1030   Output Parameters:
1031 + f - Objective value at X
1032 - gts - inner product of gradient and step direction at X
1033 
1034   Notes:
1035     TaoLineSearchComputeObjectiveAndGTS() is typically used within line searches
1036   so most users would not generally call this routine themselves.
1037 
1038   Level: developer
1039 
1040 .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
1041 @*/
1042 PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
1043 {
1044   PetscErrorCode ierr;
1045   PetscFunctionBegin;
1046   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1047   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
1048   PetscValidPointer(f,3);
1049   PetscValidPointer(gts,4);
1050   PetscCheckSameComm(ls,1,x,2);
1051   if (!ls->ops->computeobjectiveandgts) SETERRQ(PetscObjectComm((PetscObject)ls),PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective and gts function set");
1052   ierr = PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
1053   PetscStackPush("TaoLineSearch user objective/gts routine");
1054   ierr = (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,gts,ls->userctx_funcgts);CHKERRQ(ierr);
1055   PetscStackPop;
1056   ierr = PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);CHKERRQ(ierr);
1057   ierr = PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));CHKERRQ(ierr);
1058   ls->nfeval++;
1059   PetscFunctionReturn(0);
1060 }
1061 
1062 /*@
1063   TaoLineSearchGetSolution - Returns the solution to the line search
1064 
1065   Collective on TaoLineSearch
1066 
1067   Input Parameter:
1068 . ls - the TaoLineSearch context
1069 
1070   Output Parameters:
1071 + x - the new solution
1072 . f - the objective function value at x
1073 . g - the gradient at x
1074 . steplength - the multiple of the step direction taken by the line search
1075 - reason - the reason why the line search terminated
1076 
1077   reason will be set to one of:
1078 
1079 + TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
1080 . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
1081 . TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
1082 . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
1083 . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
1084 . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
1085 . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
1086 
1087 . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
1088 . TAOLINESEARCH_HALTED_OTHER - any other reason
1089 
1090 - TAOLINESEARCH_SUCCESS - successful line search
1091 
1092   Level: developer
1093 
1094 @*/
1095 PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
1096 {
1097   PetscErrorCode ierr;
1098 
1099   PetscFunctionBegin;
1100   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1101   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
1102   PetscValidPointer(f,3);
1103   PetscValidHeaderSpecific(g,VEC_CLASSID,4);
1104   PetscValidIntPointer(reason,6);
1105   if (ls->new_x) {
1106     ierr = VecCopy(ls->new_x,x);CHKERRQ(ierr);
1107   }
1108   *f = ls->new_f;
1109   if (ls->new_g) {
1110     ierr = VecCopy(ls->new_g,g);CHKERRQ(ierr);
1111   }
1112   if (steplength) {
1113     *steplength=ls->step;
1114   }
1115   *reason = ls->reason;
1116   PetscFunctionReturn(0);
1117 }
1118 
1119 /*@
1120   TaoLineSearchGetStartingVector - Gets a the initial point of the line
1121   search.
1122 
1123   Not Collective
1124 
1125   Input Parameter:
1126 . ls - the TaoLineSearch context
1127 
1128   Output Parameter:
1129 . x - The initial point of the line search
1130 
1131   Level: intermediate
1132 @*/
1133 PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1134 {
1135   PetscFunctionBegin;
1136   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1137   if (x) {
1138     *x = ls->start_x;
1139   }
1140   PetscFunctionReturn(0);
1141 }
1142 
1143 /*@
1144   TaoLineSearchGetStepDirection - Gets the step direction of the line
1145   search.
1146 
1147   Not Collective
1148 
1149   Input Parameter:
1150 . ls - the TaoLineSearch context
1151 
1152   Output Parameter:
1153 . s - the step direction of the line search
1154 
1155   Level: advanced
1156 @*/
1157 PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1158 {
1159   PetscFunctionBegin;
1160   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1161   if (s) {
1162     *s = ls->stepdirection;
1163   }
1164   PetscFunctionReturn(0);
1165 
1166 }
1167 
1168 /*@
1169   TaoLineSearchGetFullStepObjective - Returns the objective function value at the full step.  Useful for some minimization algorithms.
1170 
1171   Not Collective
1172 
1173   Input Parameter:
1174 . ls - the TaoLineSearch context
1175 
1176   Output Parameter:
1177 . f - the objective value at the full step length
1178 
1179   Level: developer
1180 @*/
1181 
1182 PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch ls, PetscReal *f_fullstep)
1183 {
1184   PetscFunctionBegin;
1185   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1186   *f_fullstep = ls->f_fullstep;
1187   PetscFunctionReturn(0);
1188 }
1189 
1190 /*@
1191   TaoLineSearchSetVariableBounds - Sets the upper and lower bounds.
1192 
1193   Logically Collective on Tao
1194 
1195   Input Parameters:
1196 + ls - the TaoLineSearch context
1197 . xl  - vector of lower bounds
1198 - xu  - vector of upper bounds
1199 
1200   Note: If the variable bounds are not set with this routine, then
1201   PETSC_NINFINITY and PETSC_INFINITY are assumed
1202 
1203   Level: beginner
1204 
1205 .seealso: TaoSetVariableBounds(), TaoLineSearchCreate()
1206 @*/
1207 PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls,Vec xl, Vec xu)
1208 {
1209   PetscFunctionBegin;
1210   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1211   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
1212   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
1213   ls->lower = xl;
1214   ls->upper = xu;
1215   ls->bounded = 1;
1216   PetscFunctionReturn(0);
1217 }
1218 
1219 /*@
1220   TaoLineSearchSetInitialStepLength - Sets the initial step length of a line
1221   search.  If this value is not set then 1.0 is assumed.
1222 
1223   Logically Collective on TaoLineSearch
1224 
1225   Input Parameters:
1226 + ls - the TaoLineSearch context
1227 - s - the initial step size
1228 
1229   Level: intermediate
1230 
1231 .seealso: TaoLineSearchGetStepLength(), TaoLineSearchApply()
1232 @*/
1233 PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls,PetscReal s)
1234 {
1235   PetscFunctionBegin;
1236   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1237   ls->initstep = s;
1238   PetscFunctionReturn(0);
1239 }
1240 
1241 /*@
1242   TaoLineSearchGetStepLength - Get the current step length
1243 
1244   Not Collective
1245 
1246   Input Parameters:
1247 . ls - the TaoLineSearch context
1248 
1249   Output Parameters:
1250 . s - the current step length
1251 
1252   Level: beginner
1253 
1254 .seealso: TaoLineSearchSetInitialStepLength(), TaoLineSearchApply()
1255 @*/
1256 PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls,PetscReal *s)
1257 {
1258   PetscFunctionBegin;
1259   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
1260   *s = ls->step;
1261   PetscFunctionReturn(0);
1262 }
1263 
1264 /*@C
1265    TaoLineSearchRegister - Adds a line-search algorithm to the registry
1266 
1267    Not collective
1268 
1269    Input Parameters:
1270 +  sname - name of a new user-defined solver
1271 -  func - routine to Create method context
1272 
1273    Notes:
1274    TaoLineSearchRegister() may be called multiple times to add several user-defined solvers.
1275 
1276    Sample usage:
1277 .vb
1278    TaoLineSearchRegister("my_linesearch",MyLinesearchCreate);
1279 .ve
1280 
1281    Then, your solver can be chosen with the procedural interface via
1282 $     TaoLineSearchSetType(ls,"my_linesearch")
1283    or at runtime via the option
1284 $     -tao_ls_type my_linesearch
1285 
1286    Level: developer
1287 
1288 @*/
1289 PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch))
1290 {
1291   PetscErrorCode ierr;
1292   PetscFunctionBegin;
1293   ierr = TaoLineSearchInitializePackage();CHKERRQ(ierr);
1294   ierr = PetscFunctionListAdd(&TaoLineSearchList, sname, (void (*)(void))func);CHKERRQ(ierr);
1295   PetscFunctionReturn(0);
1296 }
1297 
1298 /*@C
1299    TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1300    for all TaoLineSearch options in the database.
1301 
1302    Collective on TaoLineSearch
1303 
1304    Input Parameters:
1305 +  ls - the TaoLineSearch solver context
1306 -  prefix - the prefix string to prepend to all line search requests
1307 
1308    Notes:
1309    A hyphen (-) must NOT be given at the beginning of the prefix name.
1310    The first character of all runtime options is AUTOMATICALLY the hyphen.
1311 
1312    Level: advanced
1313 
1314 .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1315 @*/
1316 PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1317 {
1318   return PetscObjectAppendOptionsPrefix((PetscObject)ls,p);
1319 }
1320 
1321 /*@C
1322   TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1323   TaoLineSearch options in the database
1324 
1325   Not Collective
1326 
1327   Input Parameters:
1328 . ls - the TaoLineSearch context
1329 
1330   Output Parameters:
1331 . prefix - pointer to the prefix string used is returned
1332 
1333   Notes:
1334     On the fortran side, the user should pass in a string 'prefix' of
1335   sufficient length to hold the prefix.
1336 
1337   Level: advanced
1338 
1339 .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchAppendOptionsPrefix()
1340 @*/
1341 PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1342 {
1343   return PetscObjectGetOptionsPrefix((PetscObject)ls,p);
1344 }
1345 
1346 /*@C
1347    TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1348    TaoLineSearch options in the database.
1349 
1350    Logically Collective on TaoLineSearch
1351 
1352    Input Parameters:
1353 +  ls - the TaoLineSearch context
1354 -  prefix - the prefix string to prepend to all TAO option requests
1355 
1356    Notes:
1357    A hyphen (-) must NOT be given at the beginning of the prefix name.
1358    The first character of all runtime options is AUTOMATICALLY the hyphen.
1359 
1360    For example, to distinguish between the runtime options for two
1361    different line searches, one could call
1362 .vb
1363       TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1364       TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1365 .ve
1366 
1367    This would enable use of different options for each system, such as
1368 .vb
1369       -sys1_tao_ls_type mt
1370       -sys2_tao_ls_type armijo
1371 .ve
1372 
1373    Level: advanced
1374 
1375 .seealso: TaoLineSearchAppendOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1376 @*/
1377 
1378 PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1379 {
1380   return PetscObjectSetOptionsPrefix((PetscObject)ls,p);
1381 }
1382