Actual source code: taolinesearch.c

petsc-3.12.5 2020-03-29
Report Typos and Errors
  1:  #include <petsctaolinesearch.h>
  2:  #include <petsc/private/taolinesearchimpl.h>

  4: PetscFunctionList TaoLineSearchList = NULL;

  6: PetscClassId TAOLINESEARCH_CLASSID=0;

  8: PetscLogEvent TAOLINESEARCH_Apply;
  9: PetscLogEvent TAOLINESEARCH_Eval;

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

 14:   Collective on TaoLineSearch

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

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

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

 31:   Level: beginner

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

 36: PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
 37: {
 38:   PetscErrorCode          ierr;
 39:   PetscBool               isascii, isstring;
 40:   TaoLineSearchType       type;

 44:   if (!viewer) {
 45:     PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer);
 46:   }

 50:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
 51:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
 52:   if (isascii) {
 53:     PetscObjectPrintClassNamePrefixType((PetscObject)ls, viewer);
 54:     if (ls->ops->view) {
 55:       PetscViewerASCIIPushTab(viewer);
 56:       (*ls->ops->view)(ls,viewer);
 57:       PetscViewerASCIIPopTab(viewer);
 58:     }
 59:     PetscViewerASCIIPushTab(viewer);
 60:     PetscViewerASCIIPrintf(viewer,"maximum function evaluations=%D\n",ls->max_funcs);
 61:     PetscViewerASCIIPrintf(viewer,"tolerances: ftol=%g, rtol=%g, gtol=%g\n",(double)ls->ftol,(double)ls->rtol,(double)ls->gtol);
 62:     PetscViewerASCIIPrintf(viewer,"total number of function evaluations=%D\n",ls->nfeval);
 63:     PetscViewerASCIIPrintf(viewer,"total number of gradient evaluations=%D\n",ls->ngeval);
 64:     PetscViewerASCIIPrintf(viewer,"total number of function/gradient evaluations=%D\n",ls->nfgeval);

 66:     if (ls->bounded) {
 67:       PetscViewerASCIIPrintf(viewer,"using variable bounds\n");
 68:     }
 69:     PetscViewerASCIIPrintf(viewer,"Termination reason: %d\n",(int)ls->reason);
 70:     PetscViewerASCIIPopTab(viewer);
 71:   } else if (isstring) {
 72:     TaoLineSearchGetType(ls,&type);
 73:     PetscViewerStringSPrintf(viewer," %-3.3s",type);
 74:   }
 75:   return(0);
 76: }

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

 82:   Collective

 84:   Input Parameter:
 85: . comm - MPI communicator

 87:   Output Parameter:
 88: . newls - the new TaoLineSearch context

 90:   Available methods include:
 91: + more-thuente
 92: . gpcg
 93: - unit - Do not perform any line search


 96:    Options Database Keys:
 97: .   -tao_ls_type - select which method TAO should use

 99:    Level: beginner

101: .seealso: TaoLineSearchSetType(), TaoLineSearchApply(), TaoLineSearchDestroy()
102: @*/

104: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
105: {
107:   TaoLineSearch  ls;

111:   *newls = NULL;

113:   TaoLineSearchInitializePackage();

115:   PetscHeaderCreate(ls,TAOLINESEARCH_CLASSID,"TaoLineSearch","Linesearch","Tao",comm,TaoLineSearchDestroy,TaoLineSearchView);
116:   ls->bounded = 0;
117:   ls->max_funcs=30;
118:   ls->ftol = 0.0001;
119:   ls->gtol = 0.9;
120: #if defined(PETSC_USE_REAL_SINGLE)
121:   ls->rtol = 1.0e-5;
122: #else
123:   ls->rtol = 1.0e-10;
124: #endif
125:   ls->stepmin=1.0e-20;
126:   ls->stepmax=1.0e+20;
127:   ls->step=1.0;
128:   ls->nfeval=0;
129:   ls->ngeval=0;
130:   ls->nfgeval=0;

132:   ls->ops->computeobjective=0;
133:   ls->ops->computegradient=0;
134:   ls->ops->computeobjectiveandgradient=0;
135:   ls->ops->computeobjectiveandgts=0;
136:   ls->ops->setup=0;
137:   ls->ops->apply=0;
138:   ls->ops->view=0;
139:   ls->ops->setfromoptions=0;
140:   ls->ops->reset=0;
141:   ls->ops->destroy=0;
142:   ls->ops->monitor=0;
143:   ls->usemonitor=PETSC_FALSE;
144:   ls->setupcalled=PETSC_FALSE;
145:   ls->usetaoroutines=PETSC_FALSE;
146:   *newls = ls;
147:   return(0);
148: }

