Actual source code: taolinesearch.c

petsc-3.6.4 2016-04-12
Report Typos and Errors
  1: #include <petsctaolinesearch.h> /*I "petsctaolinesearch.h" I*/
  2: #include <petsc/private/taolinesearchimpl.h>

  4: PetscBool TaoLineSearchInitialized = PETSC_FALSE;
  5: PetscFunctionList TaoLineSearchList = NULL;

  7: PetscClassId TAOLINESEARCH_CLASSID=0;
  8: PetscLogEvent TaoLineSearch_ApplyEvent = 0, TaoLineSearch_EvalEvent=0;

 12: /*@C
 13:   TaoLineSearchView - Prints information about the TaoLineSearch

 15:   Collective on TaoLineSearch

 17:   InputParameters:
 18: + ls - the Tao context
 19: - viewer - visualization context

 21:   Options Database Key:
 22: . -tao_ls_view - Calls TaoLineSearchView() at the end of each line search

 24:   Notes:
 25:   The available visualization contexts include
 26: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
 27: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
 28:          output where only the first processor opens
 29:          the file.  All other processors send their
 30:          data to the first processor to print.

 32:   Level: beginner

 34: .seealso: PetscViewerASCIIOpen()
 35: @*/

 37: PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
 38: {
 39:   PetscErrorCode          ierr;
 40:   PetscBool               isascii, isstring;
 41:   const TaoLineSearchType type;
 42:   PetscBool               destroyviewer = PETSC_FALSE;

 46:   if (!viewer) {
 47:     destroyviewer = PETSC_TRUE;
 48:     PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer);
 49:   }

 53:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
 54:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
 55:   if (isascii) {
 56:     if (((PetscObject)ls)->prefix) {
 57:       PetscViewerASCIIPrintf(viewer,"TaoLineSearch Object:(%s)\n",((PetscObject)ls)->prefix);
 58:     } else {
 59:       PetscViewerASCIIPrintf(viewer,"TaoLineSearch Object:\n");
 60:     }
 61:     PetscViewerASCIIPushTab(viewer);
 62:     TaoLineSearchGetType(ls,&type);
 63:     if (type) {
 64:       PetscViewerASCIIPrintf(viewer,"type: %s\n",type);
 65:     } else {
 66:       PetscViewerASCIIPrintf(viewer,"type: not set yet\n");
 67:     }
 68:     if (ls->ops->view) {
 69:       PetscViewerASCIIPushTab(viewer);
 70:       (*ls->ops->view)(ls,viewer);
 71:       PetscViewerASCIIPopTab(viewer);
 72:     }
 73:     PetscViewerASCIIPrintf(viewer,"maximum function evaluations=%D\n",ls->max_funcs);
 74:     PetscViewerASCIIPrintf(viewer,"tolerances: ftol=%g, rtol=%g, gtol=%g\n",(double)ls->ftol,(double)ls->rtol,(double)ls->gtol);
 75:     PetscViewerASCIIPrintf(viewer,"total number of function evaluations=%D\n",ls->nfeval);
 76:     PetscViewerASCIIPrintf(viewer,"total number of gradient evaluations=%D\n",ls->ngeval);
 77:     PetscViewerASCIIPrintf(viewer,"total number of function/gradient evaluations=%D\n",ls->nfgeval);

 79:     if (ls->bounded) {
 80:       PetscViewerASCIIPrintf(viewer,"using variable bounds\n");
 81:     }
 82:     PetscViewerASCIIPrintf(viewer,"Termination reason: %D\n",(int)ls->reason);
 83:     PetscViewerASCIIPopTab(viewer);

 85:   } else if (isstring) {
 86:     TaoLineSearchGetType(ls,&type);
 87:     PetscViewerStringSPrintf(viewer," %-3.3s",type);
 88:   }
 89:   if (destroyviewer) {
 90:     PetscViewerDestroy(&viewer);
 91:   }
 92:   return(0);
 93: }

 97: /*@C
 98:   TaoLineSearchCreate - Creates a TAO Line Search object.  Algorithms in TAO that use
 99:   line-searches will automatically create one.

101:   Collective on MPI_Comm

103:   Input Parameter:
104: . comm - MPI communicator

106:   Output Parameter:
107: . newls - the new TaoLineSearch context

109:   Available methods include:
110: + more-thuente
111: . gpcg
112: - unit - Do not perform any line search


115:    Options Database Keys:
116: .   -tao_ls_type - select which method TAO should use

118:    Level: beginner

120: .seealso: TaoLineSearchSetType(), TaoLineSearchApply(), TaoLineSearchDestroy()
121: @*/

