Actual source code: taolinesearch.c

  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: const char *const TaoLineSearchConvergedReasons_Shifted[] = {"FAILED_ASCENT", "FAILED_BADPARAMETER", "FAILED_INFORNAN", "CONTINUE_ITERATING", "SUCCESS", "SUCCESS_USER", "HALTED_OTHER", "HALTED_MAXFCN", "HALTED_UPPERBOUND", "HALTED_LOWERBOUND", "HALTED_RTOL", "HALTED_USER", "TaoLineSearchConvergedReason", "TAOLINESEARCH_", NULL};
 12: const char *const *TaoLineSearchConvergedReasons = TaoLineSearchConvergedReasons_Shifted + 3;

 14: /*@
 15:   TaoLineSearchViewFromOptions - View a `TaoLineSearch` object based on values in the options database

 17:   Collective

 19:   Input Parameters:
 20: + A    - the `TaoLineSearch` context
 21: . obj  - optional object that provides the prefix for the option names, pass `NULL` to use the options prefix of `A`
 22: - name - command line option

 24:   Options Database Key:
 25: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`

 27:   Level: intermediate

 29:   Note:
 30:   This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
 31:   rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.

 33: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchView()`, `PetscObjectViewFromOptions()`, `TaoLineSearchCreate()`, `PetscOptionsCreateViewer()`
 34: @*/
 35: PetscErrorCode TaoLineSearchViewFromOptions(TaoLineSearch A, PetscObject obj, const char name[])
 36: {
 37:   PetscFunctionBegin;
 39:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
 40:   PetscFunctionReturn(PETSC_SUCCESS);
 41: }

 43: /*@
 44:   TaoLineSearchView - Prints information about the `TaoLineSearch`

 46:   Collective

 48:   Input Parameters:
 49: + ls     - the `TaoLineSearch` context
 50: - viewer - visualization context

 52:   Options Database Key:
 53: . -tao_ls_view - Calls `TaoLineSearchView()` at the end of each line search

 55:   Level: beginner

 57:   Notes:
 58:   The available visualization contexts include
 59: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
 60: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
 61:   output where only the first processor opens
 62:   the file.  All other processors send their
 63:   data to the first processor to print.

 65: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `PetscViewerASCIIOpen()`, `TaoLineSearchViewFromOptions()`
 66: @*/
 67: PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
 68: {
 69:   PetscBool         isascii, isstring;
 70:   TaoLineSearchType type;

 72:   PetscFunctionBegin;
 74:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(((PetscObject)ls)->comm, &viewer));
 76:   PetscCheckSameComm(ls, 1, viewer, 2);

 78:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
 79:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
 80:   if (isascii) {
 81:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ls, viewer));
 82:     PetscCall(PetscViewerASCIIPushTab(viewer));
 83:     PetscTryTypeMethod(ls, view, viewer);
 84:     PetscCall(PetscViewerASCIIPopTab(viewer));
 85:     PetscCall(PetscViewerASCIIPushTab(viewer));
 86:     PetscCall(PetscViewerASCIIPrintf(viewer, "maximum function evaluations=%" PetscInt_FMT "\n", ls->max_funcs));
 87:     PetscCall(PetscViewerASCIIPrintf(viewer, "tolerances: ftol=%g, rtol=%g, gtol=%g\n", (double)ls->ftol, (double)ls->rtol, (double)ls->gtol));
 88:     PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function evaluations=%" PetscInt_FMT "\n", ls->nfeval));
 89:     PetscCall(PetscViewerASCIIPrintf(viewer, "total number of gradient evaluations=%" PetscInt_FMT "\n", ls->ngeval));
 90:     PetscCall(PetscViewerASCIIPrintf(viewer, "total number of function/gradient evaluations=%" PetscInt_FMT "\n", ls->nfgeval));

 92:     if (ls->bounded) PetscCall(PetscViewerASCIIPrintf(viewer, "using variable bounds\n"));
 93:     PetscCall(PetscViewerASCIIPrintf(viewer, "Termination reason: %s\n", TaoLineSearchConvergedReasons[ls->reason]));
 94:     PetscCall(PetscViewerASCIIPopTab(viewer));
 95:   } else if (isstring) {
 96:     PetscCall(TaoLineSearchGetType(ls, &type));
 97:     PetscCall(PetscViewerStringSPrintf(viewer, " %-3.3s", type));
 98:   }
 99:   PetscFunctionReturn(PETSC_SUCCESS);
100: }

102: /*@
103:   TaoLineSearchCreate - Creates a `TaoLineSearch` object.  Algorithms in `Tao` that use
104:   line-searches will automatically create one so this all is rarely needed

106:   Collective

108:   Input Parameter:
109: . comm - MPI communicator

111:   Output Parameter:
112: . newls - the new `TaoLineSearch` context

114:   Options Database Key:
115: . -tao_ls_type (unit|more-thuente|gpcg|armijo|owarmijo|ipm) - select which line search `Tao` should use

117:   Level: developer

119: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`, `TaoLineSearchSetType()`, `TaoLineSearchApply()`, `TaoLineSearchDestroy()`
120: @*/
121: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
122: {
123:   TaoLineSearch ls;

125:   PetscFunctionBegin;
126:   PetscAssertPointer(newls, 2);
127:   PetscCall(TaoLineSearchInitializePackage());

129:   PetscCall(PetscHeaderCreate(ls, TAOLINESEARCH_CLASSID, "TaoLineSearch", "Linesearch", "Tao", comm, TaoLineSearchDestroy, TaoLineSearchView));
130:   ls->max_funcs = 30;
131:   ls->ftol      = 0.0001;
132:   ls->gtol      = 0.9;
133:   ls->rtol      = PetscDefined(USE_REAL_SINGLE) ? 1.0e-5 : 1.0e-10;
134:   ls->stepmin   = 1.0e-20;
135:   ls->stepmax   = 1.0e+20;
136:   ls->step      = 1.0;
137:   ls->initstep  = 1.0;
138:   *newls        = ls;
139:   PetscFunctionReturn(PETSC_SUCCESS);
140: }

