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