Date: 2022-03-04T17:39:30+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: {
     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: }

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

    263:    Collective on SNESLineSearch

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

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

    271:    Level: developer

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

    276: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
    277: {

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

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

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

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

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

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

    300:    Level: developer

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

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

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

    320:    Logically Collective on SNESLineSearch

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

    327:    Level: intermediate

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

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

    343:    Input Parameter:
    344: .  linesearch - the SNESLineSearch context

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

    350:    Level: intermediate

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

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

    367:    Logically Collective on SNESLineSearch

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

    374:    Level: intermediate

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

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

    390:    Input Parameter:
    391: .  linesearch - the SNESLineSearch context

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

    397:    Level: intermediate

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

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

    413:    Logically Collective on SNESLineSearch

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

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

    423:    Level: developer

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

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

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

    443:    Logically Collective on SNESLineSearch

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

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

    455:    Level: developer

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

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

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

    477:    Logically Collective on SNESLineSearch

    479:    Input Parameters:
    480: +  linesearch - linesearch context
    481: .  X - base state for this step
    482: -  ctx - context for this function

    484:    Input/Output Parameter:
    485: .  Y - correction, possibly modified

    487:    Output Parameter:
    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: -  Y - The search direction

    566:    Input/Output Parameters:
    567: +  X - The current solution, on output the new solution
    568: .  F - The current function, on output the new function
    569: -  fnorm - The current norm, on output the new function norm

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

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

    587:    Level: Intermediate

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

    602:   linesearch->result = SNES_LINESEARCH_SUCCEEDED;

    604:   linesearch->vec_sol    = X;
    605:   linesearch->vec_update = Y;
    606:   linesearch->vec_func   = F;

    608:   SNESLineSearchSetUp(linesearch);

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

    612:   if (fnorm) linesearch->fnorm = *fnorm;
    613:   else {
    614:     VecNorm(F, NORM_2, &linesearch->fnorm);
    615:   }

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

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

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

    623:   if (fnorm) *fnorm = linesearch->fnorm;
    624:   return(0);
    625: }

    627: /*@
    628:    SNESLineSearchDestroy - Destroys the line search instance.

    630:    Collective on SNESLineSearch

    632:    Input Parameters:
    633: .  linesearch - The linesearch context

    635:    Level: developer

    637: .seealso: SNESGetLineSearch(), SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy()
    638: @*/
    639: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch)
    640: {

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

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

    659:    Input Parameters:
    660: +  linesearch - the linesearch object
    661: -  viewer - an ASCII PetscViewer or NULL to turn off monitor

    663:    Logically Collective on SNESLineSearch

    665:    Options Database:
    666: .   -snes_linesearch_monitor [:filename] - enables the monitor

    668:    Level: intermediate

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

    674: .seealso: SNESGetLineSearch(), SNESLineSearchGetDefaultMonitor(), PetscViewer, SNESLineSearchSetMonitor()
    675: @*/
    676: PetscErrorCode  SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
    677: {

    681:   if (viewer) {PetscObjectReference((PetscObject)viewer);}
    682:   PetscViewerDestroy(&linesearch->monitor);
    683:   linesearch->monitor = viewer;
    684:   return(0);
    685: }

    687: /*@
    688:    SNESLineSearchGetDefaultMonitor - Gets the PetscViewer instance for the line search monitor.

    690:    Input Parameter:
    691: .  linesearch - linesearch context

    693:    Output Parameter:
    694: .  monitor - monitor context

    696:    Logically Collective on SNES

    698:    Options Database Keys:
    699: .   -snes_linesearch_monitor - enables the monitor

    701:    Level: intermediate

    703: .seealso: SNESGetLineSearch(), SNESLineSearchSetDefaultMonitor(), PetscViewer
    704: @*/
    705: PetscErrorCode  SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
    706: {
    709:   *monitor = linesearch->monitor;
    710:   return(0);
    711: }

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

    716:    Collective on SNESLineSearch

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

    726:    Level: developer

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

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

    757: /*@
    758:    SNESLineSearchSetFromOptions - Sets options for the line search

    760:    Input Parameter:
    761: .  linesearch - linesearch context

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

    780:    Logically Collective on SNESLineSearch

    782:    Level: intermediate

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

    796:   SNESLineSearchRegisterAll();

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

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

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

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

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

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

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

    843:   if (linesearch->ops->setfromoptions) {
    844:     (*linesearch->ops->setfromoptions)(PetscOptionsObject,linesearch);
    845:   }

    847:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)linesearch);
    848:   PetscOptionsEnd();
    849:   return(0);
    850: }

    852: /*@
    853:    SNESLineSearchView - Prints useful information about the line search

    855:    Input Parameters:
    856: .  linesearch - linesearch context

    858:    Logically Collective on SNESLineSearch

    860:    Level: intermediate

    862: .seealso: SNESLineSearchCreate()
    863: @*/
    864: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
    865: {
    867:   PetscBool      iascii;

    871:   if (!viewer) {
    872:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch),&viewer);
    873:   }

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

    902: /*@C
    903:    SNESLineSearchGetType - Gets the linesearch type

    905:    Logically Collective on SNESLineSearch

    907:    Input Parameters:
    908: .  linesearch - linesearch context

    910:    Output Parameters:
    911: -  type - The type of line search, or NULL if not set

    913:    Level: intermediate

    915: .seealso: SNESLineSearchCreate(), SNESLineSearchType, SNESLineSearchSetFromOptions(), SNESLineSearchSetType()
    916: @*/
    917: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
    918: {
    922:   *type = ((PetscObject)linesearch)->type_name;
    923:   return(0);
    924: }

    926: /*@C
    927:    SNESLineSearchSetType - Sets the linesearch type

    929:    Logically Collective on SNESLineSearch

    931:    Input Parameters:
    932: +  linesearch - linesearch context
    933: -  type - The type of line search to be used

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

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

    946:    Level: intermediate

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

    959:   PetscObjectTypeCompare((PetscObject)linesearch,type,&match);
    960:   if (match) return(0);

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

    975:   PetscObjectChangeTypeName((PetscObject)linesearch,type);
    976:   (*r)(linesearch);
    977:   return(0);
    978: }

    980: /*@
    981:    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.

    983:    Input Parameters:
    984: +  linesearch - linesearch context
    985: -  snes - The snes instance

    987:    Level: developer

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

    994:    Level: developer

    996: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    997: @*/
    998: PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
    999: {
    1003:   linesearch->snes = snes;
    1004:   return(0);
    1005: }

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

    1013:    Input Parameters:
    1014: .  linesearch - linesearch context

    1016:    Output Parameters:
    1017: .  snes - The snes instance

    1019:    Level: developer

    1021: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    1022: @*/
    1023: PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
    1024: {
    1028:   *snes = linesearch->snes;
    1029:   return(0);
    1030: }

    1032: /*@
    1033:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

    1035:    Input Parameters:
    1036: .  linesearch - linesearch context

    1038:    Output Parameters:
    1039: .  lambda - The last steplength computed during SNESLineSearchApply()

    1041:    Level: advanced

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

    1049: .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply()
    1050: @*/
    1051: PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
    1052: {
    1056:   *lambda = linesearch->lambda;
    1057:   return(0);
    1058: }

    1060: /*@
    1061:    SNESLineSearchSetLambda - Sets the linesearch steplength.

    1063:    Input Parameters:
    1064: +  linesearch - linesearch context
    1065: -  lambda - The last steplength.

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

    1073:    Level: advanced

    1075: .seealso: SNESLineSearchGetLambda()
    1076: @*/
    1077: PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
    1078: {
    1081:   linesearch->lambda = lambda;
    1082:   return(0);
    1083: }

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

    1091:    Input Parameter:
    1092: .  linesearch - linesearch context

    1094:    Output Parameters:
    1095: +  steptol - The minimum steplength
    1096: .  maxstep - The maximum steplength
    1097: .  rtol    - The relative tolerance for iterative line searches
    1098: .  atol    - The absolute tolerance for iterative line searches
    1099: .  ltol    - The change in lambda tolerance for iterative line searches
    1100: -  max_it  - The maximum number of iterations of the line search

    1102:    Level: intermediate

    1104:    Notes:
    1105:    Different line searches may implement these parameters slightly differently as
    1106:    the type requires.

    1108: .seealso: SNESLineSearchSetTolerances()
    1109: @*/
    1110: PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
    1111: {
    1114:   if (steptol) {
    1116:     *steptol = linesearch->steptol;
    1117:   }
    1118:   if (maxstep) {
    1120:     *maxstep = linesearch->maxstep;
    1121:   }
    1122:   if (rtol) {
    1124:     *rtol = linesearch->rtol;
    1125:   }
    1126:   if (atol) {
    1128:     *atol = linesearch->atol;
    1129:   }
    1130:   if (ltol) {
    1132:     *ltol = linesearch->ltol;
    1133:   }
    1134:   if (max_its) {
    1136:     *max_its = linesearch->max_its;
    1137:   }
    1138:   return(0);
    1139: }

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

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

    1156:    Notes:
    1157:    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
    1158:    place of an argument.

    1160:    Level: intermediate

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

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

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

    1185:   if (rtol != PETSC_DEFAULT) {
    1186:     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);
    1187:     linesearch->rtol = rtol;
    1188:   }

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

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

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

    1207: /*@
    1208:    SNESLineSearchGetDamping - Gets the line search damping parameter.

    1210:    Input Parameters:
    1211: .  linesearch - linesearch context

    1213:    Output Parameters:
    1214: .  damping - The damping parameter

    1216:    Level: advanced

    1218: .seealso: SNESLineSearchGetStepTolerance(), SNESQN
    1219: @*/

    1221: PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
    1222: {
    1226:   *damping = linesearch->damping;
    1227:   return(0);
    1228: }

    1230: /*@
    1231:    SNESLineSearchSetDamping - Sets the line search damping parameter.

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

    1237:    Options Database:
    1238: .   -snes_linesearch_damping
    1239:    Level: intermediate

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

    1248: .seealso: SNESLineSearchGetDamping()
    1249: @*/
    1250: PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
    1251: {
    1254:   linesearch->damping = damping;
    1255:   return(0);
    1256: }

    1258: /*@
    1259:    SNESLineSearchGetOrder - Gets the line search approximation order.

    1261:    Input Parameters:
    1262: .  linesearch - linesearch context

    1264:    Output Parameters:
    1265: .  order - The order

    1267:    Possible Values for order:
    1268: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1269: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1270: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1272:    Level: intermediate

    1274: .seealso: SNESLineSearchSetOrder()
    1275: @*/

    1277: PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
    1278: {
    1282:   *order = linesearch->order;
    1283:   return(0);
    1284: }

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

    1289:    Input Parameters:
    1290: +  linesearch - linesearch context
    1291: -  order - The damping parameter

    1293:    Level: intermediate

    1295:    Possible Values for order:
    1296: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1297: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1298: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1300:    Notes:
    1301:    Variable orders are supported by the following line searches:
    1302: +  bt - cubic and quadratic
    1303: -  cp - linear and quadratic

    1305: .seealso: SNESLineSearchGetOrder(), SNESLineSearchSetDamping()
    1306: @*/
    1307: PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
    1308: {
    1311:   linesearch->order = order;
    1312:   return(0);
    1313: }

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

    1318:    Input Parameter:
    1319: .  linesearch - linesearch context

    1321:    Output Parameters:
    1322: +  xnorm - The norm of the current solution
    1323: .  fnorm - The norm of the current function
    1324: -  ynorm - The norm of the current update

    1326:    Notes:
    1327:    This function is mainly called from SNES implementations.

    1329:    Level: developer

    1331: .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs()
    1332: @*/
    1333: PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
    1334: {
    1337:   if (xnorm) *xnorm = linesearch->xnorm;
    1338:   if (fnorm) *fnorm = linesearch->fnorm;
    1339:   if (ynorm) *ynorm = linesearch->ynorm;
    1340:   return(0);
    1341: }

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

    1346:    Input Parameters:
    1347: +  linesearch - linesearch context
    1348: .  xnorm - The norm of the current solution
    1349: .  fnorm - The norm of the current function
    1350: -  ynorm - The norm of the current update

    1352:    Level: advanced

    1354: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1355: @*/
    1356: PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
    1357: {
    1360:   linesearch->xnorm = xnorm;
    1361:   linesearch->fnorm = fnorm;
    1362:   linesearch->ynorm = ynorm;
    1363:   return(0);
    1364: }

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

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

    1372:    Options Database Keys:
    1373: .   -snes_linesearch_norms - turn norm computation on or off

    1375:    Level: intermediate

    1377: .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms()
    1378: @*/
    1379: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
    1380: {
    1382:   SNES           snes;

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

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

    1406:    Input Parameters:
    1407: +  linesearch  - linesearch context
    1408: -  flg  - indicates whether or not to compute norms

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

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

    1416:    Level: intermediate

    1418: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC
    1419: @*/
    1420: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
    1421: {
    1423:   linesearch->norms = flg;
    1424:   return(0);
    1425: }

    1427: /*@
    1428:    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context

    1430:    Input Parameter:
    1431: .  linesearch - linesearch context

    1433:    Output Parameters:
    1434: +  X - Solution vector
    1435: .  F - Function vector
    1436: .  Y - Search direction vector
    1437: .  W - Solution work vector
    1438: -  G - Function work vector

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

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

    1448:    Level: advanced

    1450: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1451: @*/
    1452: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
    1453: {
    1456:   if (X) {
    1458:     *X = linesearch->vec_sol;
    1459:   }
    1460:   if (F) {
    1462:     *F = linesearch->vec_func;
    1463:   }
    1464:   if (Y) {
    1466:     *Y = linesearch->vec_update;
    1467:   }
    1468:   if (W) {
    1470:     *W = linesearch->vec_sol_new;
    1471:   }
    1472:   if (G) {
    1474:     *G = linesearch->vec_func_new;
    1475:   }
    1476:   return(0);
    1477: }

    1479: /*@
    1480:    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context

    1482:    Input Parameters:
    1483: +  linesearch - linesearch context
    1484: .  X - Solution vector
    1485: .  F - Function vector
    1486: .  Y - Search direction vector
    1487: .  W - Solution work vector
    1488: -  G - Function work vector

    1490:    Level: advanced

    1492: .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs()
    1493: @*/
    1494: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
    1495: {
    1498:   if (X) {
    1500:     linesearch->vec_sol = X;
    1501:   }
    1502:   if (F) {
    1504:     linesearch->vec_func = F;
    1505:   }
    1506:   if (Y) {
    1508:     linesearch->vec_update = Y;
    1509:   }
    1510:   if (W) {
    1512:     linesearch->vec_sol_new = W;
    1513:   }
    1514:   if (G) {
    1516:     linesearch->vec_func_new = G;
    1517:   }
    1518:   return(0);
    1519: }

    1521: /*@C
    1522:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
    1523:    SNES options in the database.

    1525:    Logically Collective on SNESLineSearch

    1527:    Input Parameters:
    1528: +  snes - the SNES context
    1529: -  prefix - the prefix to prepend to all option names

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

    1535:    Level: advanced

    1537: .seealso: SNESGetOptionsPrefix()
    1538: @*/
    1539: PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
    1540: {

    1545:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);
    1546:   return(0);
    1547: }

    1549: /*@C
    1550:    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
    1551:    SNESLineSearch options in the database.

    1553:    Not Collective

    1555:    Input Parameter:
    1556: .  linesearch - the SNESLineSearch context

    1558:    Output Parameter:
    1559: .  prefix - pointer to the prefix string used

    1561:    Notes:
    1562:    On the fortran side, the user should pass in a string 'prefix' of
    1563:    sufficient length to hold the prefix.

    1565:    Level: advanced

    1567: .seealso: SNESAppendOptionsPrefix()
    1568: @*/
    1569: PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
    1570: {

    1575:   PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);
    1576:   return(0);
    1577: }

    1579: /*@C
    1580:    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.

    1582:    Input Parameters:
    1583: +  linesearch - the SNESLineSearch context
    1584: -  nwork - the number of work vectors

    1586:    Level: developer

    1588: .seealso: SNESSetWorkVecs()
    1589: @*/
    1590: PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
    1591: {

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

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

    1604:    Input Parameters:
    1605: .  linesearch - linesearch context

    1607:    Output Parameters:
    1608: .  result - The success or failure status

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

    1614:    Level: intermediate

    1616: .seealso: SNESLineSearchSetReason(), SNESLineSearchReason
    1617: @*/
    1618: PetscErrorCode  SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
    1619: {
    1623:   *result = linesearch->result;
    1624:   return(0);
    1625: }

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

    1630:    Input Parameters:
    1631: +  linesearch - linesearch context
    1632: -  result - The success or failure status

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

    1638:    Level: developer

    1640: .seealso: SNESLineSearchGetSResult()
    1641: @*/
    1642: PetscErrorCode  SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
    1643: {
    1646:   linesearch->result = result;
    1647:   return(0);
    1648: }

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

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

    1658:    Logically Collective on SNES

    1660:    Calling sequence of projectfunc:
    1661: .vb
    1662:    projectfunc (SNES snes, Vec X)
    1663: .ve

    1665:     Input parameters for projectfunc:
    1666: +   snes - nonlinear context
    1667: -   X - current solution

    1669:     Output parameters for projectfunc:
    1670: .   X - Projected solution

    1672:    Calling sequence of normfunc:
    1673: .vb
    1674:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
    1675: .ve

    1677:     Input parameters for normfunc:
    1678: +   snes - nonlinear context
    1679: .   X - current solution
    1680: -   F - current residual

    1682:     Output parameters for normfunc:
    1683: .   fnorm - VI-specific norm of the function

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

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

    1691:     Level: developer

    1693: .seealso: SNESLineSearchGetVIFunctions(), SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck()
    1694: @*/
    1695: PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
    1696: {
    1699:   if (projectfunc) linesearch->ops->viproject = projectfunc;
    1700:   if (normfunc) linesearch->ops->vinorm = normfunc;
    1701:   return(0);
    1702: }

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

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

    1710:    Output Parameters:
    1711: +  projectfunc - function for projecting the function to the bounds
    1712: -  normfunc - function for computing the norm of an active set

    1714:    Logically Collective on SNES

    1716:     Level: developer

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

    1728: /*@C
    1729:   SNESLineSearchRegister - See SNESLineSearchRegister()

    1731:   Level: advanced
    1732: @*/
    1733: PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
    1734: {

    1738:   SNESInitializePackage();
    1739:   PetscFunctionListAdd(&SNESLineSearchList,sname,function);
    1740:   return(0);
    1741: }