150: /*@
151:   TaoLineSearchSetUp - Sets up the internal data structures for the later use
152:   of a Tao solver

154:   Collective on ls

156:   Input Parameters:
157: . ls - the TaoLineSearch context

159:   Notes:
160:   The user will not need to explicitly call TaoLineSearchSetUp(), as it will
161:   automatically be called in TaoLineSearchSolve().  However, if the user
162:   desires to call it explicitly, it should come after TaoLineSearchCreate()
163:   but before TaoLineSearchApply().

165:   Level: developer

167: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
168: @*/

170: PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
171: {
173:   const char     *default_type=TAOLINESEARCHMT;
174:   PetscBool      flg;

178:   if (ls->setupcalled) return(0);
179:   if (!((PetscObject)ls)->type_name) {
180:     TaoLineSearchSetType(ls,default_type);
181:   }
182:   if (ls->ops->setup) {
183:     (*ls->ops->setup)(ls);
184:   }
185:   if (ls->usetaoroutines) {
186:     TaoIsObjectiveDefined(ls->tao,&flg);
187:     ls->hasobjective = flg;
188:     TaoIsGradientDefined(ls->tao,&flg);
189:     ls->hasgradient = flg;
190:     TaoIsObjectiveAndGradientDefined(ls->tao,&flg);
191:     ls->hasobjectiveandgradient = flg;
192:   } else {
193:     if (ls->ops->computeobjective) {
194:       ls->hasobjective = PETSC_TRUE;
195:     } else {
196:       ls->hasobjective = PETSC_FALSE;
197:     }
198:     if (ls->ops->computegradient) {
199:       ls->hasgradient = PETSC_TRUE;
200:     } else {
201:       ls->hasgradient = PETSC_FALSE;
202:     }
203:     if (ls->ops->computeobjectiveandgradient) {
204:       ls->hasobjectiveandgradient = PETSC_TRUE;
205:     } else {
206:       ls->hasobjectiveandgradient = PETSC_FALSE;
207:     }
208:   }
209:   ls->setupcalled = PETSC_TRUE;
210:   return(0);
211: }

213: /*@
214:   TaoLineSearchReset - Some line searches may carry state information
215:   from one TaoLineSearchApply() to the next.  This function resets this
216:   state information.

218:   Collective on TaoLineSearch

220:   Input Parameter:
221: . ls - the TaoLineSearch context

223:   Level: developer

225: .seealso: TaoLineSearchCreate(), TaoLineSearchApply()
226: @*/
227: PetscErrorCode TaoLineSearchReset(TaoLineSearch ls)
228: {

233:   if (ls->ops->reset) {
234:     (*ls->ops->reset)(ls);
235:   }
236:   return(0);
237: }

239: /*@
240:   TaoLineSearchDestroy - Destroys the TAO context that was created with
241:   TaoLineSearchCreate()

243:   Collective on TaoLineSearch

245:   Input Parameter
246: . ls - the TaoLineSearch context

248:   Level: beginner

250: .seealse: TaoLineSearchCreate(), TaoLineSearchSolve()
251: @*/
252: PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
253: {

257:   if (!*ls) return(0);
259:   if (--((PetscObject)*ls)->refct > 0) {*ls=0; return(0);}
260:   VecDestroy(&(*ls)->stepdirection);
261:   VecDestroy(&(*ls)->start_x);
262:   if ((*ls)->ops->destroy) {
263:     (*(*ls)->ops->destroy)(*ls);
264:   }
265:   if ((*ls)->usemonitor) {
266:     PetscViewerDestroy(&(*ls)->viewer);
267:   }
268:   PetscHeaderDestroy(ls);
269:   return(0);
270: }

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

275:   Collective on TaoLineSearch

277:   Input Parameters:
278: + ls - the Tao context
279: . x - The current solution (on output x contains the new solution determined by the line search)
280: . f - objective function value at current solution (on output contains the objective function value at new solution)
281: . g - gradient evaluated at x (on output contains the gradient at new solution)
282: - s - search direction