142: /*@
143:   TaoLineSearchSetUp - Sets up the internal data structures for the later use
144:   of a `TaoLineSearch`

146:   Collective

148:   Input Parameter:
149: . ls - the `TaoLineSearch` context

151:   Level: developer

153:   Note:
154:   The user will not need to explicitly call `TaoLineSearchSetUp()`, as it will
155:   automatically be called in `TaoLineSearchSolve()`.  However, if the user
156:   desires to call it explicitly, it should come after `TaoLineSearchCreate()`
157:   but before `TaoLineSearchApply()`.

159: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchApply()`
160: @*/
161: PetscErrorCode TaoLineSearchSetUp(TaoLineSearch ls)
162: {
163:   const char *default_type = TAOLINESEARCHMT;
164:   PetscBool   flg;

166:   PetscFunctionBegin;
168:   if (ls->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
169:   if (!((PetscObject)ls)->type_name) PetscCall(TaoLineSearchSetType(ls, default_type));
170:   PetscTryTypeMethod(ls, setup);
171:   if (ls->usetaoroutines) {
172:     PetscCall(TaoIsObjectiveDefined(ls->tao, &flg));
173:     ls->hasobjective = flg;
174:     PetscCall(TaoIsGradientDefined(ls->tao, &flg));
175:     ls->hasgradient = flg;
176:     PetscCall(TaoIsObjectiveAndGradientDefined(ls->tao, &flg));
177:     ls->hasobjectiveandgradient = flg;
178:   } else {
179:     if (ls->ops->computeobjective) {
180:       ls->hasobjective = PETSC_TRUE;
181:     } else {
182:       ls->hasobjective = PETSC_FALSE;
183:     }
184:     if (ls->ops->computegradient) {
185:       ls->hasgradient = PETSC_TRUE;
186:     } else {
187:       ls->hasgradient = PETSC_FALSE;
188:     }
189:     if (ls->ops->computeobjectiveandgradient) {
190:       ls->hasobjectiveandgradient = PETSC_TRUE;
191:     } else {
192:       ls->hasobjectiveandgradient = PETSC_FALSE;
193:     }
194:   }
195:   ls->setupcalled = PETSC_TRUE;
196:   PetscFunctionReturn(PETSC_SUCCESS);
197: }

199: /*@
200:   TaoLineSearchReset - Some line searches may carry state information
201:   from one `TaoLineSearchApply()` to the next.  This function resets this
202:   state information.

204:   Collective

206:   Input Parameter:
207: . ls - the `TaoLineSearch` context

209:   Level: developer

211: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchApply()`
212: @*/
213: PetscErrorCode TaoLineSearchReset(TaoLineSearch ls)
214: {
215:   PetscFunctionBegin;
217:   PetscTryTypeMethod(ls, reset);
218:   PetscFunctionReturn(PETSC_SUCCESS);
219: }

221: /*@
222:   TaoLineSearchDestroy - Destroys the `TaoLineSearch` context that was created with
223:   `TaoLineSearchCreate()`

225:   Collective

227:   Input Parameter:
228: . ls - the `TaoLineSearch` context

230:   Level: developer

232: .seealso: `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchApple()`
233: @*/
234: PetscErrorCode TaoLineSearchDestroy(TaoLineSearch *ls)
235: {
236:   PetscFunctionBegin;
237:   if (!*ls) PetscFunctionReturn(PETSC_SUCCESS);
239:   if (--((PetscObject)*ls)->refct > 0) {
240:     *ls = NULL;
241:     PetscFunctionReturn(PETSC_SUCCESS);
242:   }
243:   PetscCall(VecDestroy(&(*ls)->stepdirection));
244:   PetscCall(VecDestroy(&(*ls)->start_x));
245:   PetscCall(VecDestroy(&(*ls)->upper));
246:   PetscCall(VecDestroy(&(*ls)->lower));
247:   PetscTryTypeMethod(*ls, destroy);
248:   if ((*ls)->usemonitor) PetscCall(PetscViewerDestroy(&(*ls)->viewer));
249:   PetscCall(PetscHeaderDestroy(ls));
250:   PetscFunctionReturn(PETSC_SUCCESS);
251: }

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

257:   Collective

259:   Input Parameters:
260: + ls - the `TaoLineSearch` context
261: - s  - search direction

263:   Output Parameters:
264: + x          - On input the current solution, on output `x` contains the new solution determined by the line search
265: . f          - On input the objective function value at current solution, on output contains the objective function value at new solution
266: . g          - On input the gradient evaluated at `x`, on output contains the gradient at new solution
267: . steplength - scalar multiplier of `s` used ( $x = x_0 + steplength * x)
268: - reason     - `TaoLineSearchConvergedReason` reason why the line-search stopped

270:   Level: advanced

272:   Notes:
273:   The algorithm developer must set up the `TaoLineSearch` with calls to
274:   `TaoLineSearchSetObjectiveRoutine()` and `TaoLineSearchSetGradientRoutine()`,
275:   `TaoLineSearchSetObjectiveAndGradientRoutine()`, or `TaoLineSearchUseTaoRoutines()`.
276:   The latter is done automatically by default and thus requires no user input.

278:   You may or may not need to follow this with a call to
279:   `TaoAddLineSearchCounts()`, depending on whether you want these
280:   evaluations to count toward the total function/gradient evaluations.

282: .seealso: [](ch_tao), `Tao`, `TaoLineSearchConvergedReason`, `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchSetType()`,
283:           `TaoLineSearchSetInitialStepLength()`, `TaoAddLineSearchCounts()`
284: @*/
285: PetscErrorCode TaoLineSearchApply(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
286: {
287:   PetscInt low1, low2, low3, high1, high2, high3;

289:   PetscFunctionBegin;
292:   PetscAssertPointer(f, 3);
295:   PetscAssertPointer(reason, 7);
296:   PetscCheckSameComm(ls, 1, x, 2);
297:   PetscCheckSameTypeAndComm(x, 2, g, 4);
298:   PetscCheckSameTypeAndComm(x, 2, s, 5);
299:   PetscCall(VecGetOwnershipRange(x, &low1, &high1));
300:   PetscCall(VecGetOwnershipRange(g, &low2, &high2));
301:   PetscCall(VecGetOwnershipRange(s, &low3, &high3));
302:   PetscCheck(low1 == low2 && low1 == low3 && high1 == high2 && high1 == high3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible vector local lengths");

304:   *reason = TAOLINESEARCH_CONTINUE_ITERATING;
305:   PetscCall(PetscObjectReference((PetscObject)s));
306:   PetscCall(VecDestroy(&ls->stepdirection));
307:   ls->stepdirection = s;

309:   PetscCall(TaoLineSearchSetUp(ls));
310:   ls->nfeval  = 0;
311:   ls->ngeval  = 0;
312:   ls->nfgeval = 0;
313:   /* Check parameter values */
314:   if (ls->ftol < 0.0) {
315:     PetscCall(PetscInfo(ls, "Bad Line Search Parameter: ftol (%g) < 0\n", (double)ls->ftol));
316:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
317:   }
318:   if (ls->rtol < 0.0) {
319:     PetscCall(PetscInfo(ls, "Bad Line Search Parameter: rtol (%g) < 0\n", (double)ls->rtol));
320:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
321:   }
322:   if (ls->gtol < 0.0) {
323:     PetscCall(PetscInfo(ls, "Bad Line Search Parameter: gtol (%g) < 0\n", (double)ls->gtol));
324:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
325:   }
326:   if (ls->stepmin < 0.0) {
327:     PetscCall(PetscInfo(ls, "Bad Line Search Parameter: stepmin (%g) < 0\n", (double)ls->stepmin));
328:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
329:   }
330:   if (ls->stepmax < ls->stepmin) {
331:     PetscCall(PetscInfo(ls, "Bad Line Search Parameter: stepmin (%g) > stepmax (%g)\n", (double)ls->stepmin, (double)ls->stepmax));
332:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
333:   }
334:   if (ls->max_funcs < 0) {
335:     PetscCall(PetscInfo(ls, "Bad Line Search Parameter: max_funcs (%" PetscInt_FMT ") < 0\n", ls->max_funcs));
336:     *reason = TAOLINESEARCH_FAILED_BADPARAMETER;
337:   }
338:   if (PetscIsInfOrNanReal(*f)) {
339:     PetscCall(PetscInfo(ls, "Initial Line Search Function Value is infinity or NaN (%g)\n", (double)*f));
340:     *reason = TAOLINESEARCH_FAILED_INFORNAN;
341:   }

343:   PetscCall(PetscObjectReference((PetscObject)x));
344:   PetscCall(VecDestroy(&ls->start_x));
345:   ls->start_x = x;

347:   PetscCall(PetscLogEventBegin(TAOLINESEARCH_Apply, ls, 0, 0, 0));
348:   PetscUseTypeMethod(ls, apply, x, f, g, s);
349:   PetscCall(PetscLogEventEnd(TAOLINESEARCH_Apply, ls, 0, 0, 0));
350:   *reason   = ls->reason;
351:   ls->new_f = *f;

353:   if (steplength) *steplength = ls->step;

355:   PetscCall(TaoLineSearchViewFromOptions(ls, NULL, "-tao_ls_view"));
356:   PetscFunctionReturn(PETSC_SUCCESS);
357: }

359: /*@
360:   TaoLineSearchSetType - Sets the algorithm used in a line search

362:   Collective

364:   Input Parameters:
365: + ls   - the `TaoLineSearch` context
366: - type - the `TaoLineSearchType` selection

368:   Options Database Key:
369: . -tao_ls_type (unit|more-thuente|gpcg|armijo|owarmijo|ipm) - select which line search `Tao` should use

371:   Level: beginner

373: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`, `TaoLineSearchCreate()`, `TaoLineSearchGetType()`,
374:           `TaoLineSearchApply()`
375: @*/
376: PetscErrorCode TaoLineSearchSetType(TaoLineSearch ls, TaoLineSearchType type)
377: {
378:   PetscErrorCode (*r)(TaoLineSearch);
379:   PetscBool flg;

381:   PetscFunctionBegin;
383:   PetscAssertPointer(type, 2);
384:   PetscCall(PetscObjectTypeCompare((PetscObject)ls, type, &flg));
385:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

387:   PetscCall(PetscFunctionListFind(TaoLineSearchList, type, &r));
388:   PetscCheck(r, PetscObjectComm((PetscObject)ls), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested TaoLineSearch type %s", type);
389:   PetscTryTypeMethod(ls, destroy);
390:   ls->max_funcs = 30;
391:   ls->ftol      = 0.0001;
392:   ls->gtol      = 0.9;
393:   ls->rtol      = PetscDefined(USE_REAL_SINGLE) ? 1.0e-5 : 1.0e-10;
394:   ls->stepmin   = 1.0e-20;
395:   ls->stepmax   = 1.0e+20;

397:   ls->nfeval              = 0;
398:   ls->ngeval              = 0;
399:   ls->nfgeval             = 0;
400:   ls->ops->setup          = NULL;
401:   ls->ops->apply          = NULL;
402:   ls->ops->view           = NULL;
403:   ls->ops->setfromoptions = NULL;
404:   ls->ops->destroy        = NULL;
405:   ls->setupcalled         = PETSC_FALSE;
406:   PetscCall((*r)(ls));
407:   PetscCall(PetscObjectChangeTypeName((PetscObject)ls, type));
408:   PetscFunctionReturn(PETSC_SUCCESS);
409: }

411: /*@
412:   TaoLineSearchMonitor - Monitor the line search steps. This routine will output the
413:   iteration number, step length, and function value before calling the implementation
414:   specific monitor.

416:   Input Parameters:
417: + ls   - the `TaoLineSearch` context
418: . its  - the current iterate number (>=0)
419: . f    - the current objective function value
420: - step - the step length

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

425:   Level: developer

427: .seealso: `TaoLineSearch`
428: @*/
429: PetscErrorCode TaoLineSearchMonitor(TaoLineSearch ls, PetscInt its, PetscReal f, PetscReal step)
430: {
431:   PetscInt tabs;

433:   PetscFunctionBegin;
435:   if (ls->usemonitor) {
436:     PetscCall(PetscViewerASCIIGetTab(ls->viewer, &tabs));
437:     PetscCall(PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel));
438:     PetscCall(PetscViewerASCIIPrintf(ls->viewer, "%3" PetscInt_FMT " LS", its));
439:     PetscCall(PetscViewerASCIIPrintf(ls->viewer, "  Function value: %g,", (double)f));
440:     PetscCall(PetscViewerASCIIPrintf(ls->viewer, "  Step length: %g\n", (double)step));
441:     if (ls->ops->monitor && its > 0) {
442:       PetscCall(PetscViewerASCIISetTab(ls->viewer, ((PetscObject)ls)->tablevel + 3));
443:       PetscUseTypeMethod(ls, monitor);
444:     }
445:     PetscCall(PetscViewerASCIISetTab(ls->viewer, tabs));
446:   }
447:   PetscFunctionReturn(PETSC_SUCCESS);
448: }

450: /*@
451:   TaoLineSearchSetFromOptions - Sets various `TaoLineSearch` parameters from user
452:   options.

454:   Collective

456:   Input Parameter:
457: . ls - the `TaoLineSearch` context

459:   Options Database Keys:
460: + -tao_ls_type (unit|more-thuente|gpcg|armijo|owarmijo|ipm) - select which line search `Tao` should use
461: . -tao_ls_ftol tol                                          - tolerance for sufficient decrease
462: . -tao_ls_gtol tol                                          - tolerance for curvature condition
463: . -tao_ls_rtol tol                                          - relative tolerance for acceptable step
464: . -tao_ls_stepinit step                                     - initial steplength allowed
465: . -tao_ls_stepmin step                                      - minimum steplength allowed
466: . -tao_ls_stepmax step                                      - maximum steplength allowed
467: . -tao_ls_max_funcs n                                       - maximum number of function evaluations allowed
468: - -tao_ls_view                                              - display line-search results

470:   Level: beginner

472: .seealso: `Tao`, `TaoLineSearch`, `TaoGetLineSearch()`
473: @*/
474: PetscErrorCode TaoLineSearchSetFromOptions(TaoLineSearch ls)
475: {
476:   const char *default_type = TAOLINESEARCHMT;
477:   char        type[256], monfilename[PETSC_MAX_PATH_LEN];
478:   PetscViewer monviewer;
479:   PetscBool   flg;

481:   PetscFunctionBegin;
483:   PetscObjectOptionsBegin((PetscObject)ls);
484:   if (((PetscObject)ls)->type_name) default_type = ((PetscObject)ls)->type_name;
485:   /* Check for type from options */
486:   PetscCall(PetscOptionsFList("-tao_ls_type", "Tao Line Search type", "TaoLineSearchSetType", TaoLineSearchList, default_type, type, sizeof(type), &flg));
487:   if (flg) {
488:     PetscCall(TaoLineSearchSetType(ls, type));
489:   } else if (!((PetscObject)ls)->type_name) {
490:     PetscCall(TaoLineSearchSetType(ls, default_type));
491:   }

493:   PetscCall(PetscOptionsInt("-tao_ls_max_funcs", "max function evals in line search", "", ls->max_funcs, &ls->max_funcs, NULL));
494:   PetscCall(PetscOptionsReal("-tao_ls_ftol", "tol for sufficient decrease", "", ls->ftol, &ls->ftol, NULL));
495:   PetscCall(PetscOptionsReal("-tao_ls_gtol", "tol for curvature condition", "", ls->gtol, &ls->gtol, NULL));
496:   PetscCall(PetscOptionsReal("-tao_ls_rtol", "relative tol for acceptable step", "", ls->rtol, &ls->rtol, NULL));
497:   PetscCall(PetscOptionsReal("-tao_ls_stepmin", "lower bound for step", "", ls->stepmin, &ls->stepmin, NULL));
498:   PetscCall(PetscOptionsReal("-tao_ls_stepmax", "upper bound for step", "", ls->stepmax, &ls->stepmax, NULL));
499:   PetscCall(PetscOptionsReal("-tao_ls_stepinit", "initial step", "", ls->initstep, &ls->initstep, NULL));
500:   PetscCall(PetscOptionsString("-tao_ls_monitor", "enable the basic monitor", "TaoLineSearchSetMonitor", "stdout", monfilename, sizeof(monfilename), &flg));
501:   if (flg) {
502:     PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ls), monfilename, &monviewer));
503:     ls->viewer     = monviewer;
504:     ls->usemonitor = PETSC_TRUE;
505:   }
506:   PetscTryTypeMethod(ls, setfromoptions, PetscOptionsObject);
507:   PetscOptionsEnd();
508:   PetscFunctionReturn(PETSC_SUCCESS);
509: }