123: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
124: {
126:   TaoLineSearch  ls;

130:   *newls = NULL;

132:  #ifndef PETSC_USE_DYNAMIC_LIBRARIES
133:   TaoLineSearchInitializePackage();
134:  #endif

136:   PetscHeaderCreate(ls,TAOLINESEARCH_CLASSID,"TaoLineSearch","Linesearch","Tao",comm,TaoLineSearchDestroy,TaoLineSearchView);
137:   ls->bounded = 0;
138:   ls->max_funcs=30;
139:   ls->ftol = 0.0001;
140:   ls->gtol = 0.9;
141: #if defined(PETSC_USE_REAL_SINGLE)
142:   ls->rtol = 1.0e-5;
143: #else
144:   ls->rtol = 1.0e-10;
145: #endif
146:   ls->stepmin=1.0e-20;
147:   ls->stepmax=1.0e+20;
148:   ls->step=1.0;
149:   ls->nfeval=0;
150:   ls->ngeval=0;
151:   ls->nfgeval=0;

153:   ls->ops->computeobjective=0;
154:   ls->ops->computegradient=0;
155:   ls->ops->computeobjectiveandgradient=0;
156:   ls->ops->computeobjectiveandgts=0;
157:   ls->ops->setup=0;
158:   ls->ops->apply=0;
159:   ls->ops->view=0;
160:   ls->ops->setfromoptions=0;
161:   ls->ops->reset=0;
162:   ls->ops->destroy=0;
163:   ls->setupcalled=PETSC_FALSE;
164:   ls->usetaoroutines=PETSC_FALSE;
165:   *newls = ls;
166:   return(0);
167: }

171: /*@
172:   TaoLineSearchSetUp - Sets up the internal data structures for the later use
173:   of a Tao solver

175:   Collective on ls

177:   Input Parameters:
178: . ls - the TaoLineSearch context

180:   Notes:
181:   The user will not need to explicitly call TaoLineSearchSetUp(), as it will
182:   automatically be called in TaoLineSearchSolve().  However, if the user
183:   desires to call it explicitly, it should come after TaoLineSearchCreate()
184:   but before TaoLineSearchApply().

186:   Level: developer

188: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
189: @*/

191: PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
192: {
194:   const char     *default_type=TAOLINESEARCHMT;
195:   PetscBool      flg;

199:   if (ls->setupcalled) return(0);
200:   if (!((PetscObject)ls)->type_name) {
201:     TaoLineSearchSetType(ls,default_type);
202:   }
203:   if (ls->ops->setup) {
204:     (*ls->ops->setup)(ls);
205:   }
206:   if (ls->usetaoroutines) {
207:     TaoIsObjectiveDefined(ls->tao,&flg);
208:     ls->hasobjective = flg;
209:     TaoIsGradientDefined(ls->tao,&flg);
210:     ls->hasgradient = flg;
211:     TaoIsObjectiveAndGradientDefined(ls->tao,&flg);
212:     ls->hasobjectiveandgradient = flg;
213:   } else {
214:     if (ls->ops->computeobjective) {
215:       ls->hasobjective = PETSC_TRUE;
216:     } else {
217:       ls->hasobjective = PETSC_FALSE;
218:     }
219:     if (ls->ops->computegradient) {
220:       ls->hasgradient = PETSC_TRUE;
221:     } else {
222:       ls->hasgradient = PETSC_FALSE;
223:     }
224:     if (ls->ops->computeobjectiveandgradient) {
225:       ls->hasobjectiveandgradient = PETSC_TRUE;
226:     } else {
227:       ls->hasobjectiveandgradient = PETSC_FALSE;
228:     }
229:   }
230:   ls->setupcalled = PETSC_TRUE;
231:   return(0);
232: }

236: /*@
237:   TaoLineSearchReset - Some line searches may carry state information
238:   from one TaoLineSearchApply() to the next.  This function resets this
239:   state information.

241:   Collective on TaoLineSearch

243:   Input Parameter:
244: . ls - the TaoLineSearch context

246:   Level: developer

248: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
249: @*/
250: PetscErrorCode TaoLineSearchReset(TaoLineSearch ls)
251: {

256:   if (ls->ops->reset) {
257:     (*ls->ops->reset)(ls);
258:   }
259:   return(0);
260: }

264: /*@
265:   TaoLineSearchDestroy - Destroys the TAO context that was created with
266:   TaoLineSearchCreate()

268:   Collective on TaoLineSearch

270:   Input Parameter
271: . ls - the TaoLineSearch context

273:   Level: beginner

275: .seealse: TaoLineSearchCreate(), TaoLineSearchSolve()
276: @*/
277: PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
278: {

282:   if (!*ls) return(0);
284:   if (--((PetscObject)*ls)->refct > 0) {*ls=0; return(0);}
285:   VecDestroy(&(*ls)->stepdirection);
286:   VecDestroy(&(*ls)->start_x);
287:   if ((*ls)->ops->destroy) {
288:     (*(*ls)->ops->destroy)(*ls);
289:   }
290:   PetscHeaderDestroy(ls);
291:   return(0);
292: }