284:   Output Parameters:
285: + x - new solution
286: . f - objective function value at x
287: . g - gradient vector at x
288: . steplength - scalar multiplier of s used ( x = x0 + steplength * x )
289: - reason - reason why the line-search stopped

291:   reason will be set to one of:

293: + TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
294: . TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
295: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
296: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
297: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
298: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
299: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance
300: . TAOLINESEARCH_HALTED_USER - user can set this reason to stop line search
301: . TAOLINESEARCH_HALTED_OTHER - any other reason
302: - TAOLINESEARCH_SUCCESS - successful line search

304:   Note:
305:   The algorithm developer must set up the TaoLineSearch with calls to
306:   TaoLineSearchSetObjectiveRoutine() and TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), or TaoLineSearchUseTaoRoutines()

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

313:   Level: beginner

315:   .seealso: TaoLineSearchCreate(), TaoLineSearchSetType(), TaoLineSearchSetInitialStepLength(), TaoAddLineSearchCounts()
316:  @*/

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

324:   *reason = TAOLINESEARCH_CONTINUE_ITERATING;
334:   VecGetOwnershipRange(x, &low1, &high1);
335:   VecGetOwnershipRange(g, &low2, &high2);
336:   VecGetOwnershipRange(s, &low3, &high3);
337:   if ( low1!= low2 || low1!= low3 || high1!= high2 || high1!= high3) SETERRQ(PETSC_COMM_SELF,1,"InCompatible vector local lengths");

339:   PetscObjectReference((PetscObject)s);
340:   VecDestroy(&ls->stepdirection);
341:   ls->stepdirection = s;

343:   TaoLineSearchSetUp(ls);
344:   if (!ls->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search Object does not have 'apply' routine");
345:   ls->nfeval=0;
346:   ls->ngeval=0;
347:   ls->nfgeval=0;
348:   /* Check parameter values */
349:   if (ls->ftol < 0.0) {
350:     PetscInfo1(ls,"Bad Line Search Parameter: ftol (%g) < 0\n",(double)ls->ftol);
351:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
352:   }
353:   if (ls->rtol < 0.0) {
354:     PetscInfo1(ls,"Bad Line Search Parameter: rtol (%g) < 0\n",(double)ls->rtol);
355:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
356:   }
357:   if (ls->gtol < 0.0) {
358:     PetscInfo1(ls,"Bad Line Search Parameter: gtol (%g) < 0\n",(double)ls->gtol);
359:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
360:   }
361:   if (ls->stepmin < 0.0) {
362:     PetscInfo1(ls,"Bad Line Search Parameter: stepmin (%g) < 0\n",(double)ls->stepmin);
363:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
364:   }
365:   if (ls->stepmax < ls->stepmin) {
366:     PetscInfo2(ls,"Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n",(double)ls->stepmin,(double)ls->stepmax);
367:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
368:   }
369:   if (ls->max_funcs < 0) {
370:     PetscInfo1(ls,"Bad Line Search Parameter: max_funcs (%D) < 0\n",ls->max_funcs);
371:     *reason=TAOLINESEARCH_FAILED_BADPARAMETER;
372:   }
373:   if (PetscIsInfOrNanReal(*f)) {
374:     PetscInfo1(ls,"Initial Line Search Function Value is Inf or Nan (%g)\n",(double)*f);
375:     *reason=TAOLINESEARCH_FAILED_INFORNAN;
376:   }

378:   PetscObjectReference((PetscObject)x);
379:   VecDestroy(&ls->start_x);
380:   ls->start_x = x;

382:   PetscLogEventBegin(TAOLINESEARCH_Apply,ls,0,0,0);
383:   (*ls->ops->apply)(ls,x,f,g,s);
384:   PetscLogEventEnd(TAOLINESEARCH_Apply, ls, 0,0,0);
385:   *reason=ls->reason;
386:   ls->new_f = *f;

388:   if (steplength) {
389:     *steplength=ls->step;
390:   }

392:   TaoLineSearchViewFromOptions(ls,NULL,"-tao_ls_view");
393:   return(0);
394: }

396: /*@C
397:    TaoLineSearchSetType - Sets the algorithm used in a line search

399:    Collective on TaoLineSearch

401:    Input Parameters:
402: +  ls - the TaoLineSearch context
403: -  type - a known method

405:   Available methods include:
406: + more-thuente
407: . gpcg
408: - unit - Do not perform any line search


411:   Options Database Keys:
412: .   -tao_ls_type - select which method TAO should use

414:   Level: beginner


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

419: @*/

