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 `Tao` context
     21: . obj  - Optional object
     22: - name - command line option

     24:   Options Database Key:
     25: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments

     27:   Level: intermediate

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

     39: /*@
     40:   TaoLineSearchView - Prints information about the `TaoLineSearch`

     42:   Collective

     44:   Input Parameters:
     45: + ls     - the `TaoLineSearch` context
     46: - viewer - visualization context

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

     51:   Level: beginner

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

     61: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `PetscViewerASCIIOpen()`, `TaoLineSearchViewFromOptions()`
     62: @*/
     63: PetscErrorCode TaoLineSearchView(TaoLineSearch ls, PetscViewer viewer)
     64: {
     65:   PetscBool         isascii, isstring;
     66:   TaoLineSearchType type;

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

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

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

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

    102:   Collective

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

    107:   Output Parameter:
    108: . newls - the new `TaoLineSearch` context

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

    113:   Level: developer

    115: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchType`, `TaoLineSearchSetType()`, `TaoLineSearchApply()`, `TaoLineSearchDestroy()`
    116: @*/
    117: PetscErrorCode TaoLineSearchCreate(MPI_Comm comm, TaoLineSearch *newls)
    118: {
    119:   TaoLineSearch ls;

    121:   PetscFunctionBegin;
    122:   PetscAssertPointer(newls, 2);
    123:   PetscCall(TaoLineSearchInitializePackage());

    125:   PetscCall(PetscHeaderCreate(ls, TAOLINESEARCH_CLASSID, "TaoLineSearch", "Linesearch", "Tao", comm, TaoLineSearchDestroy, TaoLineSearchView));
    126:   ls->max_funcs = 30;
    127:   ls->ftol      = 0.0001;
    128:   ls->gtol      = 0.9;
    129: #if defined(PETSC_USE_REAL_SINGLE)
    130:   ls->rtol = 1.0e-5;
    131: #else
    132:   ls->rtol = 1.0e-10;
    133: #endif
    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: #if defined(PETSC_USE_REAL_SINGLE)
    394:   ls->rtol = 1.0e-5;
    395: #else
    396:   ls->rtol = 1.0e-10;
    397: #endif
    398:   ls->stepmin = 1.0e-20;
    399:   ls->stepmax = 1.0e+20;

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

    415: /*@C
    416:   TaoLineSearchMonitor - Monitor the line search steps. This routine will output the
    417:   iteration number, step length, and function value before calling the implementation
    418:   specific monitor.

    420:   Input Parameters:
    421: + ls   - the `TaoLineSearch` context
    422: . its  - the current iterate number (>=0)
    423: . f    - the current objective function value
    424: - step - the step length

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

    429:   Level: developer

    431: .seealso: `TaoLineSearch`
    432: @*/
    433: PetscErrorCode TaoLineSearchMonitor(TaoLineSearch ls, PetscInt its, PetscReal f, PetscReal step)
    434: {
    435:   PetscInt tabs;

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

    454: /*@
    455:   TaoLineSearchSetFromOptions - Sets various `TaoLineSearch` parameters from user
    456:   options.

    458:   Collective

    460:   Input Parameter:
    461: . ls - the `TaoLineSearch` context

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

    474:   Level: beginner

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

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

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

    515: /*@
    516:   TaoLineSearchGetType - Gets the current line search algorithm

    518:   Not Collective

    520:   Input Parameter:
    521: . ls - the `TaoLineSearch` context

    523:   Output Parameter:
    524: . type - the line search algorithm in effect

    526:   Level: developer

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

    531: .seealso: `TaoLineSearch`, `TaoLineSearchSetType()`, `TaoLineSearchType`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
    532: @*/
    533: PetscErrorCode TaoLineSearchGetType(TaoLineSearch ls, TaoLineSearchType *type)
    534: {
    535:   PetscFunctionBegin;
    537:   PetscAssertPointer(type, 2);
    538:   *type = ((PetscObject)ls)->type_name;
    539:   PetscFunctionReturn(PETSC_SUCCESS);
    540: }

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

    546:   Not Collective

    548:   Input Parameter:
    549: . ls - the `TaoLineSearch` context

    551:   Output Parameters:
    552: + nfeval  - number of function evaluations
    553: . ngeval  - number of gradient evaluations
    554: - nfgeval - number of function/gradient evaluations

    556:   Level: intermediate

    558:   Note:
    559:   If the line search is using the `Tao` objective and gradient
    560:   routines directly (see `TaoLineSearchUseTaoRoutines()`), then the `Tao`
    561:   is already counting the number of evaluations.

    563: .seealso: `TaoLineSearch`
    564: @*/
    565: PetscErrorCode TaoLineSearchGetNumberFunctionEvaluations(TaoLineSearch ls, PetscInt *nfeval, PetscInt *ngeval, PetscInt *nfgeval)
    566: {
    567:   PetscFunctionBegin;
    569:   *nfeval  = ls->nfeval;
    570:   *ngeval  = ls->ngeval;
    571:   *nfgeval = ls->nfgeval;
    572:   PetscFunctionReturn(PETSC_SUCCESS);
    573: }

    575: /*@
    576:   TaoLineSearchIsUsingTaoRoutines - Checks whether the line search is using
    577:   the standard `Tao` evaluation routines.

    579:   Not Collective

    581:   Input Parameter:
    582: . ls - the `TaoLineSearch` context

    584:   Output Parameter:
    585: . flg - `PETSC_TRUE` if the line search is using `Tao` evaluation routines,
    586:         otherwise `PETSC_FALSE`

    588:   Level: developer

    590: .seealso: `TaoLineSearch`
    591: @*/
    592: PetscErrorCode TaoLineSearchIsUsingTaoRoutines(TaoLineSearch ls, PetscBool *flg)
    593: {
    594:   PetscFunctionBegin;
    596:   *flg = ls->usetaoroutines;
    597:   PetscFunctionReturn(PETSC_SUCCESS);
    598: }

    600: /*@C
    601:   TaoLineSearchSetObjectiveRoutine - Sets the function evaluation routine for the line search

    603:   Logically Collective

    605:   Input Parameters:
    606: + ls   - the `TaoLineSearch` context
    607: . func - the objective function evaluation routine
    608: - ctx  - the (optional) user-defined context for private data

    610:   Calling sequence of `func`:
    611: + ls  - the line search context
    612: . x   - input vector
    613: . f   - function value
    614: - ctx - (optional) user-defined context

    616:   Level: advanced

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

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

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

    635:   ls->ops->computeobjective = func;
    636:   if (ctx) ls->userctx_func = ctx;
    637:   ls->usetaoroutines = PETSC_FALSE;
    638:   PetscFunctionReturn(PETSC_SUCCESS);
    639: }

    641: /*@C
    642:   TaoLineSearchSetGradientRoutine - Sets the gradient evaluation routine for the line search

    644:   Logically Collective

    646:   Input Parameters:
    647: + ls   - the `TaoLineSearch` context
    648: . func - the gradient evaluation routine
    649: - ctx  - the (optional) user-defined context for private data

    651:   Calling sequence of `func`:
    652: + ls  - the linesearch object
    653: . x   - input vector
    654: . g   - gradient vector
    655: - ctx - (optional) user-defined context

    657:   Level: beginner

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

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

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

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

    684:   Logically Collective

    686:   Input Parameters:
    687: + ls   - the `TaoLineSearch` context
    688: . func - the objective and gradient evaluation routine
    689: - ctx  - the (optional) user-defined context for private data

    691:   Calling sequence of `func`:
    692: + ls  - the linesearch object
    693: . x   - input vector
    694: . f   - function value
    695: . g   - gradient vector
    696: - ctx - (optional) user-defined context

    698:   Level: beginner

    700:   Note:
    701:   Use this routine only if you want the line search objective and gradient
    702:   evaluation routines to be different from the `Tao`'s objective
    703:   and gradient evaluation routines.

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

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

    721: /*@C
    722:   TaoLineSearchSetObjectiveAndGTSRoutine - Sets the objective and
    723:   (gradient'*stepdirection) evaluation routine for the line search.

    725:   Logically Collective

    727:   Input Parameters:
    728: + ls   - the `TaoLineSearch` context
    729: . func - the objective and gradient evaluation routine
    730: - ctx  - the (optional) user-defined context for private data

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

    740:   Level: advanced

    742:   Notes:
    743:   Sometimes it is more efficient to compute the inner product of the gradient and the step
    744:   direction than it is to compute the gradient, and this is all the line search typically needs
    745:   of the gradient.

    747:   The gradient will still need to be computed at the end of the line
    748:   search, so you will still need to set a line search gradient evaluation
    749:   routine

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

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

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

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

    776:   Logically Collective

    778:   Input Parameters:
    779: + ls - the `TaoLineSearch` context
    780: - ts - the `Tao` context with defined objective/gradient evaluation routines

    782:   Level: developer

    784: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchCreate()`
    785: @*/
    786: PetscErrorCode TaoLineSearchUseTaoRoutines(TaoLineSearch ls, Tao ts)
    787: {
    788:   PetscFunctionBegin;
    791:   ls->tao            = ts;
    792:   ls->usetaoroutines = PETSC_TRUE;
    793:   PetscFunctionReturn(PETSC_SUCCESS);
    794: }

    796: /*@
    797:   TaoLineSearchComputeObjective - Computes the objective function value at a given point

    799:   Collective

    801:   Input Parameters:
    802: + ls - the `TaoLineSearch` context
    803: - x  - input vector

    805:   Output Parameter:
    806: . f - Objective value at `x`

    808:   Level: developer

    810:   Note:
    811:   `TaoLineSearchComputeObjective()` is typically used within line searches
    812:   so most users would not generally call this routine themselves.

    814: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchComputeGradient()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetObjectiveRoutine()`
    815: @*/
    816: PetscErrorCode TaoLineSearchComputeObjective(TaoLineSearch ls, Vec x, PetscReal *f)
    817: {
    818:   Vec       gdummy;
    819:   PetscReal gts;

    821:   PetscFunctionBegin;
    824:   PetscAssertPointer(f, 3);
    825:   PetscCheckSameComm(ls, 1, x, 2);
    826:   if (ls->usetaoroutines) {
    827:     PetscCall(TaoComputeObjective(ls->tao, x, f));
    828:   } else {
    829:     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");
    830:     PetscCall(PetscLogEventBegin(TAOLINESEARCH_Eval, ls, 0, 0, 0));
    831:     if (ls->ops->computeobjective) PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjective)(ls, x, f, ls->userctx_func));
    832:     else if (ls->ops->computeobjectiveandgradient) {
    833:       PetscCall(VecDuplicate(x, &gdummy));
    834:       PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjectiveandgradient)(ls, x, f, gdummy, ls->userctx_funcgrad));
    835:       PetscCall(VecDestroy(&gdummy));
    836:     } else PetscCallBack("TaoLineSearch callback objective", (*ls->ops->computeobjectiveandgts)(ls, x, ls->stepdirection, f, &gts, ls->userctx_funcgts));
    837:     PetscCall(PetscLogEventEnd(TAOLINESEARCH_Eval, ls, 0, 0, 0));
    838:   }
    839:   ls->nfeval++;
    840:   PetscFunctionReturn(PETSC_SUCCESS);
    841: }

    843: /*@
    844:   TaoLineSearchComputeObjectiveAndGradient - Computes the objective function value at a given point

    846:   Collective

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

    852:   Output Parameters:
    853: + f - Objective value at `x`
    854: - g - Gradient vector at `x`

    856:   Level: developer

    858:   Note:
    859:   `TaoLineSearchComputeObjectiveAndGradient()` is typically used within line searches
    860:   so most users would not generally call this routine themselves.

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

    889: /*@
    890:   TaoLineSearchComputeGradient - Computes the gradient of the objective function

    892:   Collective

    894:   Input Parameters:
    895: + ls - the `TaoLineSearch` context
    896: - x  - input vector

    898:   Output Parameter:
    899: . g - gradient vector

    901:   Level: developer

    903:   Note:
    904:   `TaoComputeGradient()` is typically used within line searches
    905:   so most users would not generally call this routine themselves.

    907: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchComputeObjective()`, `TaoLineSearchComputeObjectiveAndGradient()`, `TaoLineSearchSetGradient()`
    908: @*/
    909: PetscErrorCode TaoLineSearchComputeGradient(TaoLineSearch ls, Vec x, Vec g)
    910: {
    911:   PetscReal fdummy;

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

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

    935:   Collective

    937:   Input Parameters:
    938: + ls - the `TaoLineSearch` context
    939: - x  - input vector

    941:   Output Parameters:
    942: + f   - Objective value at `x`
    943: - gts - inner product of gradient and step direction at `x`

    945:   Level: developer

    947:   Note:
    948:   `TaoLineSearchComputeObjectiveAndGTS()` is typically used within line searches
    949:   so most users would not generally call this routine themselves.

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

    969: /*@
    970:   TaoLineSearchGetSolution - Returns the solution to the line search

    972:   Collective

    974:   Input Parameter:
    975: . ls - the `TaoLineSearch` context

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

    984:   Level: developer

    986: .seealso: `TaoLineSearchGetStartingVector()`, `TaoLineSearchGetStepDirection()`
    987: @*/
    988: PetscErrorCode TaoLineSearchGetSolution(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, PetscReal *steplength, TaoLineSearchConvergedReason *reason)
    989: {
    990:   PetscFunctionBegin;
    993:   PetscAssertPointer(f, 3);
    995:   PetscAssertPointer(reason, 6);
    996:   if (ls->new_x) PetscCall(VecCopy(ls->new_x, x));
    997:   *f = ls->new_f;
    998:   if (ls->new_g) PetscCall(VecCopy(ls->new_g, g));
    999:   if (steplength) *steplength = ls->step;
    1000:   *reason = ls->reason;
    1001:   PetscFunctionReturn(PETSC_SUCCESS);
    1002: }

    1004: /*@
    1005:   TaoLineSearchGetStartingVector - Gets a the initial point of the line
    1006:   search.

    1008:   Not Collective

    1010:   Input Parameter:
    1011: . ls - the `TaoLineSearch` context

    1013:   Output Parameter:
    1014: . x - The initial point of the line search

    1016:   Level: advanced

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

    1028: /*@
    1029:   TaoLineSearchGetStepDirection - Gets the step direction of the line
    1030:   search.

    1032:   Not Collective

    1034:   Input Parameter:
    1035: . ls - the `TaoLineSearch` context

    1037:   Output Parameter:
    1038: . s - the step direction of the line search

    1040:   Level: advanced

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

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

    1055:   Not Collective

    1057:   Input Parameter:
    1058: . ls - the `TaoLineSearch` context

    1060:   Output Parameter:
    1061: . f_fullstep - the objective value at the full step length

    1063:   Level: developer

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

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

    1078:   Logically Collective

    1080:   Input Parameters:
    1081: + ls - the `TaoLineSearch` context
    1082: . xl - vector of lower bounds
    1083: - xu - vector of upper bounds

    1085:   Level: beginner

    1087:   Note:
    1088:   If the variable bounds are not set with this routine, then
    1089:   `PETSC_NINFINITY` and `PETSC_INFINITY` are assumed

    1091: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoSetVariableBounds()`, `TaoLineSearchCreate()`
    1092: @*/
    1093: PetscErrorCode TaoLineSearchSetVariableBounds(TaoLineSearch ls, Vec xl, Vec xu)
    1094: {
    1095:   PetscFunctionBegin;
    1099:   PetscCall(PetscObjectReference((PetscObject)xl));
    1100:   PetscCall(PetscObjectReference((PetscObject)xu));
    1101:   PetscCall(VecDestroy(&ls->lower));
    1102:   PetscCall(VecDestroy(&ls->upper));
    1103:   ls->lower   = xl;
    1104:   ls->upper   = xu;
    1105:   ls->bounded = (PetscBool)(xl || xu);
    1106:   PetscFunctionReturn(PETSC_SUCCESS);
    1107: }

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

    1113:   Logically Collective

    1115:   Input Parameters:
    1116: + ls - the `TaoLineSearch` context
    1117: - s  - the initial step size

    1119:   Level: intermediate

    1121: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchGetStepLength()`, `TaoLineSearchApply()`
    1122: @*/
    1123: PetscErrorCode TaoLineSearchSetInitialStepLength(TaoLineSearch ls, PetscReal s)
    1124: {
    1125:   PetscFunctionBegin;
    1128:   ls->initstep = s;
    1129:   PetscFunctionReturn(PETSC_SUCCESS);
    1130: }

    1132: /*@
    1133:   TaoLineSearchGetStepLength - Get the current step length

    1135:   Not Collective

    1137:   Input Parameter:
    1138: . ls - the `TaoLineSearch` context

    1140:   Output Parameter:
    1141: . s - the current step length

    1143:   Level: intermediate

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

    1155: /*@C
    1156:   TaoLineSearchRegister - Adds a line-search algorithm to the registry

    1158:   Not Collective, No Fortran Support

    1160:   Input Parameters:
    1161: + sname - name of a new user-defined solver
    1162: - func  - routine to Create method context

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

    1167:   Example Usage:
    1168: .vb
    1169:    TaoLineSearchRegister("my_linesearch", MyLinesearchCreate);
    1170: .ve

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

    1181:   Level: developer

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

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

    1196: /*@
    1197:   TaoLineSearchAppendOptionsPrefix - Appends to the prefix used for searching
    1198:   for all `TaoLineSearch` options in the database.

    1200:   Collective

    1202:   Input Parameters:
    1203: + ls - the `TaoLineSearch` solver context
    1204: - p  - the prefix string to prepend to all line search requests

    1206:   Level: advanced

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

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

    1214: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchSetOptionsPrefix()`, `TaoLineSearchGetOptionsPrefix()`
    1215: @*/
    1216: PetscErrorCode TaoLineSearchAppendOptionsPrefix(TaoLineSearch ls, const char p[])
    1217: {
    1218:   return PetscObjectAppendOptionsPrefix((PetscObject)ls, p);
    1219: }

    1221: /*@
    1222:   TaoLineSearchGetOptionsPrefix - Gets the prefix used for searching for all
    1223:   `TaoLineSearch` options in the database

    1225:   Not Collective

    1227:   Input Parameter:
    1228: . ls - the `TaoLineSearch` context

    1230:   Output Parameter:
    1231: . p - pointer to the prefix string used is returned

    1233:   Level: advanced

    1235: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchSetOptionsPrefix()`, `TaoLineSearchAppendOptionsPrefix()`
    1236: @*/
    1237: PetscErrorCode TaoLineSearchGetOptionsPrefix(TaoLineSearch ls, const char *p[])
    1238: {
    1239:   return PetscObjectGetOptionsPrefix((PetscObject)ls, p);
    1240: }

    1242: /*@
    1243:   TaoLineSearchSetOptionsPrefix - Sets the prefix used for searching for all
    1244:   `TaoLineSearch` options in the database.

    1246:   Logically Collective

    1248:   Input Parameters:
    1249: + ls - the `TaoLineSearch` context
    1250: - p  - the prefix string to prepend to all `ls` option requests

    1252:   Level: advanced

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

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

    1260:   For example, to distinguish between the runtime options for two
    1261:   different line searches, one could call
    1262: .vb
    1263:       TaoLineSearchSetOptionsPrefix(ls1,"sys1_")
    1264:       TaoLineSearchSetOptionsPrefix(ls2,"sys2_")
    1265: .ve

    1267:   This would enable use of different options for each system, such as
    1268: .vb
    1269:       -sys1_tao_ls_type mt
    1270:       -sys2_tao_ls_type armijo
    1271: .ve

    1273: .seealso: [](ch_tao), `Tao`, `TaoLineSearch`, `TaoLineSearchAppendOptionsPrefix()`, `TaoLineSearchGetOptionsPrefix()`
    1274: @*/
    1275: PetscErrorCode TaoLineSearchSetOptionsPrefix(TaoLineSearch ls, const char p[])
    1276: {
    1277:   return PetscObjectSetOptionsPrefix((PetscObject)ls, p);
    1278: }