296: /*@
297:   TaoLineSearchApply - Performs a line-search in a given step direction.  Criteria for acceptable step length depends on the line-search algorithm chosen

299:   Collective on TaoLineSearch

301:   Input Parameters:
302: + ls - the Tao context
303: . x - The current solution (on output x contains the new solution determined by the line search)
304: . f - objective function value at current solution (on output contains the objective function value at new solution)
305: . g - gradient evaluated at x (on output contains the gradient at new solution)
306: - s - search direction

308:   Output Parameters:
309: + x - new solution
310: . f - objective function value at x
311: . g - gradient vector at x
312: . steplength - scalar multiplier of s used ( x = x0 + steplength * x )
313: - reason - reason why the line-search stopped

315:   reason will be set to one of:

317: + TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
318: . TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
319: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
320: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
321: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
322: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
323: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
324: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
325: . TAOLINESEARCH_HALTED_OTHER - any other reason
326: - TAOLINESEARCH_SUCCESS - successful line search

328:   Note:
329:   The algorithm developer must set up the TaoLineSearch with calls to
330:   TaoLineSearchSetObjectiveRoutine() and TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), or TaoLineSearchUseTaoRoutines()

332:   Note:
333:   You may or may not need to follow this with a call to
334:   TaoAddLineSearchCounts(), depending on whether you want these
335:   evaluations to count toward the total function/gradient evaluations.

337:   Level: beginner

339:   .seealso: TaoLineSearchCreate(), TaoLineSearchSetType(), TaoLineSearchSetInitialStepLength(), TaoAddLineSearchCounts()
340:  @*/