421: PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, TaoLineSearchType type)
422: {
424:   PetscErrorCode (*r)(TaoLineSearch);
425:   PetscBool      flg;

430:   PetscObjectTypeCompare((PetscObject)ls, type, &flg);
431:   if (flg) return(0);

433:   PetscFunctionListFind(TaoLineSearchList,type, (void (**)(void)) &r);
434:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested TaoLineSearch type %s",type);
435:   if (ls->ops->destroy) {
436:     (*(ls)->ops->destroy)(ls);
437:   }
438:   ls->max_funcs=30;
439:   ls->ftol = 0.0001;
440:   ls->gtol = 0.9;
441: #if defined(PETSC_USE_REAL_SINGLE)
442:   ls->rtol = 1.0e-5;
443: #else
444:   ls->rtol = 1.0e-10;
445: #endif
446:   ls->stepmin=1.0e-20;
447:   ls->stepmax=1.0e+20;

449:   ls->nfeval=0;
450:   ls->ngeval=0;
451:   ls->nfgeval=0;
452:   ls->ops->setup=0;
453:   ls->ops->apply=0;
454:   ls->ops->view=0;
455:   ls->ops->setfromoptions=0;
456:   ls->ops->destroy=0;
457:   ls->setupcalled = PETSC_FALSE;
458:   (*r)(ls);
459:   PetscObjectChangeTypeName((PetscObject)ls, type);
460:   return(0);
461: }

463: /*@C
464:   TaoLineSearchMonitor - Monitor the line search steps. This routine will otuput the
465:   iteration number, step length, and function value before calling the implementation 
466:   specific monitor.

468:    Input Parameters:
469: +  ls - the TaoLineSearch context
470: .  its - the current iterate number (>=0)
471: .  f - the current objective function value
472: -  step - the step length

474:    Options Database Key:
475: .  -tao_ls_monitor - Use the default monitor, which prints statistics to standard output

477:    Level: developer

479: @*/
480: PetscErrorCode TaoLineSearchMonitor(TaoLineSearch ls, PetscInt its, PetscReal f, PetscReal step)
481: {
483:   PetscInt       tabs;

487:   if (ls->usemonitor) {
488:     PetscViewerASCIIGetTab(ls->viewer, &tabs);
489:     PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel);
490:     PetscViewerASCIIPrintf(ls->viewer, "%3D LS", its);
491:     PetscViewerASCIIPrintf(ls->viewer, "  Function value: %g,", (double)f);
492:     PetscViewerASCIIPrintf(ls->viewer, "  Step length: %g\n", (double)step);
493:     if (ls->ops->monitor && its > 0) {
494:       PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel + 3);
495:       (*ls->ops->monitor)(ls);
496:     }
497:     PetscViewerASCIISetTab(ls->viewer, tabs);
498:   }
499:   return(0);
500: }