511: /*@
512:   TaoLineSearchGetType - Gets the current line search algorithm

514:   Not Collective

516:   Input Parameter:
517: . ls - the `TaoLineSearch` context

519:   Output Parameter:
520: . type - the line search algorithm in effect

522:   Level: developer

524:   Note:
525:   `type` should not be retained for later use as it will be an invalid pointer if the `TaoLineSearchType` of `ls` is changed.

527: .seealso: `TaoLineSearch`, `TaoLineSearchSetType()`, `TaoLineSearchType`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
528: @*/
529: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, TaoLineSearchType *type)
530: {
531:   PetscFunctionBegin;
533:   PetscAssertPointer(type, 2);
534:   *type = ((PetscObject)ls)->type_name;
535:   PetscFunctionReturn(PETSC_SUCCESS);
536: }

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

542:   Not Collective

544:   Input Parameter:
545: . ls - the `TaoLineSearch` context

547:   Output Parameters:
548: + nfeval  - number of function evaluations
549: . ngeval  - number of gradient evaluations
550: - nfgeval - number of function/gradient evaluations

552:   Level: intermediate

554:   Note:
555:   If the line search is using the `Tao` objective and gradient
556:   routines directly (see `TaoLineSearchUseTaoRoutines()`), then the `Tao`
557:   is already counting the number of evaluations.