342: PetscErrorCode TaoLineSearchApply(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
343: {
345:   PetscInt       low1,low2,low3,high1,high2,high3;

348:   *reason = TAOLINESEARCH_CONTINUE_ITERATING;
358:   VecGetOwnershipRange(x, &low1, &high1);
359:   VecGetOwnershipRange(g, &low2, &high2);
360:   VecGetOwnershipRange(s, &low3, &high3);
361:   if ( low1!= low2 || low1!= low3 || high1!= high2 || high1!= high3) SETERRQ(PETSC_COMM_SELF,1,"InCompatible vector local lengths");

363:   PetscObjectReference((PetscObject)s);
364:   VecDestroy(&ls->stepdirection);
365:   ls->stepdirection = s;

367:   TaoLineSearchSetUp(ls);
368:   if (!ls->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search Object does not have 'apply' routine");
369:   ls->nfeval=0;
370:   ls->ngeval=0;
371:   ls->nfgeval=0;
372:   /* Check parameter values */
373:   if (ls->ftol < 0.0) {
374:     PetscInfo1(ls,"Bad Line Search Parameter: ftol (%g) < 0\n",(double)ls->ftol);
375:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
376:   }
377:   if (ls->rtol < 0.0) {
378:     PetscInfo1(ls,"Bad Line Search Parameter: rtol (%g) < 0\n",(double)ls->rtol);
379:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
380:   }
381:   if (ls->gtol < 0.0) {
382:     PetscInfo1(ls,"Bad Line Search Parameter: gtol (%g) < 0\n",(double)ls->gtol);
383:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
384:   }
385:   if (ls->stepmin < 0.0) {
386:     PetscInfo1(ls,"Bad Line Search Parameter: stepmin (%g) < 0\n",(double)ls->stepmin);
387:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
388:   }
389:   if (ls->stepmax < ls->stepmin) {
390:     PetscInfo2(ls,"Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n",(double)ls->stepmin,(double)ls->stepmax);
391:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
392:   }
393:   if (ls->max_funcs < 0) {
394:     PetscInfo1(ls,"Bad Line Search Parameter: max_funcs (%D) < 0\n",ls->max_funcs);
395:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
396:   }
397:   if (PetscIsInfOrNanReal(*f)) {
398:     PetscInfo1(ls,"Initial Line Search Function Value is Inf or Nan (%g)\n",(double)*f);
399:     *reason=TAOLINESEARCH_FAILED_INFORNAN;
400:   }

402:   PetscObjectReference((PetscObject)x);
403:   VecDestroy(&ls->start_x);
404:   ls->start_x = x;

406:   PetscLogEventBegin(TaoLineSearch_ApplyEvent,ls,0,0,0);
407:   (*ls->ops->apply)(ls,x,f,g,s);
408:   PetscLogEventEnd(TaoLineSearch_ApplyEvent, ls, 0,0,0);
409:   *reason=ls->reason;
410:   ls->new_f = *f;

412:   if (steplength) {
413:     *steplength=ls->step;
414:   }

416:   TaoLineSearchViewFromOptions(ls,NULL,"-tao_ls_view");
417:   return(0);
418: }

422: /*@C
423:    TaoLineSearchSetType - Sets the algorithm used in a line search

425:    Collective on TaoLineSearch

427:    Input Parameters:
428: +  ls - the TaoLineSearch context
429: -  type - a known method

431:   Available methods include:
432: + more-thuente
433: . gpcg
434: - unit - Do not perform any line search


437:   Options Database Keys:
438: .   -tao_ls_type - select which method TAO should use

440:   Level: beginner


443: .seealso: TaoLineSearchCreate(), TaoLineSearchGetType(), TaoLineSearchApply()

445: @*/

447: PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, const TaoLineSearchType type)
448: {
450:   PetscErrorCode (*r)(TaoLineSearch);
451:   PetscBool      flg;

456:   PetscObjectTypeCompare((PetscObject)ls, type, &flg);
457:   if (flg) return(0);

459:   PetscFunctionListFind(TaoLineSearchList,type, (void (**)(void)) &r);
460:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested TaoLineSearch type %s",type);
461:   if (ls->ops->destroy) {
462:     (*(ls)->ops->destroy)(ls);
463:   }
464:   ls->max_funcs=30;
465:   ls->ftol = 0.0001;
466:   ls->gtol = 0.9;
467: #if defined(PETSC_USE_REAL_SINGLE)
468:   ls->rtol = 1.0e-5;
469: #else
470:   ls->rtol = 1.0e-10;
471: #endif
472:   ls->stepmin=1.0e-20;
473:   ls->stepmax=1.0e+20;

475:   ls->nfeval=0;
476:   ls->ngeval=0;
477:   ls->nfgeval=0;
478:   ls->ops->setup=0;
479:   ls->ops->apply=0;
480:   ls->ops->view=0;
481:   ls->ops->setfromoptions=0;
482:   ls->ops->destroy=0;
483:   ls->setupcalled = PETSC_FALSE;
484:   (*r)(ls);
485:   PetscObjectChangeTypeName((PetscObject)ls, type);
486:   return(0);
487: }

491: /*@
492:   TaoLineSearchSetFromOptions - Sets various TaoLineSearch parameters from user
493:   options.

495:   Collective on TaoLineSearch

497:   Input Paremeter:
498: . ls - the TaoLineSearch context

500:   Options Database Keys:
501: + -tao_ls_type <type> - The algorithm that TAO uses (more-thuente, gpcg, unit)
502: . -tao_ls_ftol <tol> - tolerance for sufficient decrease
503: . -tao_ls_gtol <tol> - tolerance for curvature condition
504: . -tao_ls_rtol <tol> - relative tolerance for acceptable step
505: . -tao_ls_stepmin <step> - minimum steplength allowed
506: . -tao_ls_stepmax <step> - maximum steplength allowed
507: . -tao_ls_max_funcs <n> - maximum number of function evaluations allowed
508: - -tao_ls_view - display line-search results to standard output

510:   Level: beginner
511: @*/
512: PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
513: {
515:   const char     *default_type=TAOLINESEARCHMT;
516:   char           type[256];
517:   PetscBool      flg;

521:   PetscObjectOptionsBegin((PetscObject)ls);
522:   if (!TaoLineSearchInitialized) {
523:     TaoLineSearchInitializePackage();
524:   }
525:   if (((PetscObject)ls)->type_name) {
526:     default_type = ((PetscObject)ls)->type_name;
527:   }
528:   /* Check for type from options */
529:   PetscOptionsFList("-tao_ls_type","Tao Line Search type","TaoLineSearchSetType",TaoLineSearchList,default_type,type,256,&flg);
530:   if (flg) {
531:     TaoLineSearchSetType(ls,type);
532:   } else if (!((PetscObject)ls)->type_name) {
533:     TaoLineSearchSetType(ls,default_type);
534:   }

536:   PetscOptionsInt("-tao_ls_max_funcs","max function evals in line search","",ls->max_funcs,&ls->max_funcs,NULL);
537:   PetscOptionsReal("-tao_ls_ftol","tol for sufficient decrease","",ls->ftol,&ls->ftol,NULL);
538:   PetscOptionsReal("-tao_ls_gtol","tol for curvature condition","",ls->gtol,&ls->gtol,NULL);
539:   PetscOptionsReal("-tao_ls_rtol","relative tol for acceptable step","",ls->rtol,&ls->rtol,NULL);
540:   PetscOptionsReal("-tao_ls_stepmin","lower bound for step","",ls->stepmin,&ls->stepmin,NULL);
541:   PetscOptionsReal("-tao_ls_stepmax","upper bound for step","",ls->stepmax,&ls->stepmax,NULL);
542:   if (ls->ops->setfromoptions) {
543:     (*ls->ops->setfromoptions)(PetscOptionsObject,ls);
544:   }
545:   PetscOptionsEnd();
546:   return(0);
547: }

551: /*@C
552:   TaoLineSearchGetType - Gets the current line search algorithm

554:   Not Collective

556:   Input Parameter:
557: . ls - the TaoLineSearch context

559:   Output Paramter:
560: . type - the line search algorithm in effect

562:   Level: developer

564: @*/
565: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, const TaoLineSearchType *type)
566: {
570:   *type = ((PetscObject)ls)->type_name;
571:   return(0);
572: }