502: /*@
503:   TaoLineSearchSetFromOptions - Sets various TaoLineSearch parameters from user
504:   options.

506:   Collective on TaoLineSearch

508:   Input Paremeter:
509: . ls - the TaoLineSearch context

511:   Options Database Keys:
512: + -tao_ls_type <type> - The algorithm that TAO uses (more-thuente, gpcg, unit)
513: . -tao_ls_ftol <tol> - tolerance for sufficient decrease
514: . -tao_ls_gtol <tol> - tolerance for curvature condition
515: . -tao_ls_rtol <tol> - relative tolerance for acceptable step
516: . -tao_ls_stepmin <step> - minimum steplength allowed
517: . -tao_ls_stepmax <step> - maximum steplength allowed
518: . -tao_ls_max_funcs <n> - maximum number of function evaluations allowed
519: - -tao_ls_view - display line-search results to standard output

521:   Level: beginner
522: @*/
523: PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
524: {
526:   const char     *default_type=TAOLINESEARCHMT;
527:   char           type[256],monfilename[PETSC_MAX_PATH_LEN];
528:   PetscViewer    monviewer;
529:   PetscBool      flg;

533:   PetscObjectOptionsBegin((PetscObject)ls);
534:   if (((PetscObject)ls)->type_name) {
535:     default_type = ((PetscObject)ls)->type_name;
536:   }
537:   /* Check for type from options */
538:   PetscOptionsFList("-tao_ls_type","Tao Line Search type","TaoLineSearchSetType",TaoLineSearchList,default_type,type,256,&flg);
539:   if (flg) {
540:     TaoLineSearchSetType(ls,type);
541:   } else if (!((PetscObject)ls)->type_name) {
542:     TaoLineSearchSetType(ls,default_type);
543:   }

545:   PetscOptionsInt("-tao_ls_max_funcs","max function evals in line search","",ls->max_funcs,&ls->max_funcs,NULL);
546:   PetscOptionsReal("-tao_ls_ftol","tol for sufficient decrease","",ls->ftol,&ls->ftol,NULL);
547:   PetscOptionsReal("-tao_ls_gtol","tol for curvature condition","",ls->gtol,&ls->gtol,NULL);
548:   PetscOptionsReal("-tao_ls_rtol","relative tol for acceptable step","",ls->rtol,&ls->rtol,NULL);
549:   PetscOptionsReal("-tao_ls_stepmin","lower bound for step","",ls->stepmin,&ls->stepmin,NULL);
550:   PetscOptionsReal("-tao_ls_stepmax","upper bound for step","",ls->stepmax,&ls->stepmax,NULL);
551:   PetscOptionsString("-tao_ls_monitor","enable the basic monitor","TaoLineSearchSetMonitor","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
552:   if (flg) {
553:     PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ls),monfilename,&monviewer);
554:     ls->viewer = monviewer;
555:     ls->usemonitor = PETSC_TRUE;
556:   }
557:   if (ls->ops->setfromoptions) {
558:     (*ls->ops->setfromoptions)(PetscOptionsObject,ls);
559:   }
560:   PetscOptionsEnd();
561:   return(0);
562: }

564: /*@C
565:   TaoLineSearchGetType - Gets the current line search algorithm

567:   Not Collective

569:   Input Parameter:
570: . ls - the TaoLineSearch context

572:   Output Paramter:
573: . type - the line search algorithm in effect

575:   Level: developer

577: @*/
578: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, TaoLineSearchType *type)
579: {
583:   *type = ((PetscObject)ls)->type_name;
584:   return(0);
585: }

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

591:   Not Collective

593:   Input Parameter:
594: . ls - the TaoLineSearch context

596:   Output Parameters:
597: + nfeval   - number of function evaluations
598: . ngeval   - number of gradient evaluations
599: - nfgeval  - number of function/gradient evaluations

601:   Level: intermediate

603:   Note:
604:   If the line search is using the Tao objective and gradient
605:   routines directly (see TaoLineSearchUseTaoRoutines()), then TAO
606:   is already counting the number of evaluations.

608: @*/
609: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
610: {
613:   *nfeval = ls->nfeval;
614:   *ngeval = ls->ngeval;
615:   *nfgeval = ls->nfgeval;
616:   return(0);
617: }

619: /*@
620:   TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
621:   Tao evaluation routines.

623:   Not Collective

625:   Input Parameter:
626: . ls - the TaoLineSearch context

628:   Output Parameter:
629: . flg - PETSC_TRUE if the line search is using Tao evaluation routines,
630:         otherwise PETSC_FALSE

632:   Level: developer
633: @*/
634: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
635: {
638:   *flg = ls->usetaoroutines;
639:   return(0);
640: }

642: /*@C
643:   TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search

645:   Logically Collective on TaoLineSearch

647:   Input Parameter:
648: + ls - the TaoLineSearch context
649: . func - the objective function evaluation routine
650: - ctx - the (optional) user-defined context for private data

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

655: + x - input vector
656: . f - function value
657: - ctx (optional) user-defined context

659:   Level: beginner

661:   Note:
662:   Use this routine only if you want the line search objective
663:   evaluation routine to be different from the Tao's objective
664:   evaluation routine. If you use this routine you must also set
665:   the line search gradient and/or function/gradient routine.

667:   Note:
668:   Some algorithms (lcl, gpcg) set their own objective routine for the
669:   line search, application programmers should be wary of overriding the
670:   default objective routine.

672: .seealso: TaoLineSearchCreate(), TaoLineSearchSetGradientRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
673: @*/
674: PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, PetscReal*, void*), void *ctx)
675: {

679:   ls->ops->computeobjective=func;
680:   if (ctx) ls->userctx_func=ctx;
681:   ls->usetaoroutines=PETSC_FALSE;
682:   return(0);
683: }