559: .seealso: `TaoLineSearch`
560: @*/
561: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
562: {
563:   PetscFunctionBegin;
565:   *nfeval  = ls->nfeval;
566:   *ngeval  = ls->ngeval;
567:   *nfgeval = ls->nfgeval;
568:   PetscFunctionReturn(PETSC_SUCCESS);
569: }

571: /*@
572:   TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
573:   the standard `Tao` evaluation routines.

575:   Not Collective

577:   Input Parameter:
578: . ls - the `TaoLineSearch` context

580:   Output Parameter:
581: . flg - `PETSC_TRUE` if the line search is using `Tao` evaluation routines,
582:         otherwise `PETSC_FALSE`

584:   Level: developer

586: .seealso: `TaoLineSearch`
587: @*/
588: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
589: {
590:   PetscFunctionBegin;
592:   *flg = ls->usetaoroutines;
593:   PetscFunctionReturn(PETSC_SUCCESS);
594: }

596: /*@
597:   TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search

599:   Logically Collective

601:   Input Parameters:
602: + ls   - the `TaoLineSearch` context
603: . func - the objective function evaluation routine
604: - ctx  - the (optional) user-defined context for private data

606:   Calling sequence of `func`:
607: + ls  - the line search context
608: . x   - input vector
609: . f   - function value
610: - ctx - (optional) user-defined context

612:   Level: advanced

614:   Notes:
615:   Use this routine only if you want the line search objective
616:   evaluation routine to be different from the `Tao`'s objective
617:   evaluation routine. If you use this routine you must also set
618:   the line search gradient and/or function/gradient routine.

620:   Some algorithms (lcl, gpcg) set their own objective routine for the
621:   line search, application programmers should be wary of overriding the
622:   default objective routine.

624: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchSetGradientRoutine()`, `TaoLineSearchSetObjectiveAndGradientRoutine()`, `TaoLineSearchUseTaoRoutines()`
625: @*/
626: PetscErrorCode TaoLineSearchSetObjectiveRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, PetscReal *f, PetscCtx ctx), PetscCtx ctx)
627: {
628:   PetscFunctionBegin;

631:   ls->ops->computeobjective = func;
632:   if (ctx) ls->userctx_func = ctx;
633:   ls->usetaoroutines = PETSC_FALSE;
634:   PetscFunctionReturn(PETSC_SUCCESS);
635: }