576: /*@
577:   TaoLineSearchGetNumberFunctionEvaluations - Gets the number of function and gradient evaluation
578:   routines used by the line search in last application (not cumulative).

580:   Not Collective

582:   Input Parameter:
583: . ls - the TaoLineSearch context

585:   Output Parameters:
586: + nfeval   - number of function evaluations
587: . ngeval   - number of gradient evaluations
588: - nfgeval  - number of function/gradient evaluations

590:   Level: intermediate

592:   Note:
593:   If the line search is using the Tao objective and gradient
594:   routines directly (see TaoLineSearchUseTaoRoutines()), then TAO
595:   is already counting the number of evaluations.

597: @*/
598: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
599: {
602:   *nfeval = ls->nfeval;
603:   *ngeval = ls->ngeval;
604:   *nfgeval = ls->nfgeval;
605:   return(0);
606: }

610: /*@
611:   TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
612:   Tao evaluation routines.

614:   Not Collective

616:   Input Parameter:
617: . ls - the TaoLineSearch context

619:   Output Parameter:
620: . flg - PETSC_TRUE if the line search is using Tao evaluation routines,
621:         otherwise PETSC_FALSE

623:   Level: developer
624: @*/
625: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
626: {
629:   *flg = ls->usetaoroutines;
630:   return(0);
631: }

635: /*@C
636:   TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search

638:   Logically Collective on TaoLineSearch

640:   Input Parameter:
641: + ls - the TaoLineSearch context
642: . func - the objective function evaluation routine
643: - ctx - the (optional) user-defined context for private data

645:   Calling sequence of func:
646: $      func (TaoLinesearch ls, Vec x, PetscReal *f, void *ctx);

648: + x - input vector
649: . f - function value
650: - ctx (optional) user-defined context

652:   Level: beginner

654:   Note:
655:   Use this routine only if you want the line search objective
656:   evaluation routine to be different from the Tao's objective
657:   evaluation routine. If you use this routine you must also set
658:   the line search gradient and/or function/gradient routine.

660:   Note:
661:   Some algorithms (lcl, gpcg) set their own objective routine for the
662:   line search, application programmers should be wary of overriding the
663:   default objective routine.

665: .seealso: TaoLineSearchCreate(), TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
666: @*/
667: PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal*, void*), void *ctx)
668: {

672:   ls->ops->computeobjective=func;
673:   if (ctx) ls->userctx_func=ctx;
674:   ls->usetaoroutines=PETSC_FALSE;
675:   return(0);
676: }

680: /*@C
681:   TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search

683:   Logically Collective on TaoLineSearch

685:   Input Parameter:
686: + ls - the TaoLineSearch context
687: . func - the gradient evaluation routine
688: - ctx - the (optional) user-defined context for private data

690:   Calling sequence of func:
691: $      func (TaoLinesearch ls, Vec x, Vec g, void *ctx);

693: + x - input vector
694: . g - gradient vector
695: - ctx (optional) user-defined context

697:   Level: beginner

699:   Note:
700:   Use this routine only if you want the line search gradient
701:   evaluation routine to be different from the Tao's gradient
702:   evaluation routine. If you use this routine you must also set
703:   the line search function and/or function/gradient routine.

705:   Note:
706:   Some algorithms (lcl, gpcg) set their own gradient routine for the
707:   line search, application programmers should be wary of overriding the
708:   default gradient routine.

710: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
711: @*/
712: PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec g, void*), void *ctx)
713: {
716:   ls->ops->computegradient=func;
717:   if (ctx) ls->userctx_grad=ctx;
718:   ls->usetaoroutines=PETSC_FALSE;
719:   return(0);
720: }

724: /*@C
725:   TaoLineSearchSetObjectiveAndGradientRoutine - Sets the objective/gradient evaluation routine for the line search

727:   Logically Collective on TaoLineSearch

729:   Input Parameter:
730: + ls - the TaoLineSearch context
731: . func - the objective and gradient evaluation routine
732: - ctx - the (optional) user-defined context for private data

734:   Calling sequence of func:
735: $      func (TaoLinesearch ls, Vec x, PetscReal *f, Vec g, void *ctx);

737: + x - input vector
738: . f - function value
739: . g - gradient vector
740: - ctx (optional) user-defined context

742:   Level: beginner

744:   Note:
745:   Use this routine only if you want the line search objective and gradient
746:   evaluation routines to be different from the Tao's objective
747:   and gradient evaluation routines.

749:   Note:
750:   Some algorithms (lcl, gpcg) set their own objective routine for the
751:   line search, application programmers should be wary of overriding the
752:   default objective routine.

754: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetGradientRoutine(), TaoLineSearchUseTaoRoutines()
755: @*/
756: PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal *, Vec g, void*), void *ctx)
757: {
760:   ls->ops->computeobjectiveandgradient=func;
761:   if (ctx) ls->userctx_funcgrad=ctx;
762:   ls->usetaoroutines = PETSC_FALSE;
763:   return(0);
764: }