685: /*@C
686:   TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search

688:   Logically Collective on TaoLineSearch

690:   Input Parameter:
691: + ls - the TaoLineSearch context
692: . func - the gradient evaluation routine
693: - ctx - the (optional) user-defined context for private data

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

698: + x - input vector
699: . g - gradient vector
700: - ctx (optional) user-defined context

702:   Level: beginner

704:   Note:
705:   Use this routine only if you want the line search gradient
706:   evaluation routine to be different from the Tao's gradient
707:   evaluation routine. If you use this routine you must also set
708:   the line search function and/or function/gradient routine.

710:   Note:
711:   Some algorithms (lcl, gpcg) set their own gradient routine for the
712:   line search, application programmers should be wary of overriding the
713:   default gradient routine.

715: .seealso: TaoLineSearchCreate(), TaoLineSearchSetObjectiveRoutine(), TaoLineSearchSetObjectiveAndGradientRoutine(), TaoLineSearchUseTaoRoutines()
716: @*/
717: PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode(*func)(TaoLineSearch ls, Vec x, Vec g, void*), void *ctx)
718: {
721:   ls->ops->computegradient=func;
722:   if (ctx) ls->userctx_grad=ctx;
723:   ls->usetaoroutines=PETSC_FALSE;
724:   return(0);
725: }

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

730:   Logically Collective on TaoLineSearch

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

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

740: + x - input vector
741: . f - function value
742: . g - gradient vector
743: - ctx (optional) user-defined context

745:   Level: beginner

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

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

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

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

776:   Logically Collective on TaoLineSearch

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

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

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

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

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

800:   Level: advanced

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

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

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

824:   Logically Collective on TaoLineSearch

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

830:   Level: developer

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

844: /*@
845:   TaoLineSearchComputeObjective - Computes the objective function value at a given point

847:   Collective on TaoLineSearch

849:   Input Parameters:
850: + ls - the TaoLineSearch context
851: - x - input vector

853:   Output Parameter:
854: . f - Objective value at X

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

860:   Level: developer

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

875:   if (ls->usetaoroutines) {
876:     TaoComputeObjective(ls->tao,x,f);
877:   } else {
878:     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");
879:     PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);
880:     PetscStackPush("TaoLineSearch user objective routine");
881:     if (ls->ops->computeobjective) {
882:       (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
883:     } else if (ls->ops->computeobjectiveandgradient) {
884:       VecDuplicate(x,&gdummy);
885:       (*ls->ops->computeobjectiveandgradient)(ls,x,f,gdummy,ls->userctx_funcgrad);
886:       VecDestroy(&gdummy);
887:     } else {
888:       (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,&gts,ls->userctx_funcgts);
889:     }
890:     PetscStackPop;
891:     PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);
892:   }
893:   ls->nfeval++;
894:   return(0);
895: }

897: /*@
898:   TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point

900:   Collective on Tao

902:   Input Parameters:
903: + ls - the TaoLineSearch context
904: - x - input vector

906:   Output Parameter:
907: + f - Objective value at X
908: - g - Gradient vector at X

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

914:   Level: developer

916: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
917: @*/
918: PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
919: {

929:   if (ls->usetaoroutines) {
930:       TaoComputeObjectiveAndGradient(ls->tao,x,f,g);
931:   } else {
932:     if (!ls->ops->computeobjective && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective function set");
933:     if (!ls->ops->computegradient  && !ls->ops->computeobjectiveandgradient) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have gradient function set");
934:     PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);
935:     PetscStackPush("TaoLineSearch user objective/gradient routine");
936:     if (ls->ops->computeobjectiveandgradient) {
937:       (*ls->ops->computeobjectiveandgradient)(ls,x,f,g,ls->userctx_funcgrad);
938:     } else {
939:       (*ls->ops->computeobjective)(ls,x,f,ls->userctx_func);
940:       (*ls->ops->computegradient)(ls,x,g,ls->userctx_grad);
941:     }
942:     PetscStackPop;
943:     PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);
944:     PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
945:   }
946:   ls->nfgeval++;
947:   return(0);
948: }