637: /*@
638:   TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search

640:   Logically Collective

642:   Input Parameters:
643: + ls   - the `TaoLineSearch` context
644: . func - the gradient evaluation routine
645: - ctx  - the (optional) user-defined context for private data

647:   Calling sequence of `func`:
648: + ls  - the linesearch object
649: . x   - input vector
650: . g   - gradient vector
651: - ctx - (optional) user-defined context

653:   Level: beginner

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

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

665: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchSetObjectiveRoutine()`, `TaoLineSearchSetObjectiveAndGradientRoutine()`, `TaoLineSearchUseTaoRoutines()`
666: @*/
667: PetscErrorCode TaoLineSearchSetGradientRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, Vec g, PetscCtx ctx), PetscCtx ctx)
668: {
669:   PetscFunctionBegin;
671:   ls->ops->computegradient = func;
672:   if (ctx) ls->userctx_grad = ctx;
673:   ls->usetaoroutines = PETSC_FALSE;
674:   PetscFunctionReturn(PETSC_SUCCESS);
675: }

677: /*@
678:   TaoLineSearchSetObjectiveAndGradientRoutine - Sets the objective/gradient evaluation routine for the line search

680:   Logically Collective

682:   Input Parameters:
683: + ls   - the `TaoLineSearch` context
684: . func - the objective and gradient evaluation routine
685: - ctx  - the (optional) user-defined context for private data

687:   Calling sequence of `func`:
688: + ls  - the linesearch object
689: . x   - input vector
690: . f   - function value
691: . g   - gradient vector
692: - ctx - (optional) user-defined context

694:   Level: beginner

696:   Note:
697:   Use this routine only if you want the line search objective and gradient
698:   evaluation routines to be different from the `Tao`'s objective
699:   and gradient evaluation routines.

701:   Some algorithms (lcl, gpcg) set their own objective routine for the
702:   line search, application programmers should be wary of overriding the
703:   default objective routine.

705: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchSetObjectiveRoutine()`, `TaoLineSearchSetGradientRoutine()`, `TaoLineSearchUseTaoRoutines()`
706: @*/
707: PetscErrorCode TaoLineSearchSetObjectiveAndGradientRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscCtx ctx), PetscCtx ctx)
708: {
709:   PetscFunctionBegin;
711:   ls->ops->computeobjectiveandgradient = func;
712:   if (ctx) ls->userctx_funcgrad = ctx;
713:   ls->usetaoroutines = PETSC_FALSE;
714:   PetscFunctionReturn(PETSC_SUCCESS);
715: }