768: /*@C
769:   TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
770:   (gradient'*stepdirection) evaluation routine for the line search.
771:   Sometimes it is more efficient to compute the inner product of the gradient
772:   and the step direction than it is to compute the gradient, and this is all
773:   the line search typically needs of the gradient.

775:   Logically Collective on TaoLineSearch

777:   Input Parameter:
778: + ls - the TaoLineSearch context
779: . func - the objective and gradient evaluation routine
780: - ctx - the (optional) user-defined context for private data

782:   Calling sequence of func:
783: $      func (TaoLinesearch ls, Vec x, PetscReal *f, PetscReal *gts, void *ctx);

785: + x - input vector
786: . s - step direction
787: . f - function value
788: . gts - inner product of gradient and step direction vectors
789: - ctx (optional) user-defined context

791:   Note: The gradient will still need to be computed at the end of the line
792:   search, so you will still need to set a line search gradient evaluation
793:   routine

795:   Note: Bounded line searches (those used in bounded optimization algorithms)
796:   don't use g's directly, but rather (g'x - g'x0)/steplength.  You can get the
797:   x0 and steplength with TaoLineSearchGetStartingVector() and TaoLineSearchGetStepLength()

799:   Level: advanced

801:   Note:
802:   Some algorithms (lcl, gpcg) set their own objective routine for the
803:   line search, application programmers should be wary of overriding the
804:   default objective routine.

806: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjective(), TaoLineSearchSetGradient(), TaoLineSearchUseTaoRoutines()
807: @*/
808: PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec s, PetscReal *, PetscReal *, void*), void *ctx)
809: {
812:   ls->ops->computeobjectiveandgts=func;
813:   if (ctx) ls->userctx_funcgts=ctx;
814:   ls->usegts = PETSC_TRUE;
815:   ls->usetaoroutines=PETSC_FALSE;
816:   return(0);
817: }

821: /*@C
822:   TaoLineSearchUseTaoRoutines - Informs the TaoLineSearch to use the
823:   objective and gradient evaluation routines from the given Tao object.

825:   Logically Collective on TaoLineSearch

827:   Input Parameter:
828: + ls - the TaoLineSearch context
829: - ts - the Tao context with defined objective/gradient evaluation routines

831:   Level: developer

833: .seealso: TaoLineSearchCreate()
834: @*/
835: PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
836: {
840:   ls->tao = ts;
841:   ls->usetaoroutines=PETSC_TRUE;
842:   return(0);
843: }

847: /*@
848:   TaoLineSearchComputeObjective - Computes the objective function value at a given point

850:   Collective on TaoLineSearch

852:   Input Parameters:
853: + ls - the TaoLineSearch context
854: - x - input vector

856:   Output Parameter:
857: . f - Objective value at X

859:   Notes: TaoLineSearchComputeObjective() is typically used within line searches
860:   so most users would not generally call this routine themselves.

862:   Level: developer

864: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
865: @*/
866: PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
867: {
869:   Vec            gdummy;
870:   PetscReal      gts;

877:   if (ls->usetaoroutines) {
878:     TaoComputeObjective(ls->tao,x,f);
879:   } else {
880:     PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
881:     if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient && !ls->ops->computeobjectiveandgts) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
882:     PetscStackPush("TaoLineSearch user objective routine");
883:     if (ls->ops->computeobjective) {
884:       (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
885:     } else if (ls->ops->computeobjectiveandgradient) {
886:       VecDuplicate(x,&gdummy);
887:       (*ls->ops->computeobjectiveandgradient)(ls,x,f,gdummy,ls->userctx_funcgrad);
888:       VecDestroy(&gdummy);
889:     } else {
890:       (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,&gts,ls->userctx_funcgts);
891:     }
892:     PetscStackPop;
893:     PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
894:   }
895:   ls->nfeval++;
896:   return(0);
897: }