950: /*@
951:   TaoLineSearchComputeGradient - Computes the gradient of the objective function

953:   Collective on TaoLineSearch

955:   Input Parameters:
956: + ls - the TaoLineSearch context
957: - x - input vector

959:   Output Parameter:
960: . g - gradient vector

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

966:   Level: developer

968: .seealso: TaoLineSearchComputeObjective(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetGradient()
969: @*/
970: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
971: {
973:   PetscReal      fdummy;

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

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

1002:   Collective on Tao

1004:   Input Parameters:
1005: + ls - the TaoLineSearch context
1006: - x - input vector

1008:   Output Parameter:
1009: + f - Objective value at X
1010: - gts - inner product of gradient and step direction at X

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

1016:   Level: developer

1018: .seealso: TaoLineSearchComputeGradient(), TaoLineSearchComputeObjectiveAndGradient(), TaoLineSearchSetObjectiveRoutine()
1019: @*/
1020: PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
1021: {
1029:   if (!ls->ops->computeobjectiveandgts) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Line Search does not have objective and gts function set");
1030:   PetscLogEventBegin(TAOLINESEARCH_Eval,ls,0,0,0);
1031:   PetscStackPush("TaoLineSearch user objective/gts routine");
1032:   (*ls->ops->computeobjectiveandgts)(ls,x,ls->stepdirection,f,gts,ls->userctx_funcgts);
1033:   PetscStackPop;
1034:   PetscLogEventEnd(TAOLINESEARCH_Eval,ls,0,0,0);
1035:   PetscInfo1(ls,"TaoLineSearch Function evaluation: %14.12e\n",(double)(*f));
1036:   ls->nfeval++;
1037:   return(0);
1038: }

1040: /*@
1041:   TaoLineSearchGetSolution - Returns the solution to the line search

1043:   Collective on TaoLineSearch

1045:   Input Parameter:
1046: . ls - the TaoLineSearch context

1048:   Output Parameter:
1049: + x - the new solution
1050: . f - the objective function value at x
1051: . g - the gradient at x
1052: . steplength - the multiple of the step direction taken by the line search
1053: - reason - the reason why the line search terminated

1055:   reason will be set to one of:

1057: + TAOLINESEARCH_FAILED_INFORNAN - function evaluation gives Inf or Nan value
1058: . TAOLINESEARCH_FAILED_BADPARAMETER - negative value set as parameter
1059: . TAOLINESEARCH_FAILED_ASCENT - initial line search step * g is not descent direction
1060: . TAOLINESEARCH_HALTED_MAXFCN - maximum number of function evaluation reached
1061: . TAOLINESEARCH_HALTED_UPPERBOUND - step is at upper bound
1062: . TAOLINESEARCH_HALTED_LOWERBOUND - step is at lower bound
1063: . TAOLINESEARCH_HALTED_RTOL - range of uncertainty is smaller than given tolerance

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

1068: - TAOLINESEARCH_SUCCESS - successful line search

1070:   Level: developer

1072: @*/
1073: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
1074: {

1083:   if (ls->new_x) {
1084:     VecCopy(ls->new_x,x);
1085:   }
1086:   *f = ls->new_f;
1087:   if (ls->new_g) {
1088:     VecCopy(ls->new_g,g);
1089:   }
1090:   if (steplength) {
1091:     *steplength=ls->step;
1092:   }
1093:   *reason = ls->reason;
1094:   return(0);
1095: }

1097: /*@
1098:   TaoLineSearchGetStartingVector - Gets a the initial point of the line
1099:   search.

1101:   Not Collective

1103:   Input Parameter:
1104: . ls - the TaoLineSearch context

1106:   Output Parameter:
1107: . x - The initial point of the line search

1109:   Level: intermediate
1110: @*/
1111: PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1112: {
1115:   if (x) {
1116:     *x = ls->start_x;
1117:   }
1118:   return(0);
1119: }

1121: /*@
1122:   TaoLineSearchGetStepDirection - Gets the step direction of the line
1123:   search.

1125:   Not Collective

1127:   Input Parameter:
1128: . ls - the TaoLineSearch context

1130:   Output Parameter:
1131: . s - the step direction of the line search

1133:   Level: advanced
1134: @*/
1135: PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1136: {
1139:   if (s) {
1140:     *s = ls->stepdirection;
1141:   }
1142:   return(0);

1144: }

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

1149:   Not Collective

1151:   Input Parameter:
1152: . ls - the TaoLineSearch context

1154:   Output Parameter:
1155: . f - the objective value at the full step length

1157:   Level: developer
1158: @*/

1160: PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch ls, PetscReal *f_fullstep)
1161: {
1164:   *f_fullstep = ls->f_fullstep;
1165:   return(0);
1166: }

