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: {
     35:   PetscInt       i;

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

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

     51:    Collective on SNES

     53:    Input Parameters:
     54: .  ls - the linesearch object

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

     60:    Level: developer

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

     70:   for (i=0; i<n; i++) {
     71:     (*ls->monitorftns[i])(ls,ls->monitorcontext[i]);
     72:   }
     73:   return(0);
     74: }

     76: /*@C
     77:    SNESLineSearchMonitorSet - Sets an ADDITIONAL function that is to be used at every
     78:    iteration of the nonlinear solver to display the iteration's
     79:    progress.

     81:    Logically Collective on SNESLineSearch

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

     91:    Notes:
     92:    Several different monitoring routines may be set by calling
     93:    SNESLineSearchMonitorSet() multiple times; all will be called in the
     94:    order in which they were set.

     96:    Fortran Notes:
     97:     Only a single monitor function can be set for each SNESLineSearch object

     99:    Level: intermediate

    101: .seealso: SNESGetLineSearch(), SNESLineSearchMonitorDefault(), SNESLineSearchMonitorCancel()
    102: @*/
    103: PetscErrorCode  SNESLineSearchMonitorSet(SNESLineSearch ls,PetscErrorCode (*f)(SNESLineSearch,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
    104: {
    106:   PetscInt       i;
    107:   PetscBool      identical;

    111:   for (i=0; i<ls->numbermonitors;i++) {
    112:     PetscMonitorCompare((PetscErrorCode (*)(void))f,mctx,monitordestroy,(PetscErrorCode (*)(void))ls->monitorftns[i],ls->monitorcontext[i],ls->monitordestroy[i],&identical);
    113:     if (identical) return(0);
    114:   }
    115:   if (ls->numbermonitors >= MAXSNESLSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
    116:   ls->monitorftns[ls->numbermonitors]          = f;
    117:   ls->monitordestroy[ls->numbermonitors]   = monitordestroy;
    118:   ls->monitorcontext[ls->numbermonitors++] = (void*)mctx;
    119:   return(0);
    120: }

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

    125:    Collective on SNESLineSearch

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

    131:    Level: intermediate

    133: .seealso: SNESGetLineSearch(), SNESMonitorSet(), SNESMonitorSolution()
    134: @*/
    135: PetscErrorCode  SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls,PetscViewerAndFormat *vf)
    136: {
    138:   PetscViewer    viewer = vf->viewer;
    139:   Vec            Y,W,G;

    142:   SNESLineSearchGetVecs(ls,NULL,NULL,&Y,&W,&G);
    143:   PetscViewerPushFormat(viewer,vf->format);
    144:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted update to solution \n");
    145:   VecView(Y,viewer);
    146:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted new solution \n");
    147:   VecView(W,viewer);
    148:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted updated function value\n");
    149:   VecView(G,viewer);
    150:   PetscViewerPopFormat(viewer);
    151:   return(0);
    152: }

    154: /*@
    155:    SNESLineSearchCreate - Creates the line search context.

    157:    Logically Collective on Comm

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

    162:    Output Parameters:
    163: .  outlinesearch - the new linesearch context

    165:    Level: developer

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

    171: .seealso: LineSearchDestroy(), SNESGetLineSearch()
    172: @*/

    174: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
    175: {
    177:   SNESLineSearch linesearch;

    181:   SNESInitializePackage();
    182:   *outlinesearch = NULL;

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

    186:   linesearch->vec_sol_new  = NULL;
    187:   linesearch->vec_func_new = NULL;
    188:   linesearch->vec_sol      = NULL;
    189:   linesearch->vec_func     = NULL;
    190:   linesearch->vec_update   = NULL;

    192:   linesearch->lambda       = 1.0;
    193:   linesearch->fnorm        = 1.0;
    194:   linesearch->ynorm        = 1.0;
    195:   linesearch->xnorm        = 1.0;
    196:   linesearch->result       = SNES_LINESEARCH_SUCCEEDED;
    197:   linesearch->norms        = PETSC_TRUE;
    198:   linesearch->keeplambda   = PETSC_FALSE;
    199:   linesearch->damping      = 1.0;
    200:   linesearch->maxstep      = 1e8;
    201:   linesearch->steptol      = 1e-12;
    202:   linesearch->rtol         = 1e-8;
    203:   linesearch->atol         = 1e-15;
    204:   linesearch->ltol         = 1e-8;
    205:   linesearch->precheckctx  = NULL;
    206:   linesearch->postcheckctx = NULL;
    207:   linesearch->max_its      = 1;
    208:   linesearch->setupcalled  = PETSC_FALSE;
    209:   linesearch->monitor      = NULL;
    210:   *outlinesearch           = linesearch;
    211:   return(0);
    212: }

    214: /*@
    215:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
    216:    any required vectors.

    218:    Collective on SNESLineSearch

    220:    Input Parameters:
    221: .  linesearch - The LineSearch instance.

    223:    Notes:
    224:    For most cases, this needn't be called by users or outside of SNESLineSearchApply().
    225:    The only current case where this is called outside of this is for the VI
    226:    solvers, which modify the solution and work vectors before the first call
    227:    of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be
    228:    allocated upfront.

    230:    Level: advanced

    232: .seealso: SNESGetLineSearch(), SNESLineSearchReset()
    233: @*/

    235: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
    236: {

    240:   if (!((PetscObject)linesearch)->type_name) {
    241:     SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);
    242:   }
    243:   if (!linesearch->setupcalled) {
    244:     if (!linesearch->vec_sol_new) {
    245:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
    246:     }
    247:     if (!linesearch->vec_func_new) {
    248:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
    249:     }
    250:     if (linesearch->ops->setup) {
    251:       (*linesearch->ops->setup)(linesearch);
    252:     }
    253:     if (!linesearch->ops->snesfunc) {SNESLineSearchSetFunction(linesearch,SNESComputeFunction);}
    254:     linesearch->lambda      = linesearch->damping;
    255:     linesearch->setupcalled = PETSC_TRUE;
    256:   }
    257:   return(0);
    258: }

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

    264:    Collective on SNESLineSearch

    266:    Input Parameters:
    267: .  linesearch - The LineSearch instance.

    269:    Notes:
    270:     Usually only called by SNESReset()

    272:    Level: developer

    274: .seealso: SNESGetLineSearch(), SNESLineSearchSetUp()
    275: @*/

    277: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
    278: {

    282:   if (linesearch->ops->reset) (*linesearch->ops->reset)(linesearch);

    284:   VecDestroy(&linesearch->vec_sol_new);
    285:   VecDestroy(&linesearch->vec_func_new);

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

    289:   linesearch->nwork       = 0;
    290:   linesearch->setupcalled = PETSC_FALSE;
    291:   return(0);
    292: }

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

    297:    Input Parameters:
    298: .  linesearch - the SNESLineSearch context
    299: +  func       - function evaluation routine

    301:    Level: developer

    303:    Notes:
    304:     This is used internally by PETSc and not called by users

    306: .seealso: SNESGetLineSearch(), SNESSetFunction()
    307: @*/
    308: PetscErrorCode  SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES,Vec,Vec))
    309: {
    312:   linesearch->ops->snesfunc = func;
    313:   return(0);
    314: }

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

    321:    Logically Collective on SNESLineSearch

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

    328:    Level: intermediate

    330: .seealso: SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
    331: @*/
    332: PetscErrorCode  SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void *ctx)
    333: {
    336:   if (func) linesearch->ops->precheck = func;
    337:   if (ctx) linesearch->precheckctx = ctx;
    338:   return(0);
    339: }

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

    344:    Input Parameters:
    345: .  linesearch - the SNESLineSearch context

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

    351:    Level: intermediate

    353: .seealso: SNESGetLineSearch(), SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck()
    354: @*/
    355: PetscErrorCode  SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void **ctx)
    356: {
    359:   if (func) *func = linesearch->ops->precheck;
    360:   if (ctx) *ctx = linesearch->precheckctx;
    361:   return(0);
    362: }

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

    368:    Logically Collective on SNESLineSearch

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

    375:    Level: intermediate

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

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

    391:    Input Parameters:
    392: .  linesearch - the SNESLineSearch context

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

    398:    Level: intermediate

    400: .seealso: SNESGetLineSearch(), SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchPostCheck(), SNESLineSearchSetPreCheck()
    401: @*/
    402: PetscErrorCode  SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void **ctx)
    403: {
    406:   if (func) *func = linesearch->ops->postcheck;
    407:   if (ctx) *ctx = linesearch->postcheckctx;
    408:   return(0);
    409: }

    411: /*@
    412:    SNESLineSearchPreCheck - Prepares the line search for being applied.

    414:    Logically Collective on SNESLineSearch

    416:    Input Parameters:
    417: +  linesearch - The linesearch instance.
    418: .  X - The current solution
    419: -  Y - The step direction

    421:    Output Parameters:
    422: .  changed - Indicator that the precheck routine has changed anything

    424:    Level: developer

    426: .seealso: SNESGetLineSearch(), SNESLineSearchPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck()
    427: @*/
    428: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed)
    429: {

    433:   *changed = PETSC_FALSE;
    434:   if (linesearch->ops->precheck) {
    435:     (*linesearch->ops->precheck)(linesearch, X, Y, changed, linesearch->precheckctx);
    437:   }
    438:   return(0);
    439: }

    441: /*@
    442:    SNESLineSearchPostCheck - Prepares the line search for being applied.

    444:    Logically Collective on SNESLineSearch

    446:    Input Parameters:
    447: +  linesearch - The linesearch context
    448: .  X - The last solution
    449: .  Y - The step direction
    450: -  W - The updated solution, W = X + lambda*Y for some lambda

    452:    Output Parameters:
    453: +  changed_Y - Indicator if the direction Y has been changed.
    454: -  changed_W - Indicator if the new candidate solution W has been changed.

    456:    Level: developer

    458: .seealso: SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchSetPrecheck(), SNESLineSearchGetPrecheck()
    459: @*/
    460: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W)
    461: {

    465:   *changed_Y = PETSC_FALSE;
    466:   *changed_W = PETSC_FALSE;
    467:   if (linesearch->ops->postcheck) {
    468:     (*linesearch->ops->postcheck)(linesearch,X,Y,W,changed_Y,changed_W,linesearch->postcheckctx);
    471:   }
    472:   return(0);
    473: }

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

    478:    Logically Collective on SNESLineSearch

    480:    Input Arguments:
    481: +  linesearch - linesearch context
    482: .  X - base state for this step
    483: .  Y - initial correction
    484: -  ctx - context for this function

    486:    Output Arguments:
    487: +  Y - correction, possibly modified
    488: -  changed - flag indicating that Y was modified

    490:    Options Database Key:
    491: +  -snes_linesearch_precheck_picard - activate this routine
    492: -  -snes_linesearch_precheck_picard_angle - angle

    494:    Level: advanced

    496:    Notes:
    497:    This function should be passed to SNESLineSearchSetPreCheck()

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

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

    506: .seealso: SNESGetLineSearch(), SNESLineSearchSetPreCheck()
    507: @*/
    508: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed,void *ctx)
    509: {
    511:   PetscReal      angle = *(PetscReal*)linesearch->precheckctx;
    512:   Vec            Ylast;
    513:   PetscScalar    dot;
    514:   PetscInt       iter;
    515:   PetscReal      ynorm,ylastnorm,theta,angle_radians;
    516:   SNES           snes;

    519:   SNESLineSearchGetSNES(linesearch, &snes);
    520:   PetscObjectQuery((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject*)&Ylast);
    521:   if (!Ylast) {
    522:     VecDuplicate(Y,&Ylast);
    523:     PetscObjectCompose((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject)Ylast);
    524:     PetscObjectDereference((PetscObject)Ylast);
    525:   }
    526:   SNESGetIterationNumber(snes,&iter);
    527:   if (iter < 2) {
    528:     VecCopy(Y,Ylast);
    529:     *changed = PETSC_FALSE;
    530:     return(0);
    531:   }

    533:   VecDot(Y,Ylast,&dot);
    534:   VecNorm(Y,NORM_2,&ynorm);
    535:   VecNorm(Ylast,NORM_2,&ylastnorm);
    536:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
    537:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm),-1.0,1.0));
    538:   angle_radians = angle * PETSC_PI / 180.;
    539:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
    540:     /* Modify the step Y */
    541:     PetscReal alpha,ydiffnorm;
    542:     VecAXPY(Ylast,-1.0,Y);
    543:     VecNorm(Ylast,NORM_2,&ydiffnorm);
    544:     alpha = (ydiffnorm > .001*ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
    545:     VecCopy(Y,Ylast);
    546:     VecScale(Y,alpha);
    547:     PetscInfo3(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);
    548:     *changed = PETSC_TRUE;
    549:   } else {
    550:     PetscInfo2(snes,"Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n",(double)(theta*180./PETSC_PI),(double)angle);
    551:     VecCopy(Y,Ylast);
    552:     *changed = PETSC_FALSE;
    553:   }
    554:   return(0);
    555: }

    557: /*@
    558:    SNESLineSearchApply - Computes the line-search update.

    560:    Collective on SNESLineSearch

    562:    Input Parameters:
    563: +  linesearch - The linesearch context
    564: .  X - The current solution
    565: .  F - The current function
    566: .  fnorm - The current norm
    567: -  Y - The search direction

    569:    Output Parameters:
    570: +  X - The new solution
    571: .  F - The new function
    572: -  fnorm - The new function norm

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

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

    590:    Level: Intermediate

    592: .seealso: SNESGetLineSearch(), SNESLineSearchCreate(), SNESLineSearchPreCheck(), SNESLineSearchPostCheck(), SNESSolve(), SNESComputeFunction(), SNESLineSearchSetComputeNorms(),
    593:           SNESLineSearchType, SNESLineSearchSetType()
    594: @*/
    595: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y)
    596: {

    605:   linesearch->result = SNES_LINESEARCH_SUCCEEDED;

    607:   linesearch->vec_sol    = X;
    608:   linesearch->vec_update = Y;
    609:   linesearch->vec_func   = F;

    611:   SNESLineSearchSetUp(linesearch);

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

    615:   if (fnorm) linesearch->fnorm = *fnorm;
    616:   else {
    617:     VecNorm(F, NORM_2, &linesearch->fnorm);
    618:   }

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

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

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

    626:   if (fnorm) *fnorm = linesearch->fnorm;
    627:   return(0);
    628: }

    630: /*@
    631:    SNESLineSearchDestroy - Destroys the line search instance.

    633:    Collective on SNESLineSearch

    635:    Input Parameters:
    636: .  linesearch - The linesearch context

    638:    Level: developer

    640: .seealso: SNESGetLineSearch(), SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy()
    641: @*/
    642: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch)
    643: {

    647:   if (!*linesearch) return(0);
    649:   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = NULL; return(0);}
    650:   PetscObjectSAWsViewOff((PetscObject)*linesearch);
    651:   SNESLineSearchReset(*linesearch);
    652:   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
    653:   PetscViewerDestroy(&(*linesearch)->monitor);
    654:   SNESLineSearchMonitorCancel((*linesearch));
    655:   PetscHeaderDestroy(linesearch);
    656:   return(0);
    657: }

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

    662:    Input Parameters:
    663: +  linesearch - the linesearch object
    664: -  viewer - an ASCII PetscViewer or NULL to turn off monitor

    666:    Logically Collective on SNESLineSearch

    668:    Options Database:
    669: .   -snes_linesearch_monitor [:filename] - enables the monitor

    671:    Level: intermediate

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

    677: .seealso: SNESGetLineSearch(), SNESLineSearchGetDefaultMonitor(), PetscViewer, SNESLineSearchSetMonitor()
    678: @*/
    679: PetscErrorCode  SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
    680: {

    684:   if (viewer) {PetscObjectReference((PetscObject)viewer);}
    685:   PetscViewerDestroy(&linesearch->monitor);
    686:   linesearch->monitor = viewer;
    687:   return(0);
    688: }

    690: /*@
    691:    SNESLineSearchGetDefaultMonitor - Gets the PetscViewer instance for the line search monitor.

    693:    Input Parameter:
    694: .  linesearch - linesearch context

    696:    Output Parameter:
    697: .  monitor - monitor context

    699:    Logically Collective on SNES

    701:    Options Database Keys:
    702: .   -snes_linesearch_monitor - enables the monitor

    704:    Level: intermediate

    706: .seealso: SNESGetLineSearch(), SNESLineSearchSetDefaultMonitor(), PetscViewer
    707: @*/
    708: PetscErrorCode  SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
    709: {
    712:   *monitor = linesearch->monitor;
    713:   return(0);
    714: }

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

    719:    Collective on SNESLineSearch

    721:    Input Parameters:
    722: +  ls - LineSearch object you wish to monitor
    723: .  name - the monitor type one is seeking
    724: .  help - message indicating what monitoring is done
    725: .  manual - manual page for the monitor
    726: .  monitor - the monitor function
    727: -  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

    729:    Level: developer

    731: .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
    732:           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
    733:           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
    734:           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
    735:           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
    736:           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
    737:           PetscOptionsFList(), PetscOptionsEList()
    738: @*/
    739: PetscErrorCode  SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(SNESLineSearch,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(SNESLineSearch,PetscViewerAndFormat*))
    740: {
    741:   PetscErrorCode    ierr;
    742:   PetscViewer       viewer;
    743:   PetscViewerFormat format;
    744:   PetscBool         flg;

    747:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls),((PetscObject) ls)->options,((PetscObject)ls)->prefix,name,&viewer,&format,&flg);
    748:   if (flg) {
    749:     PetscViewerAndFormat *vf;
    750:     PetscViewerAndFormatCreate(viewer,format,&vf);
    751:     PetscObjectDereference((PetscObject)viewer);
    752:     if (monitorsetup) {
    753:       (*monitorsetup)(ls,vf);
    754:     }
    755:     SNESLineSearchMonitorSet(ls,(PetscErrorCode (*)(SNESLineSearch,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);
    756:   }
    757:   return(0);
    758: }

    760: /*@
    761:    SNESLineSearchSetFromOptions - Sets options for the line search

    763:    Input Parameters:
    764: .  linesearch - linesearch context

    766:    Options Database Keys:
    767: + -snes_linesearch_type <type> - basic, bt, l2, cp, nleqerr, shell
    768: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
    769: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch typem (SNESLineSearchSetComputeNorms())
    770: . -snes_linesearch_minlambda - The minimum step length
    771: . -snes_linesearch_maxstep - The maximum step size
    772: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
    773: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
    774: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
    775: . -snes_linesearch_max_it - The number of iterations for iterative line searches
    776: . -snes_linesearch_monitor [:filename] - Print progress of line searches
    777: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
    778: . -snes_linesearch_damping - The linesearch damping parameter
    779: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
    780: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
    781: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method

    783:    Logically Collective on SNESLineSearch

    785:    Level: intermediate

    787: .seealso: SNESLineSearchCreate(), SNESLineSearchSetOrder(), SNESLineSearchSetType(), SNESLineSearchSetTolerances(), SNESLineSearchSetDamping(), SNESLineSearchPreCheckPicard(),
    788:           SNESLineSearchType, SNESLineSearchSetComputeNorms()
    789: @*/
    790: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
    791: {
    792:   PetscErrorCode    ierr;
    793:   const char        *deft = SNESLINESEARCHBASIC;
    794:   char              type[256];
    795:   PetscBool         flg, set;
    796:   PetscViewer       viewer;

    799:   SNESLineSearchRegisterAll();

    801:   PetscObjectOptionsBegin((PetscObject)linesearch);
    802:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
    803:   PetscOptionsFList("-snes_linesearch_type","Linesearch type","SNESLineSearchSetType",SNESLineSearchList,deft,type,256,&flg);
    804:   if (flg) {
    805:     SNESLineSearchSetType(linesearch,type);
    806:   } else if (!((PetscObject)linesearch)->type_name) {
    807:     SNESLineSearchSetType(linesearch,deft);
    808:   }

    810:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch),((PetscObject) linesearch)->options,((PetscObject)linesearch)->prefix,"-snes_linesearch_monitor",&viewer,NULL,&set);
    811:   if (set) {
    812:     SNESLineSearchSetDefaultMonitor(linesearch,viewer);
    813:     PetscViewerDestroy(&viewer);
    814:   }
    815:   SNESLineSearchMonitorSetFromOptions(linesearch,"-snes_linesearch_monitor_solution_update","View correction at each iteration","SNESLineSearchMonitorSolutionUpdate",SNESLineSearchMonitorSolutionUpdate,NULL);

    817:   /* tolerances */
    818:   PetscOptionsReal("-snes_linesearch_minlambda","Minimum step length","SNESLineSearchSetTolerances",linesearch->steptol,&linesearch->steptol,NULL);
    819:   PetscOptionsReal("-snes_linesearch_maxstep","Maximum step size","SNESLineSearchSetTolerances",linesearch->maxstep,&linesearch->maxstep,NULL);
    820:   PetscOptionsReal("-snes_linesearch_rtol","Relative tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->rtol,&linesearch->rtol,NULL);
    821:   PetscOptionsReal("-snes_linesearch_atol","Absolute tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->atol,&linesearch->atol,NULL);
    822:   PetscOptionsReal("-snes_linesearch_ltol","Change in lambda tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->ltol,&linesearch->ltol,NULL);
    823:   PetscOptionsInt("-snes_linesearch_max_it","Maximum iterations for iterative line searches","SNESLineSearchSetTolerances",linesearch->max_its,&linesearch->max_its,NULL);

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

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

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

    836:       PetscOptionsReal("-snes_linesearch_precheck_picard_angle","Maximum angle at which to activate the correction",
    837:                               "none",linesearch->precheck_picard_angle,&linesearch->precheck_picard_angle,NULL);
    838:       SNESLineSearchSetPreCheck(linesearch,SNESLineSearchPreCheckPicard,&linesearch->precheck_picard_angle);
    839:     } else {
    840:       SNESLineSearchSetPreCheck(linesearch,NULL,NULL);
    841:     }
    842:   }
    843:   PetscOptionsInt("-snes_linesearch_order","Order of approximation used in the line search","SNESLineSearchSetOrder",linesearch->order,&linesearch->order,NULL);
    844:   PetscOptionsBool("-snes_linesearch_norms","Compute final norms in line search","SNESLineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,NULL);

    846:   if (linesearch->ops->setfromoptions) {
    847:     (*linesearch->ops->setfromoptions)(PetscOptionsObject,linesearch);
    848:   }

    850:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)linesearch);
    851:   PetscOptionsEnd();
    852:   return(0);
    853: }

    855: /*@
    856:    SNESLineSearchView - Prints useful information about the line search

    858:    Input Parameters:
    859: .  linesearch - linesearch context

    861:    Logically Collective on SNESLineSearch

    863:    Level: intermediate

    865: .seealso: SNESLineSearchCreate()
    866: @*/
    867: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
    868: {
    870:   PetscBool      iascii;

    874:   if (!viewer) {
    875:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch),&viewer);
    876:   }

    880:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    881:   if (iascii) {
    882:     PetscObjectPrintClassNamePrefixType((PetscObject)linesearch,viewer);
    883:     if (linesearch->ops->view) {
    884:       PetscViewerASCIIPushTab(viewer);
    885:       (*linesearch->ops->view)(linesearch,viewer);
    886:       PetscViewerASCIIPopTab(viewer);
    887:     }
    888:     PetscViewerASCIIPrintf(viewer,"  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol);
    889:     PetscViewerASCIIPrintf(viewer,"  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol);
    890:     PetscViewerASCIIPrintf(viewer,"  maximum iterations=%D\n", linesearch->max_its);
    891:     if (linesearch->ops->precheck) {
    892:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
    893:         PetscViewerASCIIPrintf(viewer,"  using precheck step to speed up Picard convergence\n", linesearch->max_its);
    894:       } else {
    895:         PetscViewerASCIIPrintf(viewer,"  using user-defined precheck step\n", linesearch->max_its);
    896:       }
    897:     }
    898:     if (linesearch->ops->postcheck) {
    899:       PetscViewerASCIIPrintf(viewer,"  using user-defined postcheck step\n", linesearch->max_its);
    900:     }
    901:   }
    902:   return(0);
    903: }

    905: /*@C
    906:    SNESLineSearchGetType - Gets the linesearch type

    908:    Logically Collective on SNESLineSearch

    910:    Input Parameters:
    911: .  linesearch - linesearch context

    913:    Output Parameters:
    914: -  type - The type of line search, or NULL if not set

    916:    Level: intermediate

    918: .seealso: SNESLineSearchCreate(), SNESLineSearchType, SNESLineSearchSetFromOptions(), SNESLineSearchSetType()
    919: @*/
    920: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
    921: {
    925:   *type = ((PetscObject)linesearch)->type_name;
    926:   return(0);
    927: }

    929: /*@C
    930:    SNESLineSearchSetType - Sets the linesearch type

    932:    Logically Collective on SNESLineSearch

    934:    Input Parameters:
    935: +  linesearch - linesearch context
    936: -  type - The type of line search to be used

    938:    Available Types:
    939: +  SNESLINESEARCHBASIC - Simple damping line search, defaults to using the full Newton step
    940: .  SNESLINESEARCHBT - Backtracking line search over the L2 norm of the function
    941: .  SNESLINESEARCHL2 - Secant line search over the L2 norm of the function
    942: .  SNESLINESEARCHCP - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
    943: .  SNESLINESEARCHNLEQERR - Affine-covariant error-oriented linesearch
    944: -  SNESLINESEARCHSHELL - User provided SNESLineSearch implementation

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

    949:    Level: intermediate

    951: .seealso: SNESLineSearchCreate(), SNESLineSearchType, SNESLineSearchSetFromOptions(), SNESLineSearchGetType()
    952: @*/
    953: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
    954: {
    955:   PetscErrorCode ierr,(*r)(SNESLineSearch);
    956:   PetscBool      match;

    962:   PetscObjectTypeCompare((PetscObject)linesearch,type,&match);
    963:   if (match) return(0);

    965:   PetscFunctionListFind(SNESLineSearchList,type,&r);
    966:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type);
    967:   /* Destroy the previous private linesearch context */
    968:   if (linesearch->ops->destroy) {
    969:     (*(linesearch)->ops->destroy)(linesearch);
    970:     linesearch->ops->destroy = NULL;
    971:   }
    972:   /* Reinitialize function pointers in SNESLineSearchOps structure */
    973:   linesearch->ops->apply          = NULL;
    974:   linesearch->ops->view           = NULL;
    975:   linesearch->ops->setfromoptions = NULL;
    976:   linesearch->ops->destroy        = NULL;

    978:   PetscObjectChangeTypeName((PetscObject)linesearch,type);
    979:   (*r)(linesearch);
    980:   return(0);
    981: }

    983: /*@
    984:    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.

    986:    Input Parameters:
    987: +  linesearch - linesearch context
    988: -  snes - The snes instance

    990:    Level: developer

    992:    Notes:
    993:    This happens automatically when the line search is obtained/created with
    994:    SNESGetLineSearch().  This routine is therefore mainly called within SNES
    995:    implementations.

    997:    Level: developer

    999: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    1000: @*/
    1001: PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
    1002: {
    1006:   linesearch->snes = snes;
    1007:   return(0);
    1008: }

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

    1016:    Input Parameters:
    1017: .  linesearch - linesearch context

    1019:    Output Parameters:
    1020: .  snes - The snes instance

    1022:    Level: developer

    1024: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    1025: @*/
    1026: PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
    1027: {
    1031:   *snes = linesearch->snes;
    1032:   return(0);
    1033: }

    1035: /*@
    1036:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

    1038:    Input Parameters:
    1039: .  linesearch - linesearch context

    1041:    Output Parameters:
    1042: .  lambda - The last steplength computed during SNESLineSearchApply()

    1044:    Level: advanced

    1046:    Notes:
    1047:    This is useful in methods where the solver is ill-scaled and
    1048:    requires some adaptive notion of the difference in scale between the
    1049:    solution and the function.  For instance, SNESQN may be scaled by the
    1050:    line search lambda using the argument -snes_qn_scaling ls.

    1052: .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply()
    1053: @*/
    1054: PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
    1055: {
    1059:   *lambda = linesearch->lambda;
    1060:   return(0);
    1061: }

    1063: /*@
    1064:    SNESLineSearchSetLambda - Sets the linesearch steplength.

    1066:    Input Parameters:
    1067: +  linesearch - linesearch context
    1068: -  lambda - The last steplength.

    1070:    Notes:
    1071:    This routine is typically used within implementations of SNESLineSearchApply()
    1072:    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
    1073:    added in order to facilitate Quasi-Newton methods that use the previous steplength
    1074:    as an inner scaling parameter.

    1076:    Level: advanced

    1078: .seealso: SNESLineSearchGetLambda()
    1079: @*/
    1080: PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
    1081: {
    1084:   linesearch->lambda = lambda;
    1085:   return(0);
    1086: }

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

    1094:    Input Parameters:
    1095: .  linesearch - linesearch context

    1097:    Output Parameters:
    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:    Level: intermediate

    1107:    Notes:
    1108:    Different line searches may implement these parameters slightly differently as
    1109:    the type requires.

    1111: .seealso: SNESLineSearchSetTolerances()
    1112: @*/
    1113: PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
    1114: {
    1117:   if (steptol) {
    1119:     *steptol = linesearch->steptol;
    1120:   }
    1121:   if (maxstep) {
    1123:     *maxstep = linesearch->maxstep;
    1124:   }
    1125:   if (rtol) {
    1127:     *rtol = linesearch->rtol;
    1128:   }
    1129:   if (atol) {
    1131:     *atol = linesearch->atol;
    1132:   }
    1133:   if (ltol) {
    1135:     *ltol = linesearch->ltol;
    1136:   }
    1137:   if (max_its) {
    1139:     *max_its = linesearch->max_its;
    1140:   }
    1141:   return(0);
    1142: }

    1144: /*@
    1145:    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
    1146:    tolerances for the relative and absolute change in the function norm, the change
    1147:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
    1148:    and the maximum number of iterations the line search procedure may take.

    1150:    Input Parameters:
    1151: +  linesearch - linesearch context
    1152: .  steptol - The minimum steplength
    1153: .  maxstep - The maximum steplength
    1154: .  rtol    - The relative tolerance for iterative line searches
    1155: .  atol    - The absolute tolerance for iterative line searches
    1156: .  ltol    - The change in lambda tolerance for iterative line searches
    1157: -  max_it  - The maximum number of iterations of the line search

    1159:    Notes:
    1160:    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
    1161:    place of an argument.

    1163:    Level: intermediate

    1165: .seealso: SNESLineSearchGetTolerances()
    1166: @*/
    1167: PetscErrorCode  SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
    1168: {

    1178:   if (steptol!= PETSC_DEFAULT) {
    1179:     if (steptol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Minimum step length %14.12e must be non-negative",(double)steptol);
    1180:     linesearch->steptol = steptol;
    1181:   }

    1183:   if (maxstep!= PETSC_DEFAULT) {
    1184:     if (maxstep < 0.0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Maximum step length %14.12e must be non-negative",(double)maxstep);
    1185:     linesearch->maxstep = maxstep;
    1186:   }

    1188:   if (rtol != PETSC_DEFAULT) {
    1189:     if (rtol < 0.0 || 1.0 <= rtol) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Relative tolerance %14.12e must be non-negative and less than 1.0",(double)rtol);
    1190:     linesearch->rtol = rtol;
    1191:   }

    1193:   if (atol != PETSC_DEFAULT) {
    1194:     if (atol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %14.12e must be non-negative",(double)atol);
    1195:     linesearch->atol = atol;
    1196:   }

    1198:   if (ltol != PETSC_DEFAULT) {
    1199:     if (ltol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Lambda tolerance %14.12e must be non-negative",(double)ltol);
    1200:     linesearch->ltol = ltol;
    1201:   }

    1203:   if (max_its != PETSC_DEFAULT) {
    1204:     if (max_its < 0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",max_its);
    1205:     linesearch->max_its = max_its;
    1206:   }
    1207:   return(0);
    1208: }

    1210: /*@
    1211:    SNESLineSearchGetDamping - Gets the line search damping parameter.

    1213:    Input Parameters:
    1214: .  linesearch - linesearch context

    1216:    Output Parameters:
    1217: .  damping - The damping parameter

    1219:    Level: advanced

    1221: .seealso: SNESLineSearchGetStepTolerance(), SNESQN
    1222: @*/

    1224: PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
    1225: {
    1229:   *damping = linesearch->damping;
    1230:   return(0);
    1231: }

    1233: /*@
    1234:    SNESLineSearchSetDamping - Sets the line search damping parameter.

    1236:    Input Parameters:
    1237: +  linesearch - linesearch context
    1238: -  damping - The damping parameter

    1240:    Options Database:
    1241: .   -snes_linesearch_damping
    1242:    Level: intermediate

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

    1251: .seealso: SNESLineSearchGetDamping()
    1252: @*/
    1253: PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
    1254: {
    1257:   linesearch->damping = damping;
    1258:   return(0);
    1259: }

    1261: /*@
    1262:    SNESLineSearchGetOrder - Gets the line search approximation order.

    1264:    Input Parameters:
    1265: .  linesearch - linesearch context

    1267:    Output Parameters:
    1268: .  order - The order

    1270:    Possible Values for order:
    1271: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1272: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1273: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1275:    Level: intermediate

    1277: .seealso: SNESLineSearchSetOrder()
    1278: @*/

    1280: PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
    1281: {
    1285:   *order = linesearch->order;
    1286:   return(0);
    1287: }

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

    1292:    Input Parameters:
    1293: +  linesearch - linesearch context
    1294: -  order - The damping parameter

    1296:    Level: intermediate

    1298:    Possible Values for order:
    1299: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1300: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1301: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1303:    Notes:
    1304:    Variable orders are supported by the following line searches:
    1305: +  bt - cubic and quadratic
    1306: -  cp - linear and quadratic

    1308: .seealso: SNESLineSearchGetOrder(), SNESLineSearchSetDamping()
    1309: @*/
    1310: PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
    1311: {
    1314:   linesearch->order = order;
    1315:   return(0);
    1316: }

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

    1321:    Input Parameters:
    1322: .  linesearch - linesearch context

    1324:    Output Parameters:
    1325: +  xnorm - The norm of the current solution
    1326: .  fnorm - The norm of the current function
    1327: -  ynorm - The norm of the current update

    1329:    Notes:
    1330:    This function is mainly called from SNES implementations.

    1332:    Level: developer

    1334: .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs()
    1335: @*/
    1336: PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
    1337: {
    1340:   if (xnorm) *xnorm = linesearch->xnorm;
    1341:   if (fnorm) *fnorm = linesearch->fnorm;
    1342:   if (ynorm) *ynorm = linesearch->ynorm;
    1343:   return(0);
    1344: }

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

    1349:    Input Parameters:
    1350: +  linesearch - linesearch context
    1351: .  xnorm - The norm of the current solution
    1352: .  fnorm - The norm of the current function
    1353: -  ynorm - The norm of the current update

    1355:    Level: advanced

    1357: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1358: @*/
    1359: PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
    1360: {
    1363:   linesearch->xnorm = xnorm;
    1364:   linesearch->fnorm = fnorm;
    1365:   linesearch->ynorm = ynorm;
    1366:   return(0);
    1367: }

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

    1372:    Input Parameters:
    1373: .  linesearch - linesearch context

    1375:    Options Database Keys:
    1376: .   -snes_linesearch_norms - turn norm computation on or off

    1378:    Level: intermediate

    1380: .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms()
    1381: @*/
    1382: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
    1383: {
    1385:   SNES           snes;

    1388:   if (linesearch->norms) {
    1389:     if (linesearch->ops->vinorm) {
    1390:       SNESLineSearchGetSNES(linesearch, &snes);
    1391:       VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
    1392:       VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1393:       (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
    1394:     } else {
    1395:       VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm);
    1396:       VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm);
    1397:       VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1398:       VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm);
    1399:       VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm);
    1400:       VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm);
    1401:     }
    1402:   }
    1403:   return(0);
    1404: }

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

    1409:    Input Parameters:
    1410: +  linesearch  - linesearch context
    1411: -  flg  - indicates whether or not to compute norms

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

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

    1419:    Level: intermediate

    1421: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC
    1422: @*/
    1423: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
    1424: {
    1426:   linesearch->norms = flg;
    1427:   return(0);
    1428: }

    1430: /*@
    1431:    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context

    1433:    Input Parameters:
    1434: .  linesearch - linesearch context

    1436:    Output Parameters:
    1437: +  X - Solution vector
    1438: .  F - Function vector
    1439: .  Y - Search direction vector
    1440: .  W - Solution work vector
    1441: -  G - Function work vector

    1443:    Notes:
    1444:    At the beginning of a line search application, X should contain a
    1445:    solution and the vector F the function computed at X.  At the end of the
    1446:    line search application, X should contain the new solution, and F the
    1447:    function evaluated at the new solution.

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

    1451:    Level: advanced

    1453: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1454: @*/
    1455: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
    1456: {
    1459:   if (X) {
    1461:     *X = linesearch->vec_sol;
    1462:   }
    1463:   if (F) {
    1465:     *F = linesearch->vec_func;
    1466:   }
    1467:   if (Y) {
    1469:     *Y = linesearch->vec_update;
    1470:   }
    1471:   if (W) {
    1473:     *W = linesearch->vec_sol_new;
    1474:   }
    1475:   if (G) {
    1477:     *G = linesearch->vec_func_new;
    1478:   }
    1479:   return(0);
    1480: }

    1482: /*@
    1483:    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context

    1485:    Input Parameters:
    1486: +  linesearch - linesearch context
    1487: .  X - Solution vector
    1488: .  F - Function vector
    1489: .  Y - Search direction vector
    1490: .  W - Solution work vector
    1491: -  G - Function work vector

    1493:    Level: advanced

    1495: .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs()
    1496: @*/
    1497: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
    1498: {
    1501:   if (X) {
    1503:     linesearch->vec_sol = X;
    1504:   }
    1505:   if (F) {
    1507:     linesearch->vec_func = F;
    1508:   }
    1509:   if (Y) {
    1511:     linesearch->vec_update = Y;
    1512:   }
    1513:   if (W) {
    1515:     linesearch->vec_sol_new = W;
    1516:   }
    1517:   if (G) {
    1519:     linesearch->vec_func_new = G;
    1520:   }
    1521:   return(0);
    1522: }

    1524: /*@C
    1525:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
    1526:    SNES options in the database.

    1528:    Logically Collective on SNESLineSearch

    1530:    Input Parameters:
    1531: +  snes - the SNES context
    1532: -  prefix - the prefix to prepend to all option names

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

    1538:    Level: advanced

    1540: .seealso: SNESGetOptionsPrefix()
    1541: @*/
    1542: PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
    1543: {

    1548:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);
    1549:   return(0);
    1550: }

    1552: /*@C
    1553:    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
    1554:    SNESLineSearch options in the database.

    1556:    Not Collective

    1558:    Input Parameter:
    1559: .  linesearch - the SNESLineSearch context

    1561:    Output Parameter:
    1562: .  prefix - pointer to the prefix string used

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

    1568:    Level: advanced

    1570: .seealso: SNESAppendOptionsPrefix()
    1571: @*/
    1572: PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
    1573: {

    1578:   PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);
    1579:   return(0);
    1580: }

    1582: /*@C
    1583:    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.

    1585:    Input Parameter:
    1586: +  linesearch - the SNESLineSearch context
    1587: -  nwork - the number of work vectors

    1589:    Level: developer

    1591: .seealso: SNESSetWorkVecs()
    1592: @*/
    1593: PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
    1594: {

    1598:   if (linesearch->vec_sol) {
    1599:     VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
    1600:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
    1601:   return(0);
    1602: }

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

    1607:    Input Parameters:
    1608: .  linesearch - linesearch context

    1610:    Output Parameters:
    1611: .  result - The success or failure status

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

    1617:    Level: intermediate

    1619: .seealso: SNESLineSearchSetReason(), SNESLineSearchReason
    1620: @*/
    1621: PetscErrorCode  SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
    1622: {
    1626:   *result = linesearch->result;
    1627:   return(0);
    1628: }

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

    1633:    Input Parameters:
    1634: +  linesearch - linesearch context
    1635: -  result - The success or failure status

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

    1641:    Level: developer

    1643: .seealso: SNESLineSearchGetSResult()
    1644: @*/
    1645: PetscErrorCode  SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
    1646: {
    1649:   linesearch->result = result;
    1650:   return(0);
    1651: }

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

    1656:    Input Parameters:
    1657: +  snes - nonlinear context obtained from SNESCreate()
    1658: .  projectfunc - function for projecting the function to the bounds
    1659: -  normfunc - function for computing the norm of an active set

    1661:    Logically Collective on SNES

    1663:    Calling sequence of projectfunc:
    1664: .vb
    1665:    projectfunc (SNES snes, Vec X)
    1666: .ve

    1668:     Input parameters for projectfunc:
    1669: +   snes - nonlinear context
    1670: -   X - current solution

    1672:     Output parameters for projectfunc:
    1673: .   X - Projected solution

    1675:    Calling sequence of normfunc:
    1676: .vb
    1677:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
    1678: .ve

    1680:     Input parameters for normfunc:
    1681: +   snes - nonlinear context
    1682: .   X - current solution
    1683: -   F - current residual

    1685:     Output parameters for normfunc:
    1686: .   fnorm - VI-specific norm of the function

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

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

    1694:     Level: developer

    1696: .seealso: SNESLineSearchGetVIFunctions(), SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck()
    1697: @*/
    1698: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
    1699: {
    1702:   if (projectfunc) linesearch->ops->viproject = projectfunc;
    1703:   if (normfunc) linesearch->ops->vinorm = normfunc;
    1704:   return(0);
    1705: }

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

    1710:    Input Parameters:
    1711: .  linesearch - the line search context, obtain with SNESGetLineSearch()

    1713:    Output Parameters:
    1714: +  projectfunc - function for projecting the function to the bounds
    1715: -  normfunc - function for computing the norm of an active set

    1717:    Logically Collective on SNES

    1719:     Level: developer

    1721: .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
    1722: @*/
    1723: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
    1724: {
    1726:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
    1727:   if (normfunc) *normfunc = linesearch->ops->vinorm;
    1728:   return(0);
    1729: }

    1731: /*@C
    1732:   SNESLineSearchRegister - See SNESLineSearchRegister()

    1734:   Level: advanced
    1735: @*/
    1736: PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
    1737: {

    1741:   SNESInitializePackage();
    1742:   PetscFunctionListAdd(&SNESLineSearchList,sname,function);
    1743:   return(0);
    1744: }