901: /*@
902:   TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point

904:   Collective on Tao

906:   Input Parameters:
907: + ls - the TaoLineSearch context
908: - x - input vector

910:   Output Parameter:
911: + f - Objective value at X
912: - g - Gradient vector at X

914:   Notes: TaoLineSearchComputeObjectiveAndGradient() is typically used within line searches
915:   so most users would not generally call this routine themselves.

917:   Level: developer

919: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
920: @*/
921: PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
922: {

932:   if (ls->usetaoroutines) {
933:       TaoComputeObjectiveAndGradient(ls->tao,x,f,g);
934:   } else {
935:     PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
936:     if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
937:     if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient function set");

939:     PetscStackPush("TaoLineSearch user objective/gradient routine");
940:     if (ls->ops->computeobjectiveandgradient) {
941:       (*ls->ops->computeobjectiveandgradient)(ls,x,f,g,ls->userctx_funcgrad);
942:     } else {
943:       (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
944:       (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
945:     }
946:     PetscStackPop;
947:     PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
948:     PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
949:   }
950:   ls->nfgeval++;
951:   return(0);
952: }

956: /*@
957:   TaoLineSearchComputeGradient - Computes the gradient of the objective function

959:   Collective on TaoLineSearch

961:   Input Parameters:
962: + ls - the TaoLineSearch context
963: - x - input vector

965:   Output Parameter:
966: . g - gradient vector

968:   Notes: TaoComputeGradient() is typically used within line searches
969:   so most users would not generally call this routine themselves.

971:   Level: developer

973: .seealso: TaoLineSearchComputeObjective(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetGradient()
974: @*/
975: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
976: {
978:   PetscReal      fdummy;

986:   if (ls->usetaoroutines) {
987:     TaoComputeGradient(ls->tao,x,g);
988:   } else {
989:     PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
990:     if (!ls->ops->computegradient && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient functions set");
991:     PetscStackPush("TaoLineSearch user gradient routine");
992:     if (ls->ops->computegradient) {
993:       (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
994:     } else {
995:       (*ls->ops->computeobjectiveandgradient)(ls,x,&fdummy,g,ls->userctx_funcgrad);
996:     }
997:     PetscStackPop;
998:     PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
999:   }
1000:   ls->ngeval++;
1001:   return(0);
1002: }

1006: /*@
1007:   TaoLineSearchComputeObjectiveAndGTS - Computes the objective function value and inner product of gradient and step direction at a given point

1009:   Collective on Tao

1011:   Input Parameters:
1012: + ls - the TaoLineSearch context
1013: - x - input vector

1015:   Output Parameter:
1016: + f - Objective value at X
1017: - gts - inner product of gradient and step direction at X

1019:   Notes: TaoLineSearchComputeObjectiveAndGTS() is typically used within line searches
1020:   so most users would not generally call this routine themselves.

1022:   Level: developer

1024: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
1025: @*/
1026: PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
1027: {
1035:   PetscLogEventBegin(TaoLineSearch_EvalEvent,ls,0,0,0);
1036:   if (!ls->ops->computeobjectiveandgts) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective and gts function set");
1037:   PetscStackPush("TaoLineSearch user objective/gts routine");
1038:   (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,gts,ls->userctx_funcgts);
1039:   PetscStackPop;
1040:   PetscLogEventEnd(TaoLineSearch_EvalEvent,ls,0,0,0);
1041:   PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
1042:   ls->nfeval++;
1043:   return(0);
1044: }

1048: /*@
1049:   TaoLineSearchGetSolution - Returns the solution to the line search

1051:   Collective on TaoLineSearch

1053:   Input Parameter:
1054: . ls - the TaoLineSearch context

1056:   Output Parameter:
1057: + x - the new solution
1058: . f - the objective function value at x
1059: . g - the gradient at x
1060: . steplength - the multiple of the step direction taken by the line search
1061: - reason - the reason why the line search terminated

1063:   reason will be set to one of:

1065: + TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
1066: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
1067: . TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
1068: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
1069: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
1070: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
1071: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance

1073: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
1074: . TAOLINESEARCH_HALTED_OTHER - any other reason

1076: + TAOLINESEARCH_SUCCESS - successful line search

1078:   Level: developer

1080: @*/
1081: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
1082: {

1091:   if (ls->new_x) {
1092:     VecCopy(ls->new_x,x);
1093:   }
1094:   *f = ls->new_f;
1095:   if (ls->new_g) {
1096:     VecCopy(ls->new_g,g);
1097:   }
1098:   if (steplength) {
1099:     *steplength=ls->step;
1100:   }
1101:   *reason = ls->reason;
1102:   return(0);
1103: }

1107: /*@
1108:   TaoLineSearchGetStartingVector - Gets a the initial point of the line
1109:   search.

1111:   Not Collective

1113:   Input Parameter:
1114: . ls - the TaoLineSearch context

1116:   Output Parameter:
1117: . x - The initial point of the line search

1119:   Level: intermediate
1120: @*/
1121: PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1122: {
1125:   if (x) {
1126:     *x = ls->start_x;
1127:   }
1128:   return(0);
1129: }

1133: /*@
1134:   TaoLineSearchGetStepDirection - Gets the step direction of the line
1135:   search.

1137:   Not Collective

1139:   Input Parameter:
1140: . ls - the TaoLineSearch context

1142:   Output Parameter:
1143: . s - the step direction of the line search

1145:   Level: advanced
1146: @*/
1147: PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1148: {
1151:   if (s) {
1152:     *s = ls->stepdirection;
1153:   }
1154:   return(0);

1156: }

1160: /*@
1161:   TaoLineSearchGetFullStepObjective - Returns the objective function value at the full step.  Useful for some minimization algorithms.

1163:   Not Collective

1165:   Input Parameter:
1166: . ls - the TaoLineSearch context

1168:   Output Parameter:
1169: . f - the objective value at the full step length

1171:   Level: developer
1172: @*/

1174: PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch ls, PetscReal *f_fullstep)
1175: {
1178:   *f_fullstep = ls->f_fullstep;
1179:   return(0);
1180: }

1184: /*@
1185:   TaoLineSearchSetVariableBounds - Sets the upper and lower bounds.

1187:   Logically Collective on Tao

1189:   Input Parameters:
1190: + ls - the TaoLineSearch context
1191: . xl  - vector of lower bounds
1192: - xu  - vector of upper bounds

1194:   Note: If the variable bounds are not set with this routine, then
1195:   PETSC_NINFINITY and PETSC_INFINITY are assumed

1197:   Level: beginner

1199: .seealso: TaoSetVariableBounds(), TaoLineSearchCreate()
1200: @*/
1201: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls,Vec xl, Vec xu)
1202: {
1207:   ls->lower = xl;
1208:   ls->upper = xu;
1209:   ls->bounded = 1;
1210:   return(0);
1211: }

1215: /*@
1216:   TaoLineSearchSetInitialStepLength - Sets the initial step length of a line
1217:   search.  If this value is not set then 1.0 is assumed.

1219:   Logically Collective on TaoLineSearch

1221:   Input Parameters:
1222: + ls - the TaoLineSearch context
1223: - s - the initial step size

1225:   Level: intermediate

1227: .seealso: TaoLineSearchGetStepLength(), TaoLineSearchApply()
1228: @*/
1229: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls,PetscReal s)
1230: {
1233:   ls->initstep = s;
1234:   return(0);
1235: }

1239: /*@
1240:   TaoLineSearchGetStepLength - Get the current step length

1242:   Not Collective

1244:   Input Parameters:
1245: . ls - the TaoLineSearch context

1247:   Output Parameters
1248: . s - the current step length

1250:   Level: beginner

1252: .seealso: TaoLineSearchSetInitialStepLength(), TaoLineSearchApply()
1253: @*/
1254: PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls,PetscReal *s)
1255: {
1258:   *s = ls->step;
1259:   return(0);
1260: }