717: /*@
718:   TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
719:   (gradient'*stepdirection) evaluation routine for the line search.

721:   Logically Collective

723:   Input Parameters:
724: + ls   - the `TaoLineSearch` context
725: . func - the objective and gradient evaluation routine
726: - ctx  - the (optional) user-defined context for private data

728:   Calling sequence of `func`:
729: + ls  - the linesearch context
730: . x   - input vector
731: . s   - step direction
732: . f   - function value
733: . gts - inner product of gradient and step direction vectors
734: - ctx - (optional) user-defined context

736:   Level: advanced

738:   Notes:
739:   Sometimes it is more efficient to compute the inner product of the gradient and the step
740:   direction than it is to compute the gradient, and this is all the line search typically needs
741:   of the gradient.

743:   The gradient will still need to be computed at the end of the line
744:   search, so you will still need to set a line search gradient evaluation
745:   routine

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

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

755: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`, `TaoLineSearchSetObjective()`, `TaoLineSearchSetGradient()`, `TaoLineSearchUseTaoRoutines()`
756: @*/
757: PetscErrorCode TaoLineSearchSetObjectiveAndGTSRoutine(TaoLineSearch ls, PetscErrorCode (*func)(TaoLineSearch ls, Vec x, Vec s, PetscReal *f, PetscReal *gts, PetscCtx ctx), PetscCtx ctx)
758: {
759:   PetscFunctionBegin;
761:   ls->ops->computeobjectiveandgts = func;
762:   if (ctx) ls->userctx_funcgts = ctx;
763:   ls->usegts         = PETSC_TRUE;
764:   ls->usetaoroutines = PETSC_FALSE;
765:   PetscFunctionReturn(PETSC_SUCCESS);
766: }

768: /*@
769:   TaoLineSearchUseTaoRoutines - Informs the `TaoLineSearch` to use the
770:   objective and gradient evaluation routines from the given `Tao` object. The default.

772:   Logically Collective

774:   Input Parameters:
775: + ls - the `TaoLineSearch` context
776: - ts - the `Tao` context with defined objective/gradient evaluation routines

778:   Level: developer

780: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`
781: @*/
782: PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
783: {
784:   PetscFunctionBegin;
787:   ls->tao            = ts;
788:   ls->usetaoroutines = PETSC_TRUE;
789:   PetscFunctionReturn(PETSC_SUCCESS);
790: }

792: /*@
793:   TaoLineSearchComputeObjective - Computes the objective function value at a given point

795:   Collective

797:   Input Parameters:
798: + ls - the `TaoLineSearch` context
799: - x  - input vector

801:   Output Parameter:
802: . f - Objective value at `x`

804:   Level: developer

806:   Note:
807:   `TaoLineSearchComputeObjective()` is typically used within line searches
808:   so most users would not generally call this routine themselves.

810: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchComputeGradient()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetObjectiveRoutine()`
811: @*/
812: PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
813: {
814:   Vec       gdummy;
815:   PetscReal gts;

817:   PetscFunctionBegin;
820:   PetscAssertPointer(f, 3);
821:   PetscCheckSameComm(ls, 1, x, 2);
822:   if (ls->usetaoroutines) {
823:     PetscCall(TaoComputeObjective(ls->tao, x, f));
824:   } else {
825:     PetscCheck(ls->ops->computeobjective || ls->ops->computeobjectiveandgradient || ls->ops->computeobjectiveandgts, PetscObjectComm((PetscObject)ls), PETSC_ERR_ARG_WRONGSTATE, "Line Search does not have objective function set");
826:     PetscCall(PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0));
827:     if (ls->ops->computeobjective) PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjective)(ls, x, f, ls->userctx_func));
828:     else if (ls->ops->computeobjectiveandgradient) {
829:       PetscCall(VecDuplicate(x, &gdummy));
830:       PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjectiveandgradient)(ls, x, f, gdummy, ls->userctx_funcgrad));
831:       PetscCall(VecDestroy(&gdummy));
832:     } else PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjectiveandgts)(ls, x, ls->stepdirection, f, &gts, ls->userctx_funcgts));
833:     PetscCall(PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0));
834:   }
835:   ls->nfeval++;
836:   PetscFunctionReturn(PETSC_SUCCESS);
837: }

839: /*@
840:   TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point

842:   Collective

844:   Input Parameters:
845: + ls - the `TaoLineSearch` context
846: - x  - input vector

848:   Output Parameters:
849: + f - Objective value at `x`
850: - g - Gradient vector at `x`

852:   Level: developer

854:   Note:
855:   `TaoLineSearchComputeObjectiveAndGradient()` is typically used within line searches
856:   so most users would not generally call this routine themselves.

858: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchComputeGradient()`, `TaoLineSearchSetObjectiveRoutine()`
859: @*/
860: PetscErrorCode TaoLineSearchComputeObjectiveAndGradient(TaoLineSearch ls, Vec x, PetscReal *f, Vec g)
861: {
862:   PetscFunctionBegin;
865:   PetscAssertPointer(f, 3);
867:   PetscCheckSameComm(ls, 1, x, 2);
868:   PetscCheckSameComm(ls, 1, g, 4);
869:   if (ls->usetaoroutines) {
870:     PetscCall(TaoComputeObjectiveAndGradient(ls->tao, x, f, g));
871:   } else {
872:     PetscCall(PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0));
873:     if (ls->ops->computeobjectiveandgradient) PetscCallBack("TaoLineSearch callback objective/gradient", (*ls->ops->computeobjectiveandgradient)(ls, x, f, g, ls->userctx_funcgrad));
874:     else {
875:       PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjective)(ls, x, f, ls->userctx_func));
876:       PetscCallBack("TaoLineSearch callback gradient", (*ls->ops->computegradient)(ls, x, g, ls->userctx_grad));
877:     }
878:     PetscCall(PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0));
879:     PetscCall(PetscInfo(ls, "TaoLineSearch Function evaluation: %14.12e\n", (double)(*f)));
880:   }
881:   ls->nfgeval++;
882:   PetscFunctionReturn(PETSC_SUCCESS);
883: }

