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