1264: /*MC
1265:    TaoLineSearchRegister - Adds a line-search algorithm to the registry

1267:    Not collective

1269:    Input Parameters:
1270: +  sname - name of a new user-defined solver
1271: -  func - routine to Create method context

1273:    Notes:
1274:    TaoLineSearchRegister() may be called multiple times to add several user-defined solvers.

1276:    Sample usage:
1277: .vb
1278:    TaoLineSearchRegister("my_linesearch",MyLinesearchCreate);
1279: .ve

1281:    Then, your solver can be chosen with the procedural interface via
1282: $     TaoLineSearchSetType(ls,"my_linesearch")
1283:    or at runtime via the option
1284: $     -tao_ls_type my_linesearch

1286:    Level: developer

1288: .seealso: TaoLineSearchRegisterDestroy()
1289: M*/
1290: PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch))
1291: {
1294:   PetscFunctionListAdd(&TaoLineSearchList, sname, (void (*)(void))func);
1295:   return(0);
1296: }

1300: /*@C
1301:    TaoLineSearchRegisterDestroy - Frees the list of line-search algorithms that were
1302:    registered by TaoLineSearchRegister().

1304:    Not Collective

1306:    Level: developer

1308: .seealso: TaoLineSearchRegister()
1309: @*/
1310: PetscErrorCode TaoLineSearchRegisterDestroy(void)
1311: {
1314:   PetscFunctionListDestroy(&TaoLineSearchList);
1315:   TaoLineSearchInitialized = PETSC_FALSE;
1316:   return(0);
1317: }

1321: /*@C
1322:    TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1323:    for all TaoLineSearch options in the database.


1326:    Collective on TaoLineSearch

1328:    Input Parameters:
1329: +  ls - the TaoLineSearch solver context
1330: -  prefix - the prefix string to prepend to all line search requests

1332:    Notes:
1333:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1334:    The first character of all runtime options is AUTOMATICALLY the hyphen.


1337:    Level: advanced

1339: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1340: @*/
1341: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1342: {
1343:   return PetscObjectAppendOptionsPrefix((PetscObject)ls,p);
1344: }

1348: /*@C
1349:   TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1350:   TaoLineSearch options in the database

1352:   Not Collective

1354:   Input Parameters:
1355: . ls - the TaoLineSearch context

1357:   Output Parameters:
1358: . prefix - pointer to the prefix string used is returned

1360:   Notes: On the fortran side, the user should pass in a string 'prefix' of
1361:   sufficient length to hold the prefix.

1363:   Level: advanced

1365: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchAppendOptionsPrefix()
1366: @*/
1367: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1368: {
1369:   return PetscObjectGetOptionsPrefix((PetscObject)ls,p);
1370: }

1374: /*@C
1375:    TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1376:    TaoLineSearch options in the database.


1379:    Logically Collective on TaoLineSearch

1381:    Input Parameters:
1382: +  ls - the TaoLineSearch context
1383: -  prefix - the prefix string to prepend to all TAO option requests

1385:    Notes:
1386:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1387:    The first character of all runtime options is AUTOMATICALLY the hyphen.

1389:    For example, to distinguish between the runtime options for two
1390:    different line searches, one could call
1391: .vb
1392:       TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1393:       TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1394: .ve

1396:    This would enable use of different options for each system, such as
1397: .vb
1398:       -sys1_tao_ls_type mt
1399:       -sys2_tao_ls_type armijo
1400: .ve

1402:    Level: advanced

1404: .seealso: TaoLineSearchAppendOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1405: @*/

1407: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1408: {
1409:   return PetscObjectSetOptionsPrefix((PetscObject)ls,p);
1410: }