885: /*@
886:   TaoLineSearchComputeGradient - Computes the gradient of the objective function

888:   Collective

890:   Input Parameters:
891: + ls - the `TaoLineSearch` context
892: - x  - input vector

894:   Output Parameter:
895: . g - gradient vector

897:   Level: developer

899:   Note:
900:   `TaoComputeGradient()` is typically used within line searches
901:   so most users would not generally call this routine themselves.

903: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchComputeObjective()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetGradient()`
904: @*/
905: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
906: {
907:   PetscReal fdummy;

909:   PetscFunctionBegin;
913:   PetscCheckSameComm(ls, 1, x, 2);
914:   PetscCheckSameComm(ls, 1, g, 3);
915:   if (ls->usetaoroutines) {
916:     PetscCall(TaoComputeGradient(ls->tao, x, g));
917:   } else {
918:     PetscCall(PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0));
919:     if (ls->ops->computegradient) PetscCallBack("TaoLineSearch callback gradient", (*ls->ops->computegradient)(ls, x, g, ls->userctx_grad));
920:     else PetscCallBack("TaoLineSearch callback gradient", (*ls->ops->computeobjectiveandgradient)(ls, x, &fdummy, g, ls->userctx_funcgrad));
921:     PetscCall(PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0));
922:   }
923:   ls->ngeval++;
924:   PetscFunctionReturn(PETSC_SUCCESS);
925: }

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

931:   Collective

933:   Input Parameters:
934: + ls - the `TaoLineSearch` context
935: - x  - input vector

937:   Output Parameters:
938: + f   - Objective value at `x`
939: - gts - inner product of gradient and step direction at `x`

941:   Level: developer

943:   Note:
944:   `TaoLineSearchComputeObjectiveAndGTS()` is typically used within line searches
945:   so most users would not generally call this routine themselves.

947: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchComputeGradient()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetObjectiveRoutine()`
948: @*/
949: PetscErrorCode TaoLineSearchComputeObjectiveAndGTS(TaoLineSearch ls, Vec x, PetscReal *f, PetscReal *gts)
950: {
951:   PetscFunctionBegin;
954:   PetscAssertPointer(f, 3);
955:   PetscAssertPointer(gts, 4);
956:   PetscCheckSameComm(ls, 1, x, 2);
957:   PetscCall(PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0));
958:   PetscCallBack("TaoLineSearch callback objective/gts", (*ls->ops->computeobjectiveandgts)(ls, x, ls->stepdirection, f, gts, ls->userctx_funcgts));
959:   PetscCall(PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0));
960:   PetscCall(PetscInfo(ls, "TaoLineSearch Function evaluation: %14.12e\n", (double)(*f)));
961:   ls->nfeval++;
962:   PetscFunctionReturn(PETSC_SUCCESS);
963: }

965: /*@
966:   TaoLineSearchGetSolution - Returns the solution to the line search

968:   Collective

970:   Input Parameter:
971: . ls - the `TaoLineSearch` context

973:   Output Parameters:
974: + x          - the new solution
975: . f          - the objective function value at `x`
976: . g          - the gradient at `x`
977: . steplength - the multiple of the step direction taken by the line search
978: - reason     - the reason why the line search terminated

980:   Level: developer

982: .seealso: `TaoLineSearchGetStartingVector()`, `TaoLineSearchGetStepDirection()`
983: @*/
984: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
985: {
986:   PetscFunctionBegin;
989:   PetscAssertPointer(f, 3);
991:   PetscAssertPointer(reason, 6);
992:   if (ls->new_x) PetscCall(VecCopy(ls->new_x, x));
993:   *f = ls->new_f;
994:   if (ls->new_g) PetscCall(VecCopy(ls->new_g, g));
995:   if (steplength) *steplength = ls->step;
996:   *reason = ls->reason;
997:   PetscFunctionReturn(PETSC_SUCCESS);
998: }

1000: /*@
1001:   TaoLineSearchGetStartingVector - Gets a the initial point of the line
1002:   search.

1004:   Not Collective

1006:   Input Parameter:
1007: . ls - the `TaoLineSearch` context

1009:   Output Parameter:
1010: . x - The initial point of the line search

1012:   Level: advanced

1014: .seealso: `TaoLineSearchGetSolution()`, `TaoLineSearchGetStepDirection()`
1015: @*/
1016: PetscErrorCode TaoLineSearchGetStartingVector(TaoLineSearch ls, Vec *x)
1017: {
1018:   PetscFunctionBegin;
1020:   if (x) *x = ls->start_x;
1021:   PetscFunctionReturn(PETSC_SUCCESS);
1022: }

1024: /*@
1025:   TaoLineSearchGetStepDirection - Gets the step direction of the line
1026:   search.

1028:   Not Collective

1030:   Input Parameter:
1031: . ls - the `TaoLineSearch` context

1033:   Output Parameter:
1034: . s - the step direction of the line search

1036:   Level: advanced

1038: .seealso: `TaoLineSearchGetSolution()`, `TaoLineSearchGetStartingVector()`
1039: @*/
1040: PetscErrorCode TaoLineSearchGetStepDirection(TaoLineSearch ls, Vec *s)
1041: {
1042:   PetscFunctionBegin;
1044:   if (s) *s = ls->stepdirection;
1045:   PetscFunctionReturn(PETSC_SUCCESS);
1046: }

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

1051:   Not Collective

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

1056:   Output Parameter:
1057: . f_fullstep - the objective value at the full step length

1059:   Level: developer

1061: .seealso: `TaoLineSearchGetSolution()`, `TaoLineSearchGetStartingVector()`, `TaoLineSearchGetStepDirection()`
1062: @*/
1063: PetscErrorCode TaoLineSearchGetFullStepObjective(TaoLineSearch ls, PetscReal *f_fullstep)
1064: {
1065:   PetscFunctionBegin;
1067:   *f_fullstep = ls->f_fullstep;
1068:   PetscFunctionReturn(PETSC_SUCCESS);
1069: }

1071: /*@
1072:   TaoLineSearchSetVariableBounds - Sets the upper and lower bounds for a bounded line search

1074:   Logically Collective

1076:   Input Parameters:
1077: + ls - the `TaoLineSearch` context
1078: . xl - vector of lower bounds
1079: - xu - vector of upper bounds

1081:   Level: beginner

1083:   Note:
1084:   If the variable bounds are not set with this routine, then
1085:   `PETSC_NINFINITY` and `PETSC_INFINITY` are assumed

1087: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoSetVariableBounds()`, `TaoLineSearchCreate()`
1088: @*/
1089: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls, Vec xl, Vec xu)
1090: {
1091:   PetscFunctionBegin;
1095:   PetscCall(PetscObjectReference((PetscObject)xl));
1096:   PetscCall(PetscObjectReference((PetscObject)xu));
1097:   PetscCall(VecDestroy(&ls->lower));
1098:   PetscCall(VecDestroy(&ls->upper));
1099:   ls->lower   = xl;
1100:   ls->upper   = xu;
1101:   ls->bounded = (PetscBool)(xl || xu);
1102:   PetscFunctionReturn(PETSC_SUCCESS);
1103: }

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