1168: /*@
1169:   TaoLineSearchSetVariableBounds - Sets the upper and lower bounds.

1171:   Logically Collective on Tao

1173:   Input Parameters:
1174: + ls - the TaoLineSearch context
1175: . xl  - vector of lower bounds
1176: - xu  - vector of upper bounds

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

1181:   Level: beginner

1183: .seealso: TaoSetVariableBounds(), TaoLineSearchCreate()
1184: @*/
1185: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls,Vec xl, Vec xu)
1186: {
1191:   ls->lower = xl;
1192:   ls->upper = xu;
1193:   ls->bounded = 1;
1194:   return(0);
1195: }

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

1201:   Logically Collective on TaoLineSearch

1203:   Input Parameters:
1204: + ls - the TaoLineSearch context
1205: - s - the initial step size

1207:   Level: intermediate

1209: .seealso: TaoLineSearchGetStepLength(), TaoLineSearchApply()
1210: @*/
1211: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls,PetscReal s)
1212: {
1215:   ls->initstep = s;
1216:   return(0);
1217: }

1219: /*@
1220:   TaoLineSearchGetStepLength - Get the current step length

1222:   Not Collective

1224:   Input Parameters:
1225: . ls - the TaoLineSearch context

1227:   Output Parameters
1228: . s - the current step length

1230:   Level: beginner

1232: .seealso: TaoLineSearchSetInitialStepLength(), TaoLineSearchApply()
1233: @*/
1234: PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls,PetscReal *s)
1235: {
1238:   *s = ls->step;
1239:   return(0);
1240: }

1242: /*@C
1243:    TaoLineSearchRegister - Adds a line-search algorithm to the registry

1245:    Not collective

1247:    Input Parameters:
1248: +  sname - name of a new user-defined solver
1249: -  func - routine to Create method context

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

1254:    Sample usage:
1255: .vb
1256:    TaoLineSearchRegister("my_linesearch",MyLinesearchCreate);
1257: .ve

1259:    Then, your solver can be chosen with the procedural interface via
1260: $     TaoLineSearchSetType(ls,"my_linesearch")
1261:    or at runtime via the option
1262: $     -tao_ls_type my_linesearch

1264:    Level: developer

1266: @*/
1267: PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch))
1268: {
1271:   TaoLineSearchInitializePackage();
1272:   PetscFunctionListAdd(&TaoLineSearchList, sname, (void (*)(void))func);
1273:   return(0);
1274: }

1276: /*@C
1277:    TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1278:    for all TaoLineSearch options in the database.


1281:    Collective on TaoLineSearch

1283:    Input Parameters:
1284: +  ls - the TaoLineSearch solver context
1285: -  prefix - the prefix string to prepend to all line search requests

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


1292:    Level: advanced

1294: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1295: @*/
1296: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1297: {
1298:   return PetscObjectAppendOptionsPrefix((PetscObject)ls,p);
1299: }

1301: /*@C
1302:   TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1303:   TaoLineSearch options in the database

1305:   Not Collective

1307:   Input Parameters:
1308: . ls - the TaoLineSearch context

1310:   Output Parameters:
1311: . prefix - pointer to the prefix string used is returned

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

1317:   Level: advanced

1319: .seealso: TaoLineSearchSetOptionsPrefix(), TaoLineSearchAppendOptionsPrefix()
1320: @*/
1321: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1322: {
1323:   return PetscObjectGetOptionsPrefix((PetscObject)ls,p);
1324: }

1326: /*@C
1327:    TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1328:    TaoLineSearch options in the database.


1331:    Logically Collective on TaoLineSearch

1333:    Input Parameters:
1334: +  ls - the TaoLineSearch context
1335: -  prefix - the prefix string to prepend to all TAO option requests

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

1341:    For example, to distinguish between the runtime options for two
1342:    different line searches, one could call
1343: .vb
1344:       TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1345:       TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1346: .ve

1348:    This would enable use of different options for each system, such as
1349: .vb
1350:       -sys1_tao_ls_type mt
1351:       -sys2_tao_ls_type armijo
1352: .ve

1354:    Level: advanced

1356: .seealso: TaoLineSearchAppendOptionsPrefix(), TaoLineSearchGetOptionsPrefix()
1357: @*/

1359: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1360: {
1361:   return PetscObjectSetOptionsPrefix((PetscObject)ls,p);
1362: }