Date: 2022-03-31T04:48:38+00:00

Actual source code: linesearch.c

      1: #include <petsc/private/linesearchimpl.h>

      3: PetscBool         SNESLineSearchRegisterAllCalled = PETSC_FALSE;
      4: PetscFunctionList SNESLineSearchList              = NULL;

      6: PetscClassId  SNESLINESEARCH_CLASSID;
      7: PetscLogEvent SNESLINESEARCH_Apply;

      9: /*@
     10:    SNESLineSearchMonitorCancel - Clears all the monitor functions for a SNESLineSearch object.

     12:    Logically Collective on SNESLineSearch

     14:    Input Parameters:
     15: .  ls - the SNESLineSearch context

     17:    Options Database Key:
     18: .  -snes_linesearch_monitor_cancel - cancels all monitors that have been hardwired
     19:     into a code by calls to SNESLineSearchMonitorSet(), but does not cancel those
     20:     set via the options database

     22:    Notes:
     23:    There is no way to clear one specific monitor from a SNESLineSearch object.

     25:    This does not clear the monitor set with SNESLineSearchSetDefaultMonitor() use SNESLineSearchSetDefaultMonitor(ls,NULL) to cancel
     26:    that one.

     28:    Level: intermediate

     30: .seealso: SNESGetLineSearch(), SNESLineSearchMonitorDefault(), SNESLineSearchMonitorSet()
     31: @*/
     32: PetscErrorCode  SNESLineSearchMonitorCancel(SNESLineSearch ls)
     33: {
     34:   PetscInt       i;

     37:   for (i=0; i<ls->numbermonitors; i++) {
     38:     if (ls->monitordestroy[i]) {
     39:       (*ls->monitordestroy[i])(&ls->monitorcontext[i]);
     40:     }
     41:   }
     42:   ls->numbermonitors = 0;
     43:   return 0;
     44: }

     46: /*@
     47:    SNESLineSearchMonitor - runs the user provided monitor routines, if they exist

     49:    Collective on SNES

     51:    Input Parameters:
     52: .  ls - the linesearch object

     54:    Notes:
     55:    This routine is called by the SNES implementations.
     56:    It does not typically need to be called by the user.

     58:    Level: developer

     60: .seealso: SNESGetLineSearch(), SNESLineSearchMonitorSet()
     61: @*/
     62: PetscErrorCode  SNESLineSearchMonitor(SNESLineSearch ls)
     63: {
     64:   PetscInt       i,n = ls->numbermonitors;

     66:   for (i=0; i<n; i++) {
     67:     (*ls->monitorftns[i])(ls,ls->monitorcontext[i]);
     68:   }
     69:   return 0;
     70: }

     72: /*@C
     73:    SNESLineSearchMonitorSet - Sets an ADDITIONAL function that is to be used at every
     74:    iteration of the nonlinear solver to display the iteration's
     75:    progress.

     77:    Logically Collective on SNESLineSearch

     79:    Input Parameters:
     80: +  ls - the SNESLineSearch context
     81: .  f - the monitor function
     82: .  mctx - [optional] user-defined context for private data for the
     83:           monitor routine (use NULL if no context is desired)
     84: -  monitordestroy - [optional] routine that frees monitor context
     85:           (may be NULL)

     87:    Notes:
     88:    Several different monitoring routines may be set by calling
     89:    SNESLineSearchMonitorSet() multiple times; all will be called in the
     90:    order in which they were set.

     92:    Fortran Notes:
     93:     Only a single monitor function can be set for each SNESLineSearch object

     95:    Level: intermediate

     97: .seealso: SNESGetLineSearch(), SNESLineSearchMonitorDefault(), SNESLineSearchMonitorCancel()
     98: @*/
     99: PetscErrorCode  SNESLineSearchMonitorSet(SNESLineSearch ls,PetscErrorCode (*f)(SNESLineSearch,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
    100: {
    101:   PetscInt       i;
    102:   PetscBool      identical;

    105:   for (i=0; i<ls->numbermonitors;i++) {
    106:     PetscMonitorCompare((PetscErrorCode (*)(void))f,mctx,monitordestroy,(PetscErrorCode (*)(void))ls->monitorftns[i],ls->monitorcontext[i],ls->monitordestroy[i],&identical);
    107:     if (identical) return 0;
    108:   }
    110:   ls->monitorftns[ls->numbermonitors]          = f;
    111:   ls->monitordestroy[ls->numbermonitors]   = monitordestroy;
    112:   ls->monitorcontext[ls->numbermonitors++] = (void*)mctx;
    113:   return 0;
    114: }

    116: /*@C
    117:    SNESLineSearchMonitorSolutionUpdate - Monitors each update a new function value the linesearch tries

    119:    Collective on SNESLineSearch

    121:    Input Parameters:
    122: +  ls - the SNES linesearch object
    123: -  vf - the context for the monitor, in this case it is an ASCII PetscViewer and format

    125:    Level: intermediate

    127: .seealso: SNESGetLineSearch(), SNESMonitorSet(), SNESMonitorSolution()
    128: @*/
    129: PetscErrorCode  SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls,PetscViewerAndFormat *vf)
    130: {
    131:   PetscViewer    viewer = vf->viewer;
    132:   Vec            Y,W,G;

    134:   SNESLineSearchGetVecs(ls,NULL,NULL,&Y,&W,&G);
    135:   PetscViewerPushFormat(viewer,vf->format);
    136:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted update to solution \n");
    137:   VecView(Y,viewer);
    138:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted new solution \n");
    139:   VecView(W,viewer);
    140:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted updated function value\n");
    141:   VecView(G,viewer);
    142:   PetscViewerPopFormat(viewer);
    143:   return 0;
    144: }

    146: /*@
    147:    SNESLineSearchCreate - Creates the line search context.

    149:    Logically Collective on Comm

    151:    Input Parameters:
    152: .  comm - MPI communicator for the line search (typically from the associated SNES context).

    154:    Output Parameters:
    155: .  outlinesearch - the new linesearch context

    157:    Level: developer

    159:    Notes:
    160:    The preferred calling sequence for users is to use SNESGetLineSearch() to acquire the SNESLineSearch instance
    161:    already associated with the SNES.  This function is for developer use.

    163: .seealso: LineSearchDestroy(), SNESGetLineSearch()
    164: @*/

    166: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
    167: {
    168:   SNESLineSearch linesearch;

    171:   SNESInitializePackage();
    172:   *outlinesearch = NULL;

    174:   PetscHeaderCreate(linesearch,SNESLINESEARCH_CLASSID, "SNESLineSearch","Linesearch","SNESLineSearch",comm,SNESLineSearchDestroy,SNESLineSearchView);

    176:   linesearch->vec_sol_new  = NULL;
    177:   linesearch->vec_func_new = NULL;
    178:   linesearch->vec_sol      = NULL;
    179:   linesearch->vec_func     = NULL;
    180:   linesearch->vec_update   = NULL;

    182:   linesearch->lambda       = 1.0;
    183:   linesearch->fnorm        = 1.0;
    184:   linesearch->ynorm        = 1.0;
    185:   linesearch->xnorm        = 1.0;
    186:   linesearch->result       = SNES_LINESEARCH_SUCCEEDED;
    187:   linesearch->norms        = PETSC_TRUE;
    188:   linesearch->keeplambda   = PETSC_FALSE;
    189:   linesearch->damping      = 1.0;
    190:   linesearch->maxstep      = 1e8;
    191:   linesearch->steptol      = 1e-12;
    192:   linesearch->rtol         = 1e-8;
    193:   linesearch->atol         = 1e-15;
    194:   linesearch->ltol         = 1e-8;
    195:   linesearch->precheckctx  = NULL;
    196:   linesearch->postcheckctx = NULL;
    197:   linesearch->max_its      = 1;
    198:   linesearch->setupcalled  = PETSC_FALSE;
    199:   linesearch->monitor      = NULL;
    200:   *outlinesearch           = linesearch;
    201:   return 0;
    202: }

    204: /*@
    205:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
    206:    any required vectors.

    208:    Collective on SNESLineSearch

    210:    Input Parameters:
    211: .  linesearch - The LineSearch instance.

    213:    Notes:
    214:    For most cases, this needn't be called by users or outside of SNESLineSearchApply().
    215:    The only current case where this is called outside of this is for the VI
    216:    solvers, which modify the solution and work vectors before the first call
    217:    of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be
    218:    allocated upfront.

    220:    Level: advanced

    222: .seealso: SNESGetLineSearch(), SNESLineSearchReset()
    223: @*/

    225: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
    226: {
    227:   if (!((PetscObject)linesearch)->type_name) {
    228:     SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);
    229:   }
    230:   if (!linesearch->setupcalled) {
    231:     if (!linesearch->vec_sol_new) {
    232:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
    233:     }
    234:     if (!linesearch->vec_func_new) {
    235:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
    236:     }
    237:     if (linesearch->ops->setup) {
    238:       (*linesearch->ops->setup)(linesearch);
    239:     }
    240:     if (!linesearch->ops->snesfunc) SNESLineSearchSetFunction(linesearch,SNESComputeFunction);
    241:     linesearch->lambda      = linesearch->damping;
    242:     linesearch->setupcalled = PETSC_TRUE;
    243:   }
    244:   return 0;
    245: }

    247: /*@
    248:    SNESLineSearchReset - Undoes the SNESLineSearchSetUp() and deletes any Vecs or Mats allocated by the line search.

    250:    Collective on SNESLineSearch

    252:    Input Parameters:
    253: .  linesearch - The LineSearch instance.

    255:    Notes:
    256:     Usually only called by SNESReset()

    258:    Level: developer

    260: .seealso: SNESGetLineSearch(), SNESLineSearchSetUp()
    261: @*/

    263: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
    264: {
    265:   if (linesearch->ops->reset) (*linesearch->ops->reset)(linesearch);

    267:   VecDestroy(&linesearch->vec_sol_new);
    268:   VecDestroy(&linesearch->vec_func_new);

    270:   VecDestroyVecs(linesearch->nwork, &linesearch->work);

    272:   linesearch->nwork       = 0;
    273:   linesearch->setupcalled = PETSC_FALSE;
    274:   return 0;
    275: }

    277: /*@C
    278:    SNESLineSearchSetFunction - Sets the function evaluation used by the SNES line search

    280:    Input Parameters:
    281: .  linesearch - the SNESLineSearch context
    282: +  func       - function evaluation routine

    284:    Level: developer

    286:    Notes:
    287:     This is used internally by PETSc and not called by users

    289: .seealso: SNESGetLineSearch(), SNESSetFunction()
    290: @*/
    291: PetscErrorCode  SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES,Vec,Vec))
    292: {
    294:   linesearch->ops->snesfunc = func;
    295:   return 0;
    296: }

    298: /*@C
    299:    SNESLineSearchSetPreCheck - Sets a user function that is called after the initial search direction has been computed but
    300:          before the line search routine has been applied. Allows the user to adjust the result of (usually a linear solve) that
    301:          determined the search direction.

    303:    Logically Collective on SNESLineSearch

    305:    Input Parameters:
    306: +  linesearch - the SNESLineSearch context
    307: .  func - [optional] function evaluation routine, see SNESLineSearchPreCheck() for the calling sequence
    308: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

    310:    Level: intermediate

    312: .seealso: SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
    313: @*/
    314: PetscErrorCode  SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void *ctx)
    315: {
    317:   if (func) linesearch->ops->precheck = func;
    318:   if (ctx) linesearch->precheckctx = ctx;
    319:   return 0;
    320: }

    322: /*@C
    323:    SNESLineSearchGetPreCheck - Gets the pre-check function for the line search routine.

    325:    Input Parameter:
    326: .  linesearch - the SNESLineSearch context

    328:    Output Parameters:
    329: +  func       - [optional] function evaluation routine, see SNESLineSearchPreCheck() for calling sequence
    330: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

    332:    Level: intermediate

    334: .seealso: SNESGetLineSearch(), SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck()
    335: @*/
    336: PetscErrorCode  SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void **ctx)
    337: {
    339:   if (func) *func = linesearch->ops->precheck;
    340:   if (ctx) *ctx = linesearch->precheckctx;
    341:   return 0;
    342: }

    344: /*@C
    345:    SNESLineSearchSetPostCheck - Sets a user function that is called after the line search has been applied to determine the step
    346:        direction and length. Allows the user a chance to change or override the decision of the line search routine

    348:    Logically Collective on SNESLineSearch

    350:    Input Parameters:
    351: +  linesearch - the SNESLineSearch context
    352: .  func - [optional] function evaluation routine, see SNESLineSearchPostCheck()  for the calling sequence
    353: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

    355:    Level: intermediate

    357: .seealso: SNESGetLineSearch(), SNESLineSearchPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchGetPostCheck()
    358: @*/
    359: PetscErrorCode  SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx)
    360: {
    362:   if (func) linesearch->ops->postcheck = func;
    363:   if (ctx) linesearch->postcheckctx = ctx;
    364:   return 0;
    365: }

    367: /*@C
    368:    SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine.

    370:    Input Parameter:
    371: .  linesearch - the SNESLineSearch context

    373:    Output Parameters:
    374: +  func - [optional] function evaluation routine, see for the calling sequence SNESLineSearchPostCheck()
    375: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

    377:    Level: intermediate

    379: .seealso: SNESGetLineSearch(), SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchPostCheck(), SNESLineSearchSetPreCheck()
    380: @*/
    381: PetscErrorCode  SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void **ctx)
    382: {
    384:   if (func) *func = linesearch->ops->postcheck;
    385:   if (ctx) *ctx = linesearch->postcheckctx;
    386:   return 0;
    387: }

    389: /*@
    390:    SNESLineSearchPreCheck - Prepares the line search for being applied.

    392:    Logically Collective on SNESLineSearch

    394:    Input Parameters:
    395: +  linesearch - The linesearch instance.
    396: .  X - The current solution
    397: -  Y - The step direction

    399:    Output Parameters:
    400: .  changed - Indicator that the precheck routine has changed anything

    402:    Level: developer

    404: .seealso: SNESGetLineSearch(), SNESLineSearchPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck()
    405: @*/
    406: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed)
    407: {
    408:   *changed = PETSC_FALSE;
    409:   if (linesearch->ops->precheck) {
    410:     (*linesearch->ops->precheck)(linesearch, X, Y, changed, linesearch->precheckctx);
    412:   }
    413:   return 0;
    414: }

    416: /*@
    417:    SNESLineSearchPostCheck - Prepares the line search for being applied.

    419:    Logically Collective on SNESLineSearch

    421:    Input Parameters:
    422: +  linesearch - The linesearch context
    423: .  X - The last solution
    424: .  Y - The step direction
    425: -  W - The updated solution, W = X + lambda*Y for some lambda

    427:    Output Parameters:
    428: +  changed_Y - Indicator if the direction Y has been changed.
    429: -  changed_W - Indicator if the new candidate solution W has been changed.

    431:    Level: developer

    433: .seealso: SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchSetPrecheck(), SNESLineSearchGetPrecheck()
    434: @*/
    435: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W)
    436: {
    437:   *changed_Y = PETSC_FALSE;
    438:   *changed_W = PETSC_FALSE;
    439:   if (linesearch->ops->postcheck) {
    440:     (*linesearch->ops->postcheck)(linesearch,X,Y,W,changed_Y,changed_W,linesearch->postcheckctx);
    443:   }
    444:   return 0;
    445: }

    447: /*@C
    448:    SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration

    450:    Logically Collective on SNESLineSearch

    452:    Input Parameters:
    453: +  linesearch - linesearch context
    454: .  X - base state for this step
    455: -  ctx - context for this function

    457:    Input/Output Parameter:
    458: .  Y - correction, possibly modified

    460:    Output Parameter:
    461: .  changed - flag indicating that Y was modified

    463:    Options Database Key:
    464: +  -snes_linesearch_precheck_picard - activate this routine
    465: -  -snes_linesearch_precheck_picard_angle - angle

    467:    Level: advanced

    469:    Notes:
    470:    This function should be passed to SNESLineSearchSetPreCheck()

    472:    The justification for this method involves the linear convergence of a Picard iteration
    473:    so the Picard linearization should be provided in place of the "Jacobian". This correction
    474:    is generally not useful when using a Newton linearization.

    476:    Reference:
    477:    Hindmarsh and Payne (1996) Time step limits for stable solutions of the ice sheet equation, Annals of Glaciology.

    479: .seealso: SNESGetLineSearch(), SNESLineSearchSetPreCheck()
    480: @*/
    481: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed,void *ctx)
    482: {
    483:   PetscReal      angle = *(PetscReal*)linesearch->precheckctx;
    484:   Vec            Ylast;
    485:   PetscScalar    dot;
    486:   PetscInt       iter;
    487:   PetscReal      ynorm,ylastnorm,theta,angle_radians;
    488:   SNES           snes;

    490:   SNESLineSearchGetSNES(linesearch, &snes);
    491:   PetscObjectQuery((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject*)&Ylast);
    492:   if (!Ylast) {
    493:     VecDuplicate(Y,&Ylast);
    494:     PetscObjectCompose((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject)Ylast);
    495:     PetscObjectDereference((PetscObject)Ylast);
    496:   }
    497:   SNESGetIterationNumber(snes,&iter);
    498:   if (iter < 2) {
    499:     VecCopy(Y,Ylast);
    500:     *changed = PETSC_FALSE;
    501:     return 0;
    502:   }

    504:   VecDot(Y,Ylast,&dot);
    505:   VecNorm(Y,NORM_2,&ynorm);
    506:   VecNorm(Ylast,NORM_2,&ylastnorm);
    507:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
    508:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm),-1.0,1.0));
    509:   angle_radians = angle * PETSC_PI / 180.;
    510:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
    511:     /* Modify the step Y */
    512:     PetscReal alpha,ydiffnorm;
    513:     VecAXPY(Ylast,-1.0,Y);
    514:     VecNorm(Ylast,NORM_2,&ydiffnorm);
    515:     alpha = (ydiffnorm > .001*ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
    516:     VecCopy(Y,Ylast);
    517:     VecScale(Y,alpha);
    518:     PetscInfo(snes,"Angle %14.12e degrees less than threshold %14.12e, corrected step by alpha=%14.12e\n",(double)(theta*180./PETSC_PI),(double)angle,(double)alpha);
    519:     *changed = PETSC_TRUE;
    520:   } else {
    521:     PetscInfo(snes,"Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n",(double)(theta*180./PETSC_PI),(double)angle);
    522:     VecCopy(Y,Ylast);
    523:     *changed = PETSC_FALSE;
    524:   }
    525:   return 0;
    526: }

    528: /*@
    529:    SNESLineSearchApply - Computes the line-search update.

    531:    Collective on SNESLineSearch

    533:    Input Parameters:
    534: +  linesearch - The linesearch context
    535: -  Y - The search direction

    537:    Input/Output Parameters:
    538: +  X - The current solution, on output the new solution
    539: .  F - The current function, on output the new function
    540: -  fnorm - The current norm, on output the new function norm

    542:    Options Database Keys:
    543: + -snes_linesearch_type - basic, bt, l2, cp, nleqerr, shell
    544: . -snes_linesearch_monitor [:filename] - Print progress of line searches
    545: . -snes_linesearch_damping - The linesearch damping parameter, default is 1.0 (no damping)
    546: . -snes_linesearch_norms   - Turn on/off the linesearch norms computation (SNESLineSearchSetComputeNorms())
    547: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
    548: - -snes_linesearch_max_it - The number of iterations for iterative line searches

    550:    Notes:
    551:    This is typically called from within a SNESSolve() implementation in order to
    552:    help with convergence of the nonlinear method.  Various SNES types use line searches
    553:    in different ways, but the overarching theme is that a line search is used to determine
    554:    an optimal damping parameter of a step at each iteration of the method.  Each
    555:    application of the line search may invoke SNESComputeFunction() several times, and
    556:    therefore may be fairly expensive.

    558:    Level: Intermediate

    560: .seealso: SNESGetLineSearch(), SNESLineSearchCreate(), SNESLineSearchPreCheck(), SNESLineSearchPostCheck(), SNESSolve(), SNESComputeFunction(), SNESLineSearchSetComputeNorms(),
    561:           SNESLineSearchType, SNESLineSearchSetType()
    562: @*/
    563: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y)
    564: {

    570:   linesearch->result = SNES_LINESEARCH_SUCCEEDED;

    572:   linesearch->vec_sol    = X;
    573:   linesearch->vec_update = Y;
    574:   linesearch->vec_func   = F;

    576:   SNESLineSearchSetUp(linesearch);

    578:   if (!linesearch->keeplambda) linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */

    580:   if (fnorm) linesearch->fnorm = *fnorm;
    581:   else {
    582:     VecNorm(F, NORM_2, &linesearch->fnorm);
    583:   }

    585:   PetscLogEventBegin(SNESLINESEARCH_Apply,linesearch,X,F,Y);

    587:   (*linesearch->ops->apply)(linesearch);

    589:   PetscLogEventEnd(SNESLINESEARCH_Apply,linesearch,X,F,Y);

    591:   if (fnorm) *fnorm = linesearch->fnorm;
    592:   return 0;
    593: }

    595: /*@
    596:    SNESLineSearchDestroy - Destroys the line search instance.

    598:    Collective on SNESLineSearch

    600:    Input Parameters:
    601: .  linesearch - The linesearch context

    603:    Level: developer

    605: .seealso: SNESGetLineSearch(), SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy()
    606: @*/
    607: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch)
    608: {
    609:   if (!*linesearch) return 0;
    611:   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = NULL; return 0;}
    612:   PetscObjectSAWsViewOff((PetscObject)*linesearch);
    613:   SNESLineSearchReset(*linesearch);
    614:   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
    615:   PetscViewerDestroy(&(*linesearch)->monitor);
    616:   SNESLineSearchMonitorCancel((*linesearch));
    617:   PetscHeaderDestroy(linesearch);
    618:   return 0;
    619: }

    621: /*@
    622:    SNESLineSearchSetDefaultMonitor - Turns on/off printing useful information and debugging output about the line search.

    624:    Input Parameters:
    625: +  linesearch - the linesearch object
    626: -  viewer - an ASCII PetscViewer or NULL to turn off monitor

    628:    Logically Collective on SNESLineSearch

    630:    Options Database:
    631: .   -snes_linesearch_monitor [:filename] - enables the monitor

    633:    Level: intermediate

    635:    Developer Note: This monitor is implemented differently than the other SNESLineSearchMonitors that are set with
    636:      SNESLineSearchMonitorSet() since it is called in many locations of the line search routines to display aspects of the
    637:      line search that are not visible to the other monitors.

    639: .seealso: SNESGetLineSearch(), SNESLineSearchGetDefaultMonitor(), PetscViewer, SNESLineSearchSetMonitor()
    640: @*/
    641: PetscErrorCode  SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
    642: {
    643:   if (viewer) PetscObjectReference((PetscObject)viewer);
    644:   PetscViewerDestroy(&linesearch->monitor);
    645:   linesearch->monitor = viewer;
    646:   return 0;
    647: }

    649: /*@
    650:    SNESLineSearchGetDefaultMonitor - Gets the PetscViewer instance for the line search monitor.

    652:    Input Parameter:
    653: .  linesearch - linesearch context

    655:    Output Parameter:
    656: .  monitor - monitor context

    658:    Logically Collective on SNES

    660:    Options Database Keys:
    661: .   -snes_linesearch_monitor - enables the monitor

    663:    Level: intermediate

    665: .seealso: SNESGetLineSearch(), SNESLineSearchSetDefaultMonitor(), PetscViewer
    666: @*/
    667: PetscErrorCode  SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
    668: {
    670:   *monitor = linesearch->monitor;
    671:   return 0;
    672: }

    674: /*@C
    675:    SNESLineSearchMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user

    677:    Collective on SNESLineSearch

    679:    Input Parameters:
    680: +  ls - LineSearch object you wish to monitor
    681: .  name - the monitor type one is seeking
    682: .  help - message indicating what monitoring is done
    683: .  manual - manual page for the monitor
    684: .  monitor - the monitor function
    685: -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the SNESLineSearch or PetscViewer objects

    687:    Level: developer

    689: .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
    690:           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
    691:           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
    692:           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
    693:           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
    694:           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
    695:           PetscOptionsFList(), PetscOptionsEList()
    696: @*/
    697: PetscErrorCode  SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(SNESLineSearch,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(SNESLineSearch,PetscViewerAndFormat*))
    698: {
    699:   PetscViewer       viewer;
    700:   PetscViewerFormat format;
    701:   PetscBool         flg;

    703:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls),((PetscObject) ls)->options,((PetscObject)ls)->prefix,name,&viewer,&format,&flg);
    704:   if (flg) {
    705:     PetscViewerAndFormat *vf;
    706:     PetscViewerAndFormatCreate(viewer,format,&vf);
    707:     PetscObjectDereference((PetscObject)viewer);
    708:     if (monitorsetup) {
    709:       (*monitorsetup)(ls,vf);
    710:     }
    711:     SNESLineSearchMonitorSet(ls,(PetscErrorCode (*)(SNESLineSearch,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);
    712:   }
    713:   return 0;
    714: }

    716: /*@
    717:    SNESLineSearchSetFromOptions - Sets options for the line search

    719:    Input Parameter:
    720: .  linesearch - linesearch context

    722:    Options Database Keys:
    723: + -snes_linesearch_type <type> - basic, bt, l2, cp, nleqerr, shell
    724: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
    725: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch typem (SNESLineSearchSetComputeNorms())
    726: . -snes_linesearch_minlambda - The minimum step length
    727: . -snes_linesearch_maxstep - The maximum step size
    728: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
    729: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
    730: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
    731: . -snes_linesearch_max_it - The number of iterations for iterative line searches
    732: . -snes_linesearch_monitor [:filename] - Print progress of line searches
    733: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
    734: . -snes_linesearch_damping - The linesearch damping parameter
    735: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
    736: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
    737: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method

    739:    Logically Collective on SNESLineSearch

    741:    Level: intermediate

    743: .seealso: SNESLineSearchCreate(), SNESLineSearchSetOrder(), SNESLineSearchSetType(), SNESLineSearchSetTolerances(), SNESLineSearchSetDamping(), SNESLineSearchPreCheckPicard(),
    744:           SNESLineSearchType, SNESLineSearchSetComputeNorms()
    745: @*/
    746: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
    747: {
    748:   PetscErrorCode    ierr;
    749:   const char        *deft = SNESLINESEARCHBASIC;
    750:   char              type[256];
    751:   PetscBool         flg, set;
    752:   PetscViewer       viewer;

    754:   SNESLineSearchRegisterAll();

    756:   PetscObjectOptionsBegin((PetscObject)linesearch);
    757:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
    758:   PetscOptionsFList("-snes_linesearch_type","Linesearch type","SNESLineSearchSetType",SNESLineSearchList,deft,type,256,&flg);
    759:   if (flg) {
    760:     SNESLineSearchSetType(linesearch,type);
    761:   } else if (!((PetscObject)linesearch)->type_name) {
    762:     SNESLineSearchSetType(linesearch,deft);
    763:   }

    765:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch),((PetscObject) linesearch)->options,((PetscObject)linesearch)->prefix,"-snes_linesearch_monitor",&viewer,NULL,&set);
    766:   if (set) {
    767:     SNESLineSearchSetDefaultMonitor(linesearch,viewer);
    768:     PetscViewerDestroy(&viewer);
    769:   }
    770:   SNESLineSearchMonitorSetFromOptions(linesearch,"-snes_linesearch_monitor_solution_update","View correction at each iteration","SNESLineSearchMonitorSolutionUpdate",SNESLineSearchMonitorSolutionUpdate,NULL);

    772:   /* tolerances */
    773:   PetscOptionsReal("-snes_linesearch_minlambda","Minimum step length","SNESLineSearchSetTolerances",linesearch->steptol,&linesearch->steptol,NULL);
    774:   PetscOptionsReal("-snes_linesearch_maxstep","Maximum step size","SNESLineSearchSetTolerances",linesearch->maxstep,&linesearch->maxstep,NULL);
    775:   PetscOptionsReal("-snes_linesearch_rtol","Relative tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->rtol,&linesearch->rtol,NULL);
    776:   PetscOptionsReal("-snes_linesearch_atol","Absolute tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->atol,&linesearch->atol,NULL);
    777:   PetscOptionsReal("-snes_linesearch_ltol","Change in lambda tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->ltol,&linesearch->ltol,NULL);
    778:   PetscOptionsInt("-snes_linesearch_max_it","Maximum iterations for iterative line searches","SNESLineSearchSetTolerances",linesearch->max_its,&linesearch->max_its,NULL);

    780:   /* damping parameters */
    781:   PetscOptionsReal("-snes_linesearch_damping","Line search damping and initial step guess","SNESLineSearchSetDamping",linesearch->damping,&linesearch->damping,NULL);

    783:   PetscOptionsBool("-snes_linesearch_keeplambda","Use previous lambda as damping","SNESLineSearchSetKeepLambda",linesearch->keeplambda,&linesearch->keeplambda,NULL);

    785:   /* precheck */
    786:   PetscOptionsBool("-snes_linesearch_precheck_picard","Use a correction that sometimes improves convergence of Picard iteration","SNESLineSearchPreCheckPicard",flg,&flg,&set);
    787:   if (set) {
    788:     if (flg) {
    789:       linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */

    791:       PetscOptionsReal("-snes_linesearch_precheck_picard_angle","Maximum angle at which to activate the correction",
    792:                               "none",linesearch->precheck_picard_angle,&linesearch->precheck_picard_angle,NULL);
    793:       SNESLineSearchSetPreCheck(linesearch,SNESLineSearchPreCheckPicard,&linesearch->precheck_picard_angle);
    794:     } else {
    795:       SNESLineSearchSetPreCheck(linesearch,NULL,NULL);
    796:     }
    797:   }
    798:   PetscOptionsInt("-snes_linesearch_order","Order of approximation used in the line search","SNESLineSearchSetOrder",linesearch->order,&linesearch->order,NULL);
    799:   PetscOptionsBool("-snes_linesearch_norms","Compute final norms in line search","SNESLineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,NULL);

    801:   if (linesearch->ops->setfromoptions) {
    802:     (*linesearch->ops->setfromoptions)(PetscOptionsObject,linesearch);
    803:   }

    805:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)linesearch);
    806:   PetscOptionsEnd();
    807:   return 0;
    808: }

    810: /*@
    811:    SNESLineSearchView - Prints useful information about the line search

    813:    Input Parameters:
    814: .  linesearch - linesearch context

    816:    Logically Collective on SNESLineSearch

    818:    Level: intermediate

    820: .seealso: SNESLineSearchCreate()
    821: @*/
    822: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
    823: {
    824:   PetscBool      iascii;

    827:   if (!viewer) {
    828:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch),&viewer);
    829:   }

    833:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    834:   if (iascii) {
    835:     PetscObjectPrintClassNamePrefixType((PetscObject)linesearch,viewer);
    836:     if (linesearch->ops->view) {
    837:       PetscViewerASCIIPushTab(viewer);
    838:       (*linesearch->ops->view)(linesearch,viewer);
    839:       PetscViewerASCIIPopTab(viewer);
    840:     }
    841:     PetscViewerASCIIPrintf(viewer,"  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol);
    842:     PetscViewerASCIIPrintf(viewer,"  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol);
    843:     PetscViewerASCIIPrintf(viewer,"  maximum iterations=%D\n", linesearch->max_its);
    844:     if (linesearch->ops->precheck) {
    845:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
    846:         PetscViewerASCIIPrintf(viewer,"  using precheck step to speed up Picard convergence\n", linesearch->max_its);
    847:       } else {
    848:         PetscViewerASCIIPrintf(viewer,"  using user-defined precheck step\n", linesearch->max_its);
    849:       }
    850:     }
    851:     if (linesearch->ops->postcheck) {
    852:       PetscViewerASCIIPrintf(viewer,"  using user-defined postcheck step\n", linesearch->max_its);
    853:     }
    854:   }
    855:   return 0;
    856: }

    858: /*@C
    859:    SNESLineSearchGetType - Gets the linesearch type

    861:    Logically Collective on SNESLineSearch

    863:    Input Parameters:
    864: .  linesearch - linesearch context

    866:    Output Parameters:
    867: -  type - The type of line search, or NULL if not set

    869:    Level: intermediate

    871: .seealso: SNESLineSearchCreate(), SNESLineSearchType, SNESLineSearchSetFromOptions(), SNESLineSearchSetType()
    872: @*/
    873: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
    874: {
    877:   *type = ((PetscObject)linesearch)->type_name;
    878:   return 0;
    879: }

    881: /*@C
    882:    SNESLineSearchSetType - Sets the linesearch type

    884:    Logically Collective on SNESLineSearch

    886:    Input Parameters:
    887: +  linesearch - linesearch context
    888: -  type - The type of line search to be used

    890:    Available Types:
    891: +  SNESLINESEARCHBASIC - Simple damping line search, defaults to using the full Newton step
    892: .  SNESLINESEARCHBT - Backtracking line search over the L2 norm of the function
    893: .  SNESLINESEARCHL2 - Secant line search over the L2 norm of the function
    894: .  SNESLINESEARCHCP - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
    895: .  SNESLINESEARCHNLEQERR - Affine-covariant error-oriented linesearch
    896: -  SNESLINESEARCHSHELL - User provided SNESLineSearch implementation

    898:    Options Database:
    899: .  -snes_linesearch_type <type> - basic, bt, l2, cp, nleqerr, shell

    901:    Level: intermediate

    903: .seealso: SNESLineSearchCreate(), SNESLineSearchType, SNESLineSearchSetFromOptions(), SNESLineSearchGetType()
    904: @*/
    905: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
    906: {
    907:   PetscBool      match;
    908:   PetscErrorCode (*r)(SNESLineSearch);

    913:   PetscObjectTypeCompare((PetscObject)linesearch,type,&match);
    914:   if (match) return 0;

    916:   PetscFunctionListFind(SNESLineSearchList,type,&r);
    918:   /* Destroy the previous private linesearch context */
    919:   if (linesearch->ops->destroy) {
    920:     (*(linesearch)->ops->destroy)(linesearch);
    921:     linesearch->ops->destroy = NULL;
    922:   }
    923:   /* Reinitialize function pointers in SNESLineSearchOps structure */
    924:   linesearch->ops->apply          = NULL;
    925:   linesearch->ops->view           = NULL;
    926:   linesearch->ops->setfromoptions = NULL;
    927:   linesearch->ops->destroy        = NULL;

    929:   PetscObjectChangeTypeName((PetscObject)linesearch,type);
    930:   (*r)(linesearch);
    931:   return 0;
    932: }

    934: /*@
    935:    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.

    937:    Input Parameters:
    938: +  linesearch - linesearch context
    939: -  snes - The snes instance

    941:    Level: developer

    943:    Notes:
    944:    This happens automatically when the line search is obtained/created with
    945:    SNESGetLineSearch().  This routine is therefore mainly called within SNES
    946:    implementations.

    948:    Level: developer

    950: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    951: @*/
    952: PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
    953: {
    956:   linesearch->snes = snes;
    957:   return 0;
    958: }

    960: /*@
    961:    SNESLineSearchGetSNES - Gets the SNES instance associated with the line search.
    962:    Having an associated SNES is necessary because most line search implementations must be able to
    963:    evaluate the function using SNESComputeFunction() for the associated SNES.  This routine
    964:    is used in the line search implementations when one must get this associated SNES instance.

    966:    Input Parameters:
    967: .  linesearch - linesearch context

    969:    Output Parameters:
    970: .  snes - The snes instance

    972:    Level: developer

    974: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    975: @*/
    976: PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
    977: {
    980:   *snes = linesearch->snes;
    981:   return 0;
    982: }

    984: /*@
    985:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

    987:    Input Parameters:
    988: .  linesearch - linesearch context

    990:    Output Parameters:
    991: .  lambda - The last steplength computed during SNESLineSearchApply()

    993:    Level: advanced

    995:    Notes:
    996:    This is useful in methods where the solver is ill-scaled and
    997:    requires some adaptive notion of the difference in scale between the
    998:    solution and the function.  For instance, SNESQN may be scaled by the
    999:    line search lambda using the argument -snes_qn_scaling ls.

    1001: .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply()
    1002: @*/
    1003: PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
    1004: {
    1007:   *lambda = linesearch->lambda;
    1008:   return 0;
    1009: }

    1011: /*@
    1012:    SNESLineSearchSetLambda - Sets the linesearch steplength.

    1014:    Input Parameters:
    1015: +  linesearch - linesearch context
    1016: -  lambda - The last steplength.

    1018:    Notes:
    1019:    This routine is typically used within implementations of SNESLineSearchApply()
    1020:    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
    1021:    added in order to facilitate Quasi-Newton methods that use the previous steplength
    1022:    as an inner scaling parameter.

    1024:    Level: advanced

    1026: .seealso: SNESLineSearchGetLambda()
    1027: @*/
    1028: PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
    1029: {
    1031:   linesearch->lambda = lambda;
    1032:   return 0;
    1033: }

    1035: /*@
    1036:    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
    1037:    tolerances for the relative and absolute change in the function norm, the change
    1038:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
    1039:    and the maximum number of iterations the line search procedure may take.

    1041:    Input Parameter:
    1042: .  linesearch - linesearch context

    1044:    Output Parameters:
    1045: +  steptol - The minimum steplength
    1046: .  maxstep - The maximum steplength
    1047: .  rtol    - The relative tolerance for iterative line searches
    1048: .  atol    - The absolute tolerance for iterative line searches
    1049: .  ltol    - The change in lambda tolerance for iterative line searches
    1050: -  max_it  - The maximum number of iterations of the line search

    1052:    Level: intermediate

    1054:    Notes:
    1055:    Different line searches may implement these parameters slightly differently as
    1056:    the type requires.

    1058: .seealso: SNESLineSearchSetTolerances()
    1059: @*/
    1060: PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
    1061: {
    1063:   if (steptol) {
    1065:     *steptol = linesearch->steptol;
    1066:   }
    1067:   if (maxstep) {
    1069:     *maxstep = linesearch->maxstep;
    1070:   }
    1071:   if (rtol) {
    1073:     *rtol = linesearch->rtol;
    1074:   }
    1075:   if (atol) {
    1077:     *atol = linesearch->atol;
    1078:   }
    1079:   if (ltol) {
    1081:     *ltol = linesearch->ltol;
    1082:   }
    1083:   if (max_its) {
    1085:     *max_its = linesearch->max_its;
    1086:   }
    1087:   return 0;
    1088: }

    1090: /*@
    1091:    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
    1092:    tolerances for the relative and absolute change in the function norm, the change
    1093:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
    1094:    and the maximum number of iterations the line search procedure may take.

    1096:    Input Parameters:
    1097: +  linesearch - linesearch context
    1098: .  steptol - The minimum steplength
    1099: .  maxstep - The maximum steplength
    1100: .  rtol    - The relative tolerance for iterative line searches
    1101: .  atol    - The absolute tolerance for iterative line searches
    1102: .  ltol    - The change in lambda tolerance for iterative line searches
    1103: -  max_it  - The maximum number of iterations of the line search

    1105:    Notes:
    1106:    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
    1107:    place of an argument.

    1109:    Level: intermediate

    1111: .seealso: SNESLineSearchGetTolerances()
    1112: @*/
    1113: PetscErrorCode  SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
    1114: {

    1123:   if (steptol!= PETSC_DEFAULT) {
    1125:     linesearch->steptol = steptol;
    1126:   }

    1128:   if (maxstep!= PETSC_DEFAULT) {
    1130:     linesearch->maxstep = maxstep;
    1131:   }

    1133:   if (rtol != PETSC_DEFAULT) {
    1135:     linesearch->rtol = rtol;
    1136:   }

    1138:   if (atol != PETSC_DEFAULT) {
    1140:     linesearch->atol = atol;
    1141:   }

    1143:   if (ltol != PETSC_DEFAULT) {
    1145:     linesearch->ltol = ltol;
    1146:   }

    1148:   if (max_its != PETSC_DEFAULT) {
    1150:     linesearch->max_its = max_its;
    1151:   }
    1152:   return 0;
    1153: }

    1155: /*@
    1156:    SNESLineSearchGetDamping - Gets the line search damping parameter.

    1158:    Input Parameters:
    1159: .  linesearch - linesearch context

    1161:    Output Parameters:
    1162: .  damping - The damping parameter

    1164:    Level: advanced

    1166: .seealso: SNESLineSearchGetStepTolerance(), SNESQN
    1167: @*/

    1169: PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
    1170: {
    1173:   *damping = linesearch->damping;
    1174:   return 0;
    1175: }

    1177: /*@
    1178:    SNESLineSearchSetDamping - Sets the line search damping parameter.

    1180:    Input Parameters:
    1181: +  linesearch - linesearch context
    1182: -  damping - The damping parameter

    1184:    Options Database:
    1185: .   -snes_linesearch_damping
    1186:    Level: intermediate

    1188:    Notes:
    1189:    The basic line search merely takes the update step scaled by the damping parameter.
    1190:    The use of the damping parameter in the l2 and cp line searches is much more subtle;
    1191:    it is used as a starting point in calculating the secant step. However, the eventual
    1192:    step may be of greater length than the damping parameter.  In the bt line search it is
    1193:    used as the maximum possible step length, as the bt line search only backtracks.

    1195: .seealso: SNESLineSearchGetDamping()
    1196: @*/
    1197: PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
    1198: {
    1200:   linesearch->damping = damping;
    1201:   return 0;
    1202: }

    1204: /*@
    1205:    SNESLineSearchGetOrder - Gets the line search approximation order.

    1207:    Input Parameters:
    1208: .  linesearch - linesearch context

    1210:    Output Parameters:
    1211: .  order - The order

    1213:    Possible Values for order:
    1214: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1215: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1216: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1218:    Level: intermediate

    1220: .seealso: SNESLineSearchSetOrder()
    1221: @*/

    1223: PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
    1224: {
    1227:   *order = linesearch->order;
    1228:   return 0;
    1229: }

    1231: /*@
    1232:    SNESLineSearchSetOrder - Sets the maximum order of the polynomial fit used in the line search

    1234:    Input Parameters:
    1235: +  linesearch - linesearch context
    1236: -  order - The damping parameter

    1238:    Level: intermediate

    1240:    Possible Values for order:
    1241: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1242: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1243: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1245:    Notes:
    1246:    Variable orders are supported by the following line searches:
    1247: +  bt - cubic and quadratic
    1248: -  cp - linear and quadratic

    1250: .seealso: SNESLineSearchGetOrder(), SNESLineSearchSetDamping()
    1251: @*/
    1252: PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
    1253: {
    1255:   linesearch->order = order;
    1256:   return 0;
    1257: }

    1259: /*@
    1260:    SNESLineSearchGetNorms - Gets the norms for for X, Y, and F.

    1262:    Input Parameter:
    1263: .  linesearch - linesearch context

    1265:    Output Parameters:
    1266: +  xnorm - The norm of the current solution
    1267: .  fnorm - The norm of the current function
    1268: -  ynorm - The norm of the current update

    1270:    Notes:
    1271:    This function is mainly called from SNES implementations.

    1273:    Level: developer

    1275: .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs()
    1276: @*/
    1277: PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
    1278: {
    1280:   if (xnorm) *xnorm = linesearch->xnorm;
    1281:   if (fnorm) *fnorm = linesearch->fnorm;
    1282:   if (ynorm) *ynorm = linesearch->ynorm;
    1283:   return 0;
    1284: }

    1286: /*@
    1287:    SNESLineSearchSetNorms - Gets the computed norms for for X, Y, and F.

    1289:    Input Parameters:
    1290: +  linesearch - linesearch context
    1291: .  xnorm - The norm of the current solution
    1292: .  fnorm - The norm of the current function
    1293: -  ynorm - The norm of the current update

    1295:    Level: advanced

    1297: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1298: @*/
    1299: PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
    1300: {
    1302:   linesearch->xnorm = xnorm;
    1303:   linesearch->fnorm = fnorm;
    1304:   linesearch->ynorm = ynorm;
    1305:   return 0;
    1306: }

    1308: /*@
    1309:    SNESLineSearchComputeNorms - Computes the norms of X, F, and Y.

    1311:    Input Parameters:
    1312: .  linesearch - linesearch context

    1314:    Options Database Keys:
    1315: .   -snes_linesearch_norms - turn norm computation on or off

    1317:    Level: intermediate

    1319: .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms()
    1320: @*/
    1321: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
    1322: {
    1323:   SNES           snes;

    1325:   if (linesearch->norms) {
    1326:     if (linesearch->ops->vinorm) {
    1327:       SNESLineSearchGetSNES(linesearch, &snes);
    1328:       VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
    1329:       VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1330:       (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
    1331:     } else {
    1332:       VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm);
    1333:       VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm);
    1334:       VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1335:       VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm);
    1336:       VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm);
    1337:       VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm);
    1338:     }
    1339:   }
    1340:   return 0;
    1341: }

    1343: /*@
    1344:    SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search.

    1346:    Input Parameters:
    1347: +  linesearch  - linesearch context
    1348: -  flg  - indicates whether or not to compute norms

    1350:    Options Database Keys:
    1351: .   -snes_linesearch_norms <true> - Turns on/off computation of the norms for basic linesearch

    1353:    Notes:
    1354:    This is most relevant to the SNESLINESEARCHBASIC line search type since most line searches have a stopping criteria involving the norm.

    1356:    Level: intermediate

    1358: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC
    1359: @*/
    1360: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
    1361: {
    1362:   linesearch->norms = flg;
    1363:   return 0;
    1364: }

    1366: /*@
    1367:    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context

    1369:    Input Parameter:
    1370: .  linesearch - linesearch context

    1372:    Output Parameters:
    1373: +  X - Solution vector
    1374: .  F - Function vector
    1375: .  Y - Search direction vector
    1376: .  W - Solution work vector
    1377: -  G - Function work vector

    1379:    Notes:
    1380:    At the beginning of a line search application, X should contain a
    1381:    solution and the vector F the function computed at X.  At the end of the
    1382:    line search application, X should contain the new solution, and F the
    1383:    function evaluated at the new solution.

    1385:    These vectors are owned by the SNESLineSearch and should not be destroyed by the caller

    1387:    Level: advanced

    1389: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1390: @*/
    1391: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
    1392: {
    1394:   if (X) {
    1396:     *X = linesearch->vec_sol;
    1397:   }
    1398:   if (F) {
    1400:     *F = linesearch->vec_func;
    1401:   }
    1402:   if (Y) {
    1404:     *Y = linesearch->vec_update;
    1405:   }
    1406:   if (W) {
    1408:     *W = linesearch->vec_sol_new;
    1409:   }
    1410:   if (G) {
    1412:     *G = linesearch->vec_func_new;
    1413:   }
    1414:   return 0;
    1415: }

    1417: /*@
    1418:    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context

    1420:    Input Parameters:
    1421: +  linesearch - linesearch context
    1422: .  X - Solution vector
    1423: .  F - Function vector
    1424: .  Y - Search direction vector
    1425: .  W - Solution work vector
    1426: -  G - Function work vector

    1428:    Level: advanced

    1430: .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs()
    1431: @*/
    1432: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
    1433: {
    1435:   if (X) {
    1437:     linesearch->vec_sol = X;
    1438:   }
    1439:   if (F) {
    1441:     linesearch->vec_func = F;
    1442:   }
    1443:   if (Y) {
    1445:     linesearch->vec_update = Y;
    1446:   }
    1447:   if (W) {
    1449:     linesearch->vec_sol_new = W;
    1450:   }
    1451:   if (G) {
    1453:     linesearch->vec_func_new = G;
    1454:   }
    1455:   return 0;
    1456: }

    1458: /*@C
    1459:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
    1460:    SNES options in the database.

    1462:    Logically Collective on SNESLineSearch

    1464:    Input Parameters:
    1465: +  snes - the SNES context
    1466: -  prefix - the prefix to prepend to all option names

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

    1472:    Level: advanced

    1474: .seealso: SNESGetOptionsPrefix()
    1475: @*/
    1476: PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
    1477: {
    1479:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);
    1480:   return 0;
    1481: }

    1483: /*@C
    1484:    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
    1485:    SNESLineSearch options in the database.

    1487:    Not Collective

    1489:    Input Parameter:
    1490: .  linesearch - the SNESLineSearch context

    1492:    Output Parameter:
    1493: .  prefix - pointer to the prefix string used

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

    1499:    Level: advanced

    1501: .seealso: SNESAppendOptionsPrefix()
    1502: @*/
    1503: PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
    1504: {
    1506:   PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);
    1507:   return 0;
    1508: }

    1510: /*@C
    1511:    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.

    1513:    Input Parameters:
    1514: +  linesearch - the SNESLineSearch context
    1515: -  nwork - the number of work vectors

    1517:    Level: developer

    1519: .seealso: SNESSetWorkVecs()
    1520: @*/
    1521: PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
    1522: {
    1523:   if (linesearch->vec_sol) {
    1524:     VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
    1525:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
    1526:   return 0;
    1527: }

    1529: /*@
    1530:    SNESLineSearchGetReason - Gets the success/failure status of the last line search application

    1532:    Input Parameters:
    1533: .  linesearch - linesearch context

    1535:    Output Parameters:
    1536: .  result - The success or failure status

    1538:    Notes:
    1539:    This is typically called after SNESLineSearchApply() in order to determine if the line-search failed
    1540:    (and set the SNES convergence accordingly).

    1542:    Level: intermediate

    1544: .seealso: SNESLineSearchSetReason(), SNESLineSearchReason
    1545: @*/
    1546: PetscErrorCode  SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
    1547: {
    1550:   *result = linesearch->result;
    1551:   return 0;
    1552: }

    1554: /*@
    1555:    SNESLineSearchSetReason - Sets the success/failure status of the last line search application

    1557:    Input Parameters:
    1558: +  linesearch - linesearch context
    1559: -  result - The success or failure status

    1561:    Notes:
    1562:    This is typically called in a SNESLineSearchApply() or SNESLineSearchShell implementation to set
    1563:    the success or failure of the line search method.

    1565:    Level: developer

    1567: .seealso: SNESLineSearchGetSResult()
    1568: @*/
    1569: PetscErrorCode  SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
    1570: {
    1572:   linesearch->result = result;
    1573:   return 0;
    1574: }

    1576: /*@C
    1577:    SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation.

    1579:    Input Parameters:
    1580: +  snes - nonlinear context obtained from SNESCreate()
    1581: .  projectfunc - function for projecting the function to the bounds
    1582: -  normfunc - function for computing the norm of an active set

    1584:    Logically Collective on SNES

    1586:    Calling sequence of projectfunc:
    1587: .vb
    1588:    projectfunc (SNES snes, Vec X)
    1589: .ve

    1591:     Input parameters for projectfunc:
    1592: +   snes - nonlinear context
    1593: -   X - current solution

    1595:     Output parameters for projectfunc:
    1596: .   X - Projected solution

    1598:    Calling sequence of normfunc:
    1599: .vb
    1600:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
    1601: .ve

    1603:     Input parameters for normfunc:
    1604: +   snes - nonlinear context
    1605: .   X - current solution
    1606: -   F - current residual

    1608:     Output parameters for normfunc:
    1609: .   fnorm - VI-specific norm of the function

    1611:     Notes:
    1612:     The VI solvers require projection of the solution to the feasible set.  projectfunc should implement this.

    1614:     The VI solvers require special evaluation of the function norm such that the norm is only calculated
    1615:     on the inactive set.  This should be implemented by normfunc.

    1617:     Level: developer

    1619: .seealso: SNESLineSearchGetVIFunctions(), SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck()
    1620: @*/
    1621: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
    1622: {
    1624:   if (projectfunc) linesearch->ops->viproject = projectfunc;
    1625:   if (normfunc) linesearch->ops->vinorm = normfunc;
    1626:   return 0;
    1627: }

    1629: /*@C
    1630:    SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation.

    1632:    Input Parameter:
    1633: .  linesearch - the line search context, obtain with SNESGetLineSearch()

    1635:    Output Parameters:
    1636: +  projectfunc - function for projecting the function to the bounds
    1637: -  normfunc - function for computing the norm of an active set

    1639:    Logically Collective on SNES

    1641:     Level: developer

    1643: .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
    1644: @*/
    1645: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
    1646: {
    1647:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
    1648:   if (normfunc) *normfunc = linesearch->ops->vinorm;
    1649:   return 0;
    1650: }

    1652: /*@C
    1653:   SNESLineSearchRegister - See SNESLineSearchRegister()

    1655:   Level: advanced
    1656: @*/
    1657: PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
    1658: {
    1659:   SNESInitializePackage();
    1660:   PetscFunctionListAdd(&SNESLineSearchList,sname,function);
    1661:   return 0;
    1662: }