1109:   Logically Collective

1111:   Input Parameters:
1112: + ls - the `TaoLineSearch` context
1113: - s  - the initial step size

1115:   Level: intermediate

1117: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchGetStepLength()`, `TaoLineSearchApply()`
1118: @*/
1119: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls, PetscReal s)
1120: {
1121:   PetscFunctionBegin;
1124:   ls->initstep = s;
1125:   PetscFunctionReturn(PETSC_SUCCESS);
1126: }

1128: /*@
1129:   TaoLineSearchGetStepLength - Get the current step length

1131:   Not Collective

1133:   Input Parameter:
1134: . ls - the `TaoLineSearch` context

1136:   Output Parameter:
1137: . s - the current step length

1139:   Level: intermediate

1141: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchSetInitialStepLength()`, `TaoLineSearchApply()`
1142: @*/
1143: PetscErrorCode TaoLineSearchGetStepLength(TaoLineSearch ls, PetscReal *s)
1144: {
1145:   PetscFunctionBegin;
1147:   *s = ls->step;
1148:   PetscFunctionReturn(PETSC_SUCCESS);
1149: }

1151: /*@
1152:   TaoLineSearchRegister - Adds a line-search algorithm to the registry

1154:   Not Collective, No Fortran Support

1156:   Input Parameters:
1157: + sname - name of a new user-defined solver
1158: - func  - routine to Create method context

1160:   Calling sequence of `func`:
1161: . ls - the `TaoLineSearch` object to set with the `TaoLineSearchType` specific structure

1163:   Example Usage:
1164: .vb
1165:    TaoLineSearchRegister("my_linesearch", MyLinesearchCreate);
1166: .ve

1168:   Then, your solver can be chosen with the procedural interface via
1169: .vb
1170:   TaoLineSearchSetType(ls, "my_linesearch")
1171: .ve
1172:   or at runtime via the option
1173: .vb
1174:   -tao_ls_type my_linesearch
1175: .ve

1177:   Level: developer

1179:   Note:
1180:   `TaoLineSearchRegister()` may be called multiple times to add several user-defined solvers.

1182: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`
1183: @*/
1184: PetscErrorCode TaoLineSearchRegister(const char sname[], PetscErrorCode (*func)(TaoLineSearch ls))
1185: {
1186:   PetscFunctionBegin;
1187:   PetscCall(TaoLineSearchInitializePackage());
1188:   PetscCall(PetscFunctionListAdd(&TaoLineSearchList, sname, func));
1189:   PetscFunctionReturn(PETSC_SUCCESS);
1190: }

1192: /*@
1193:   TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
1194:   for all `TaoLineSearch` options in the database.

1196:   Collective

1198:   Input Parameters:
1199: + ls - the `TaoLineSearch` solver context
1200: - p  - the prefix string to prepend to all line search requests

1202:   Level: advanced

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

1208:   This is inherited from the `Tao` object so rarely needs to be set

1210: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchSetOptionsPrefix()`, `TaoLineSearchGetOptionsPrefix()`
1211: @*/
1212: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
1213: {
1214:   return PetscObjectAppendOptionsPrefix((PetscObject)ls, p);
1215: }

1217: /*@
1218:   TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
1219:   `TaoLineSearch` options in the database

1221:   Not Collective

1223:   Input Parameter:
1224: . ls - the `TaoLineSearch` context

1226:   Output Parameter:
1227: . p - pointer to the prefix string used is returned

1229:   Level: advanced

1231: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchSetOptionsPrefix()`, `TaoLineSearchAppendOptionsPrefix()`
1232: @*/
1233: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
1234: {
1235:   return PetscObjectGetOptionsPrefix((PetscObject)ls, p);
1236: }

1238: /*@
1239:   TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
1240:   `TaoLineSearch` options in the database.

1242:   Logically Collective

1244:   Input Parameters:
1245: + ls - the `TaoLineSearch` context
1246: - p  - the prefix string to prepend to all `ls` option requests

1248:   Level: advanced

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

1254:   This is inherited from the `Tao` object so rarely needs to be set

1256:   For example, to distinguish between the runtime options for two
1257:   different line searches, one could call
1258: .vb
1259:       TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
1260:       TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
1261: .ve

1263:   This would enable use of different options for each system, such as
1264: .vb
1265:       -sys1_tao_ls_type mt
1266:       -sys2_tao_ls_type armijo
1267: .ve

1269: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchAppendOptionsPrefix()`, `TaoLineSearchGetOptionsPrefix()`
1270: @*/
1271: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
1272: {
1273:   return PetscObjectSetOptionsPrefix((PetscObject)ls, p);
1274: }