Actual source code: linesearch.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      1: #include <petsc/private/linesearchimpl.h> /*I "petscsnes.h" I*/

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

      6: PetscClassId  SNESLINESEARCH_CLASSID;
      7: PetscLogEvent SNESLineSearch_Apply;

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

     14:    Logically Collective on SNESLineSearch

     16:    Input Parameters:
     17: .  ls - the SNESLineSearch context

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

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

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

     30:    Level: intermediate

     32: .keywords: SNESLineSearch, nonlinear, set, monitor

     34: .seealso: SNESLineSearchMonitorDefault(), SNESLineSearchMonitorSet()
     35: @*/
     36: PetscErrorCode  SNESLineSearchMonitorCancel(SNESLineSearch ls)
     37: {
     39:   PetscInt       i;

     43:   for (i=0; i<ls->numbermonitors; i++) {
     44:     if (ls->monitordestroy[i]) {
     45:       (*ls->monitordestroy[i])(&ls->monitorcontext[i]);
     46:     }
     47:   }
     48:   ls->numbermonitors = 0;
     49:   return(0);
     50: }

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

     57:    Collective on SNES

     59:    Input Parameters:
     60: .  ls - the linesearch object

     62:    Notes:
     63:    This routine is called by the SNES implementations.
     64:    It does not typically need to be called by the user.

     66:    Level: developer

     68: .seealso: SNESLineSearchMonitorSet()
     69: @*/
     70: PetscErrorCode  SNESLineSearchMonitor(SNESLineSearch ls)
     71: {
     73:   PetscInt       i,n = ls->numbermonitors;

     76:   for (i=0; i<n; i++) {
     77:     (*ls->monitorftns[i])(ls,ls->monitorcontext[i]);
     78:   }
     79:   return(0);
     80: }

     84: /*@C
     85:    SNESLineSearchMonitorSet - Sets an ADDITIONAL function that is to be used at every
     86:    iteration of the nonlinear solver to display the iteration's
     87:    progress.

     89:    Logically Collective on SNESLineSearch

     91:    Input Parameters:
     92: +  ls - the SNESLineSearch context
     93: .  f - the monitor function
     94: .  mctx - [optional] user-defined context for private data for the
     95:           monitor routine (use NULL if no context is desired)
     96: -  monitordestroy - [optional] routine that frees monitor context
     97:           (may be NULL)

     99:    Notes:
    100:    Several different monitoring routines may be set by calling
    101:    SNESLineSearchMonitorSet() multiple times; all will be called in the
    102:    order in which they were set.

    104:    Fortran notes: Only a single monitor function can be set for each SNESLineSearch object

    106:    Level: intermediate

    108: .keywords: SNESLineSearch, nonlinear, set, monitor

    110: .seealso: SNESLineSearchMonitorDefault(), SNESLineSearchMonitorCancel()
    111: @*/
    112: PetscErrorCode  SNESLineSearchMonitorSet(SNESLineSearch ls,PetscErrorCode (*f)(SNESLineSearch,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
    113: {
    116:   if (ls->numbermonitors >= MAXSNESLSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
    117:   ls->monitorftns[ls->numbermonitors]          = f;
    118:   ls->monitordestroy[ls->numbermonitors]   = monitordestroy;
    119:   ls->monitorcontext[ls->numbermonitors++] = (void*)mctx;
    120:   return(0);
    121: }

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

    128:    Collective on SNESLineSearch

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

    134:    Level: intermediate

    136: .keywords: SNES, nonlinear, default, monitor, norm

    138: .seealso: SNESMonitorSet(), SNESMonitorSolution()
    139: @*/
    140: PetscErrorCode  SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls,PetscViewerAndFormat *vf)
    141: {
    143:   PetscViewer    viewer = vf->viewer;
    144:   Vec            Y,W,G;

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

    161: /*@
    162:    SNESLineSearchCreate - Creates the line search context.

    164:    Logically Collective on Comm

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

    169:    Output Parameters:
    170: .  outlinesearch - the new linesearch context

    172:    Level: developer

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

    178: .keywords: LineSearch, create, context

    180: .seealso: LineSearchDestroy(), SNESGetLineSearch()
    181: @*/

    183: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
    184: {
    186:   SNESLineSearch linesearch;

    190:   SNESInitializePackage();
    191:   *outlinesearch = NULL;

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

    195:   linesearch->vec_sol_new  = NULL;
    196:   linesearch->vec_func_new = NULL;
    197:   linesearch->vec_sol      = NULL;
    198:   linesearch->vec_func     = NULL;
    199:   linesearch->vec_update   = NULL;

    201:   linesearch->lambda       = 1.0;
    202:   linesearch->fnorm        = 1.0;
    203:   linesearch->ynorm        = 1.0;
    204:   linesearch->xnorm        = 1.0;
    205:   linesearch->result       = SNES_LINESEARCH_SUCCEEDED;
    206:   linesearch->norms        = PETSC_TRUE;
    207:   linesearch->keeplambda   = PETSC_FALSE;
    208:   linesearch->damping      = 1.0;
    209:   linesearch->maxstep      = 1e8;
    210:   linesearch->steptol      = 1e-12;
    211:   linesearch->rtol         = 1e-8;
    212:   linesearch->atol         = 1e-15;
    213:   linesearch->ltol         = 1e-8;
    214:   linesearch->precheckctx  = NULL;
    215:   linesearch->postcheckctx = NULL;
    216:   linesearch->max_its      = 1;
    217:   linesearch->setupcalled  = PETSC_FALSE;
    218:   *outlinesearch           = linesearch;
    219:   return(0);
    220: }

    224: /*@
    225:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
    226:    any required vectors.

    228:    Collective on SNESLineSearch

    230:    Input Parameters:
    231: .  linesearch - The LineSearch instance.

    233:    Notes:
    234:    For most cases, this needn't be called by users or outside of SNESLineSearchApply().
    235:    The only current case where this is called outside of this is for the VI
    236:    solvers, which modify the solution and work vectors before the first call
    237:    of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be
    238:    allocated upfront.

    240:    Level: advanced

    242: .keywords: SNESLineSearch, SetUp

    244: .seealso: SNESLineSearchReset()
    245: @*/

    247: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
    248: {

    252:   if (!((PetscObject)linesearch)->type_name) {
    253:     SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);
    254:   }
    255:   if (!linesearch->setupcalled) {
    256:     if (!linesearch->vec_sol_new) {
    257:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
    258:     }
    259:     if (!linesearch->vec_func_new) {
    260:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
    261:     }
    262:     if (linesearch->ops->setup) {
    263:       (*linesearch->ops->setup)(linesearch);
    264:     }
    265:     if (!linesearch->ops->snesfunc) {SNESLineSearchSetFunction(linesearch,SNESComputeFunction);}
    266:     linesearch->lambda      = linesearch->damping;
    267:     linesearch->setupcalled = PETSC_TRUE;
    268:   }
    269:   return(0);
    270: }

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

    278:    Collective on SNESLineSearch

    280:    Input Parameters:
    281: .  linesearch - The LineSearch instance.

    283:    Notes: Usually only called by SNESReset()

    285:    Level: developer

    287: .keywords: SNESLineSearch, Reset

    289: .seealso: SNESLineSearchSetUp()
    290: @*/

    292: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
    293: {

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

    299:   VecDestroy(&linesearch->vec_sol_new);
    300:   VecDestroy(&linesearch->vec_func_new);

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

    304:   linesearch->nwork       = 0;
    305:   linesearch->setupcalled = PETSC_FALSE;
    306:   return(0);
    307: }

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

    314:    Input Parameters:
    315: .  linesearch - the SNESLineSearch context
    316: +  func       - function evaluation routine

    318:    Level: developer

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

    322: .keywords: get, linesearch, pre-check

    324: .seealso: SNESSetFunction()
    325: @*/
    326: PetscErrorCode  SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES,Vec,Vec))
    327: {
    330:   linesearch->ops->snesfunc = func;
    331:   return(0);
    332: }

    335: /*MC
    336:     SNESLineSearchPreCheckFunction - form of function passed to check the search direction before line search is called

    338:      Synopsis:
    339:      #include <petscsnes.h>
    340:      SNESLineSearchPreCheckFunction(SNESLineSearch snes,Vec x,Vec y, PetscBool *changed);

    342:        Input Parameters:
    343: +      x - solution vector
    344: .      y - search direction vector
    345: -      changed - flag to indicate the precheck changed x or y.

    347:      Note: This is NOTE a PETSc function, rather it documents the calling sequence of functions passed to SNESLineSearchSetPreCheck()
    348:            and SNESLineSearchGetPreCheck()

    350:    Level: advanced

    352: .seealso:   SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck()
    353: M*/

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

    362:    Logically Collective on SNESLineSearch

    364:    Input Parameters:
    365: +  linesearch - the SNESLineSearch context
    366: .  func - [optional] function evaluation routine, see SNESLineSearchPreCheckFunction for the calling sequence
    367: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

    369:    Level: intermediate

    371: .keywords: set, linesearch, pre-check

    373: .seealso: SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
    374: @*/
    375: PetscErrorCode  SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void *ctx)
    376: {
    379:   if (func) linesearch->ops->precheck = func;
    380:   if (ctx) linesearch->precheckctx = ctx;
    381:   return(0);
    382: }

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

    389:    Input Parameters:
    390: .  linesearch - the SNESLineSearch context

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

    396:    Level: intermediate

    398: .keywords: get, linesearch, pre-check

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

    411: /*MC
    412:     SNESLineSearchPostCheckFunction - form of function that is called after line search is complete

    414:      Synopsis:
    415:      #include <petscsnes.h>
    416:      SNESLineSearchPostheckFunction(SNESLineSearch linesearch,Vec x,Vec y,  Vec w, *changed_y, PetscBool *changed_w);

    418:      Input Parameters:
    419: +      x - old solution vector
    420: .      y - search direction vector
    421: .      w - new solution vector
    422: .      changed_y - indicates that the line search changed y
    423: -      changed_w - indicates that the line search changed w

    425:      Note: This is NOTE a PETSc function, rather it documents the calling sequence of functions passed to SNESLineSearchSetPostCheck()
    426:            and SNESLineSearchGetPostCheck()

    428:    Level: advanced

    430: .seealso:   SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchGetPostCheck()
    431: M*/

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

    439:    Logically Collective on SNESLineSearch

    441:    Input Parameters:
    442: +  linesearch - the SNESLineSearch context
    443: .  func - [optional] function evaluation routine, see SNESLineSearchPostCheckFunction for the calling sequence
    444: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

    446:    Level: intermediate

    448: .keywords: set, linesearch, post-check

    450: .seealso: SNESLineSearchSetPreCheck()
    451: @*/
    452: PetscErrorCode  SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx)
    453: {
    456:   if (func) linesearch->ops->postcheck = func;
    457:   if (ctx) linesearch->postcheckctx = ctx;
    458:   return(0);
    459: }

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

    466:    Input Parameters:
    467: .  linesearch - the SNESLineSearch context

    469:    Output Parameters:
    470: +  func - [optional] function evaluation routine, see for the calling sequence SNESLineSearchPostCheckFunction
    471: -  ctx        - [optional] user-defined context for private data for the function evaluation routine (may be NULL)

    473:    Level: intermediate

    475: .keywords: get, linesearch, post-check

    477: .seealso: SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck()
    478: @*/
    479: PetscErrorCode  SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void **ctx)
    480: {
    483:   if (func) *func = linesearch->ops->postcheck;
    484:   if (ctx) *ctx = linesearch->postcheckctx;
    485:   return(0);
    486: }

    490: /*@
    491:    SNESLineSearchPreCheck - Prepares the line search for being applied.

    493:    Logically Collective on SNESLineSearch

    495:    Input Parameters:
    496: +  linesearch - The linesearch instance.
    497: .  X - The current solution
    498: -  Y - The step direction

    500:    Output Parameters:
    501: .  changed - Indicator that the precheck routine has changed anything

    503:    Level: developer

    505: .keywords: SNESLineSearch, Create

    507: .seealso: SNESLineSearchPostCheck()
    508: @*/
    509: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed)
    510: {

    514:   *changed = PETSC_FALSE;
    515:   if (linesearch->ops->precheck) {
    516:     (*linesearch->ops->precheck)(linesearch, X, Y, changed, linesearch->precheckctx);
    518:   }
    519:   return(0);
    520: }

    524: /*@
    525:    SNESLineSearchPostCheck - Prepares the line search for being applied.

    527:    Logically Collective on SNESLineSearch

    529:    Input Parameters:
    530: +  linesearch - The linesearch context
    531: .  X - The last solution
    532: .  Y - The step direction
    533: -  W - The updated solution, W = X + lambda*Y for some lambda

    535:    Output Parameters:
    536: +  changed_Y - Indicator if the direction Y has been changed.
    537: -  changed_W - Indicator if the new candidate solution W has been changed.

    539:    Level: developer

    541: .keywords: SNESLineSearch, Create

    543: .seealso: SNESLineSearchPreCheck()
    544: @*/
    545: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W)
    546: {

    550:   *changed_Y = PETSC_FALSE;
    551:   *changed_W = PETSC_FALSE;
    552:   if (linesearch->ops->postcheck) {
    553:     (*linesearch->ops->postcheck)(linesearch,X,Y,W,changed_Y,changed_W,linesearch->postcheckctx);
    556:   }
    557:   return(0);
    558: }

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

    565:    Logically Collective on SNESLineSearch

    567:    Input Arguments:
    568: +  linesearch - linesearch context
    569: .  X - base state for this step
    570: .  Y - initial correction
    571: -  ctx - context for this function

    573:    Output Arguments:
    574: +  Y - correction, possibly modified
    575: -  changed - flag indicating that Y was modified

    577:    Options Database Key:
    578: +  -snes_linesearch_precheck_picard - activate this routine
    579: -  -snes_linesearch_precheck_picard_angle - angle

    581:    Level: advanced

    583:    Notes:
    584:    This function should be passed to SNESLineSearchSetPreCheck()

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

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

    593: .seealso: SNESLineSearchSetPreCheck()
    594: @*/
    595: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed,void *ctx)
    596: {
    598:   PetscReal      angle = *(PetscReal*)linesearch->precheckctx;
    599:   Vec            Ylast;
    600:   PetscScalar    dot;
    601:   PetscInt       iter;
    602:   PetscReal      ynorm,ylastnorm,theta,angle_radians;
    603:   SNES           snes;

    606:   SNESLineSearchGetSNES(linesearch, &snes);
    607:   PetscObjectQuery((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject*)&Ylast);
    608:   if (!Ylast) {
    609:     VecDuplicate(Y,&Ylast);
    610:     PetscObjectCompose((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject)Ylast);
    611:     PetscObjectDereference((PetscObject)Ylast);
    612:   }
    613:   SNESGetIterationNumber(snes,&iter);
    614:   if (iter < 2) {
    615:     VecCopy(Y,Ylast);
    616:     *changed = PETSC_FALSE;
    617:     return(0);
    618:   }

    620:   VecDot(Y,Ylast,&dot);
    621:   VecNorm(Y,NORM_2,&ynorm);
    622:   VecNorm(Ylast,NORM_2,&ylastnorm);
    623:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
    624:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm),-1.0,1.0));
    625:   angle_radians = angle * PETSC_PI / 180.;
    626:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
    627:     /* Modify the step Y */
    628:     PetscReal alpha,ydiffnorm;
    629:     VecAXPY(Ylast,-1.0,Y);
    630:     VecNorm(Ylast,NORM_2,&ydiffnorm);
    631:     alpha = ylastnorm / ydiffnorm;
    632:     VecCopy(Y,Ylast);
    633:     VecScale(Y,alpha);
    634:     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);
    635:   } else {
    636:     PetscInfo2(snes,"Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n",(double)(theta*180./PETSC_PI),(double)angle);
    637:     VecCopy(Y,Ylast);
    638:     *changed = PETSC_FALSE;
    639:   }
    640:   return(0);
    641: }

    645: /*@
    646:    SNESLineSearchApply - Computes the line-search update.

    648:    Collective on SNESLineSearch

    650:    Input Parameters:
    651: +  linesearch - The linesearch context
    652: .  X - The current solution
    653: .  F - The current function
    654: .  fnorm - The current norm
    655: -  Y - The search direction

    657:    Output Parameters:
    658: +  X - The new solution
    659: .  F - The new function
    660: -  fnorm - The new function norm

    662:    Options Database Keys:
    663: + -snes_linesearch_type - basic, bt, l2, cp, nleqerr, shell
    664: . -snes_linesearch_monitor [:filename] - Print progress of line searches
    665: . -snes_linesearch_damping - The linesearch damping parameter
    666: . -snes_linesearch_norms   - Turn on/off the linesearch norms
    667: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
    668: - -snes_linesearch_max_it - The number of iterations for iterative line searches

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

    678:    Level: Intermediate

    680: .keywords: SNESLineSearch, Create

    682: .seealso: SNESLineSearchCreate(), SNESLineSearchPreCheck(), SNESLineSearchPostCheck(), SNESSolve(), SNESComputeFunction()
    683: @*/
    684: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y)
    685: {

    694:   linesearch->result = SNES_LINESEARCH_SUCCEEDED;

    696:   linesearch->vec_sol    = X;
    697:   linesearch->vec_update = Y;
    698:   linesearch->vec_func   = F;

    700:   SNESLineSearchSetUp(linesearch);

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

    704:   if (fnorm) linesearch->fnorm = *fnorm;
    705:   else {
    706:     VecNorm(F, NORM_2, &linesearch->fnorm);
    707:   }

    709:   PetscLogEventBegin(SNESLineSearch_Apply,linesearch,X,F,Y);

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

    713:   PetscLogEventEnd(SNESLineSearch_Apply,linesearch,X,F,Y);

    715:   if (fnorm) *fnorm = linesearch->fnorm;
    716:   return(0);
    717: }

    721: /*@
    722:    SNESLineSearchDestroy - Destroys the line search instance.

    724:    Collective on SNESLineSearch

    726:    Input Parameters:
    727: .  linesearch - The linesearch context

    729:    Level: Intermediate

    731: .keywords: SNESLineSearch, Destroy

    733: .seealso: SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy()
    734: @*/
    735: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch)
    736: {

    740:   if (!*linesearch) return(0);
    742:   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = 0; return(0);}
    743:   PetscObjectSAWsViewOff((PetscObject)*linesearch);
    744:   SNESLineSearchReset(*linesearch);
    745:   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
    746:   PetscViewerDestroy(&(*linesearch)->monitor);
    747:   SNESLineSearchMonitorCancel((*linesearch));
    748:   PetscHeaderDestroy(linesearch);
    749:   return(0);
    750: }

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

    757:    Input Parameters:
    758: +  linesearch - the linesearch object
    759: -  viewer - an ASCII PetscViewer or NULL to turn off monitor

    761:    Logically Collective on SNESLineSearch

    763:    Options Database:
    764: .   -snes_linesearch_monitor [:filename] - enables the monitor

    766:    Level: intermediate

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

    772: .seealso: SNESLineSearchGetDefaultMonitor(), PetscViewer, SNESLineSearchSetMonitor()
    773: @*/
    774: PetscErrorCode  SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
    775: {

    779:   if (viewer) {PetscObjectReference((PetscObject)viewer);}
    780:   PetscViewerDestroy(&linesearch->monitor);
    781:   linesearch->monitor = viewer;
    782:   return(0);
    783: }

    787: /*@
    788:    SNESLineSearchGetDefaultMonitor - Gets the PetscViewer instance for the line search monitor.

    790:    Input Parameter:
    791: .  linesearch - linesearch context

    793:    Output Parameter:
    794: .  monitor - monitor context

    796:    Logically Collective on SNES

    798:    Options Database Keys:
    799: .   -snes_linesearch_monitor - enables the monitor

    801:    Level: intermediate

    803: .seealso: SNESLineSearchSetDefaultMonitor(), PetscViewer
    804: @*/
    805: PetscErrorCode  SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
    806: {
    809:   if (monitor) {
    811:     *monitor = linesearch->monitor;
    812:   }
    813:   return(0);
    814: }

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

    821:    Collective on SNESLineSearch

    823:    Input Parameters:
    824: +  ls - LineSearch object you wish to monitor
    825: .  name - the monitor type one is seeking
    826: .  help - message indicating what monitoring is done
    827: .  manual - manual page for the monitor
    828: .  monitor - the monitor function
    829: -  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

    831:    Level: developer

    833: .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
    834:           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
    835:           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
    836:           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
    837:           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
    838:           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
    839:           PetscOptionsFList(), PetscOptionsEList()
    840: @*/
    841: PetscErrorCode  SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(SNESLineSearch,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(SNESLineSearch,PetscViewerAndFormat*))
    842: {
    843:   PetscErrorCode    ierr;
    844:   PetscViewer       viewer;
    845:   PetscViewerFormat format;
    846:   PetscBool         flg;

    849:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls),((PetscObject)ls)->prefix,name,&viewer,&format,&flg);
    850:   if (flg) {
    851:     PetscViewerAndFormat *vf;
    852:     PetscViewerAndFormatCreate(viewer,format,&vf);
    853:     PetscObjectDereference((PetscObject)viewer);
    854:     if (monitorsetup) {
    855:       (*monitorsetup)(ls,vf);
    856:     }
    857:     SNESLineSearchMonitorSet(ls,(PetscErrorCode (*)(SNESLineSearch,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);
    858:   }
    859:   return(0);
    860: }

    864: /*@
    865:    SNESLineSearchSetFromOptions - Sets options for the line search

    867:    Input Parameters:
    868: .  linesearch - linesearch context

    870:    Options Database Keys:
    871: + -snes_linesearch_type <type> - basic, bt, l2, cp, nleqerr, shell
    872: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
    873: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch type
    874: . -snes_linesearch_minlambda - The minimum step length
    875: . -snes_linesearch_maxstep - The maximum step size
    876: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
    877: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
    878: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
    879: . -snes_linesearch_max_it - The number of iterations for iterative line searches
    880: . -snes_linesearch_monitor [:filename] - Print progress of line searches
    881: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
    882: . -snes_linesearch_damping - The linesearch damping parameter
    883: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
    884: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
    885: - -snes_linesearch_precheck_picard_angle - Angle used in picard precheck method

    887:    Logically Collective on SNESLineSearch

    889:    Level: intermediate

    891: .seealso: SNESLineSearchCreate(), SNESLineSearchSetOrder(), SNESLineSearchSetType(), SNESLineSearchSetTolerances(), SNESLineSearchSetDamping(), SNESLineSearchPreCheckPicard()
    892: @*/
    893: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
    894: {
    895:   PetscErrorCode    ierr;
    896:   const char        *deft = SNESLINESEARCHBASIC;
    897:   char              type[256];
    898:   PetscBool         flg, set;
    899:   PetscViewer       viewer;

    902:   SNESLineSearchRegisterAll();

    904:   PetscObjectOptionsBegin((PetscObject)linesearch);
    905:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
    906:   PetscOptionsFList("-snes_linesearch_type","Linesearch type","SNESLineSearchSetType",SNESLineSearchList,deft,type,256,&flg);
    907:   if (flg) {
    908:     SNESLineSearchSetType(linesearch,type);
    909:   } else if (!((PetscObject)linesearch)->type_name) {
    910:     SNESLineSearchSetType(linesearch,deft);
    911:   }

    913:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch),((PetscObject)linesearch)->prefix,"-snes_linesearch_monitor",&viewer,NULL,&set);
    914:   if (set) {
    915:     SNESLineSearchSetDefaultMonitor(linesearch,viewer);
    916:     PetscViewerDestroy(&viewer);
    917:   }
    918:   SNESLineSearchMonitorSetFromOptions(linesearch,"-snes_linesearch_monitor_solution_update","View correction at each iteration","SNESLineSearchMonitorSolutionUpdate",SNESLineSearchMonitorSolutionUpdate,NULL);
    919:
    920:   /* tolerances */
    921:   PetscOptionsReal("-snes_linesearch_minlambda","Minimum step length","SNESLineSearchSetTolerances",linesearch->steptol,&linesearch->steptol,NULL);
    922:   PetscOptionsReal("-snes_linesearch_maxstep","Maximum step size","SNESLineSearchSetTolerances",linesearch->maxstep,&linesearch->maxstep,NULL);
    923:   PetscOptionsReal("-snes_linesearch_rtol","Relative tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->rtol,&linesearch->rtol,NULL);
    924:   PetscOptionsReal("-snes_linesearch_atol","Absolute tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->atol,&linesearch->atol,NULL);
    925:   PetscOptionsReal("-snes_linesearch_ltol","Change in lambda tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->ltol,&linesearch->ltol,NULL);
    926:   PetscOptionsInt("-snes_linesearch_max_it","Maximum iterations for iterative line searches","SNESLineSearchSetTolerances",linesearch->max_its,&linesearch->max_its,NULL);

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

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

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

    939:       PetscOptionsReal("-snes_linesearch_precheck_picard_angle","Maximum angle at which to activate the correction",
    940:                               "none",linesearch->precheck_picard_angle,&linesearch->precheck_picard_angle,NULL);
    941:       SNESLineSearchSetPreCheck(linesearch,SNESLineSearchPreCheckPicard,&linesearch->precheck_picard_angle);
    942:     } else {
    943:       SNESLineSearchSetPreCheck(linesearch,NULL,NULL);
    944:     }
    945:   }
    946:   PetscOptionsInt("-snes_linesearch_order","Order of approximation used in the line search","SNESLineSearchSetOrder",linesearch->order,&linesearch->order,NULL);
    947:   PetscOptionsBool("-snes_linesearch_norms","Compute final norms in line search","SNESLineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,NULL);

    949:   if (linesearch->ops->setfromoptions) {
    950:     (*linesearch->ops->setfromoptions)(PetscOptionsObject,linesearch);
    951:   }

    953:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)linesearch);
    954:   PetscOptionsEnd();
    955:   return(0);
    956: }

    960: /*@
    961:    SNESLineSearchView - Prints useful information about the line search

    963:    Input Parameters:
    964: .  linesearch - linesearch context

    966:    Logically Collective on SNESLineSearch

    968:    Level: intermediate

    970: .seealso: SNESLineSearchCreate()
    971: @*/
    972: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
    973: {
    975:   PetscBool      iascii;

    979:   if (!viewer) {
    980:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch),&viewer);
    981:   }

    985:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    986:   if (iascii) {
    987:     PetscObjectPrintClassNamePrefixType((PetscObject)linesearch,viewer);
    988:     if (linesearch->ops->view) {
    989:       PetscViewerASCIIPushTab(viewer);
    990:       (*linesearch->ops->view)(linesearch,viewer);
    991:       PetscViewerASCIIPopTab(viewer);
    992:     }
    993:     PetscViewerASCIIPrintf(viewer,"  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol);
    994:     PetscViewerASCIIPrintf(viewer,"  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol);
    995:     PetscViewerASCIIPrintf(viewer,"  maximum iterations=%D\n", linesearch->max_its);
    996:     if (linesearch->ops->precheck) {
    997:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
    998:         PetscViewerASCIIPrintf(viewer,"  using precheck step to speed up Picard convergence\n", linesearch->max_its);
    999:       } else {
    1000:         PetscViewerASCIIPrintf(viewer,"  using user-defined precheck step\n", linesearch->max_its);
    1001:       }
    1002:     }
    1003:     if (linesearch->ops->postcheck) {
    1004:       PetscViewerASCIIPrintf(viewer,"  using user-defined postcheck step\n", linesearch->max_its);
    1005:     }
    1006:   }
    1007:   return(0);
    1008: }

    1012: /*@C
    1013:    SNESLineSearchSetType - Sets the linesearch type

    1015:    Logically Collective on SNESLineSearch

    1017:    Input Parameters:
    1018: +  linesearch - linesearch context
    1019: -  type - The type of line search to be used

    1021:    Available Types:
    1022: +  basic - Simple damping line search.
    1023: .  bt - Backtracking line search over the L2 norm of the function
    1024: .  l2 - Secant line search over the L2 norm of the function
    1025: .  cp - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
    1026: .  nleqerr - Affine-covariant error-oriented linesearch
    1027: -  shell - User provided SNESLineSearch implementation

    1029:    Level: intermediate

    1031: .seealso: SNESLineSearchCreate()
    1032: @*/
    1033: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
    1034: {
    1035:   PetscErrorCode ierr,(*r)(SNESLineSearch);
    1036:   PetscBool      match;

    1042:   PetscObjectTypeCompare((PetscObject)linesearch,type,&match);
    1043:   if (match) return(0);

    1045:   PetscFunctionListFind(SNESLineSearchList,type,&r);
    1046:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type);
    1047:   /* Destroy the previous private linesearch context */
    1048:   if (linesearch->ops->destroy) {
    1049:     (*(linesearch)->ops->destroy)(linesearch);

    1051:     linesearch->ops->destroy = NULL;
    1052:   }
    1053:   /* Reinitialize function pointers in SNESLineSearchOps structure */
    1054:   linesearch->ops->apply          = 0;
    1055:   linesearch->ops->view           = 0;
    1056:   linesearch->ops->setfromoptions = 0;
    1057:   linesearch->ops->destroy        = 0;

    1059:   PetscObjectChangeTypeName((PetscObject)linesearch,type);
    1060:   (*r)(linesearch);
    1061:   return(0);
    1062: }

    1066: /*@
    1067:    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.

    1069:    Input Parameters:
    1070: +  linesearch - linesearch context
    1071: -  snes - The snes instance

    1073:    Level: developer

    1075:    Notes:
    1076:    This happens automatically when the line search is obtained/created with
    1077:    SNESGetLineSearch().  This routine is therefore mainly called within SNES
    1078:    implementations.

    1080:    Level: developer

    1082: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    1083: @*/
    1084: PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
    1085: {
    1089:   linesearch->snes = snes;
    1090:   return(0);
    1091: }

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

    1101:    Input Parameters:
    1102: .  linesearch - linesearch context

    1104:    Output Parameters:
    1105: .  snes - The snes instance

    1107:    Level: developer

    1109: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    1110: @*/
    1111: PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
    1112: {
    1116:   *snes = linesearch->snes;
    1117:   return(0);
    1118: }

    1122: /*@
    1123:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

    1125:    Input Parameters:
    1126: .  linesearch - linesearch context

    1128:    Output Parameters:
    1129: .  lambda - The last steplength computed during SNESLineSearchApply()

    1131:    Level: advanced

    1133:    Notes:
    1134:    This is useful in methods where the solver is ill-scaled and
    1135:    requires some adaptive notion of the difference in scale between the
    1136:    solution and the function.  For instance, SNESQN may be scaled by the
    1137:    line search lambda using the argument -snes_qn_scaling ls.

    1139: .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply()
    1140: @*/
    1141: PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
    1142: {
    1146:   *lambda = linesearch->lambda;
    1147:   return(0);
    1148: }

    1152: /*@
    1153:    SNESLineSearchSetLambda - Sets the linesearch steplength.

    1155:    Input Parameters:
    1156: +  linesearch - linesearch context
    1157: -  lambda - The last steplength.

    1159:    Notes:
    1160:    This routine is typically used within implementations of SNESLineSearchApply()
    1161:    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
    1162:    added in order to facilitate Quasi-Newton methods that use the previous steplength
    1163:    as an inner scaling parameter.

    1165:    Level: advanced

    1167: .seealso: SNESLineSearchGetLambda()
    1168: @*/
    1169: PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
    1170: {
    1173:   linesearch->lambda = lambda;
    1174:   return(0);
    1175: }

    1177: #undef  __FUNCT__
    1179: /*@
    1180:    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
    1181:    tolerances for the relative and absolute change in the function norm, the change
    1182:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
    1183:    and the maximum number of iterations the line search procedure may take.

    1185:    Input Parameters:
    1186: .  linesearch - linesearch context

    1188:    Output Parameters:
    1189: +  steptol - The minimum steplength
    1190: .  maxstep - The maximum steplength
    1191: .  rtol    - The relative tolerance for iterative line searches
    1192: .  atol    - The absolute tolerance for iterative line searches
    1193: .  ltol    - The change in lambda tolerance for iterative line searches
    1194: -  max_it  - The maximum number of iterations of the line search

    1196:    Level: intermediate

    1198:    Notes:
    1199:    Different line searches may implement these parameters slightly differently as
    1200:    the type requires.

    1202: .seealso: SNESLineSearchSetTolerances()
    1203: @*/
    1204: PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
    1205: {
    1208:   if (steptol) {
    1210:     *steptol = linesearch->steptol;
    1211:   }
    1212:   if (maxstep) {
    1214:     *maxstep = linesearch->maxstep;
    1215:   }
    1216:   if (rtol) {
    1218:     *rtol = linesearch->rtol;
    1219:   }
    1220:   if (atol) {
    1222:     *atol = linesearch->atol;
    1223:   }
    1224:   if (ltol) {
    1226:     *ltol = linesearch->ltol;
    1227:   }
    1228:   if (max_its) {
    1230:     *max_its = linesearch->max_its;
    1231:   }
    1232:   return(0);
    1233: }

    1235: #undef  __FUNCT__
    1237: /*@
    1238:    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
    1239:    tolerances for the relative and absolute change in the function norm, the change
    1240:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
    1241:    and the maximum number of iterations the line search procedure may take.

    1243:    Input Parameters:
    1244: +  linesearch - linesearch context
    1245: .  steptol - The minimum steplength
    1246: .  maxstep - The maximum steplength
    1247: .  rtol    - The relative tolerance for iterative line searches
    1248: .  atol    - The absolute tolerance for iterative line searches
    1249: .  ltol    - The change in lambda tolerance for iterative line searches
    1250: -  max_it  - The maximum number of iterations of the line search

    1252:    Notes:
    1253:    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
    1254:    place of an argument.

    1256:    Level: intermediate

    1258: .seealso: SNESLineSearchGetTolerances()
    1259: @*/
    1260: PetscErrorCode  SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
    1261: {

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

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

    1281:   if (rtol != PETSC_DEFAULT) {
    1282:     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);
    1283:     linesearch->rtol = rtol;
    1284:   }

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

    1291:   if (ltol != PETSC_DEFAULT) {
    1292:     if (ltol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Labmda tolerance %14.12e must be non-negative",(double)ltol);
    1293:     linesearch->ltol = ltol;
    1294:   }

    1296:   if (max_its != PETSC_DEFAULT) {
    1297:     if (max_its < 0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",max_its);
    1298:     linesearch->max_its = max_its;
    1299:   }
    1300:   return(0);
    1301: }

    1305: /*@
    1306:    SNESLineSearchGetDamping - Gets the line search damping parameter.

    1308:    Input Parameters:
    1309: .  linesearch - linesearch context

    1311:    Output Parameters:
    1312: .  damping - The damping parameter

    1314:    Level: advanced

    1316: .seealso: SNESLineSearchGetStepTolerance(), SNESQN
    1317: @*/

    1319: PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
    1320: {
    1324:   *damping = linesearch->damping;
    1325:   return(0);
    1326: }

    1330: /*@
    1331:    SNESLineSearchSetDamping - Sets the line search damping paramter.

    1333:    Input Parameters:
    1334: +  linesearch - linesearch context
    1335: -  damping - The damping parameter

    1337:    Options Database:
    1338: .   -snes_linesearch_damping
    1339:    Level: intermediate

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

    1348: .seealso: SNESLineSearchGetDamping()
    1349: @*/
    1350: PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
    1351: {
    1354:   linesearch->damping = damping;
    1355:   return(0);
    1356: }

    1360: /*@
    1361:    SNESLineSearchGetOrder - Gets the line search approximation order.

    1363:    Input Parameters:
    1364: .  linesearch - linesearch context

    1366:    Output Parameters:
    1367: .  order - The order

    1369:    Possible Values for order:
    1370: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1371: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1372: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1374:    Level: intermediate

    1376: .seealso: SNESLineSearchSetOrder()
    1377: @*/

    1379: PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
    1380: {
    1384:   *order = linesearch->order;
    1385:   return(0);
    1386: }

    1390: /*@
    1391:    SNESLineSearchSetOrder - Sets the line search damping paramter.

    1393:    Input Parameters:
    1394: .  linesearch - linesearch context
    1395: .  order - The damping parameter

    1397:    Level: intermediate

    1399:    Possible Values for order:
    1400: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1401: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1402: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1404:    Notes:
    1405:    Variable orders are supported by the following line searches:
    1406: +  bt - cubic and quadratic
    1407: -  cp - linear and quadratic

    1409: .seealso: SNESLineSearchGetOrder()
    1410: @*/
    1411: PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
    1412: {
    1415:   linesearch->order = order;
    1416:   return(0);
    1417: }

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

    1424:    Input Parameters:
    1425: .  linesearch - linesearch context

    1427:    Output Parameters:
    1428: +  xnorm - The norm of the current solution
    1429: .  fnorm - The norm of the current function
    1430: -  ynorm - The norm of the current update

    1432:    Notes:
    1433:    This function is mainly called from SNES implementations.

    1435:    Level: developer

    1437: .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs()
    1438: @*/
    1439: PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
    1440: {
    1443:   if (xnorm) *xnorm = linesearch->xnorm;
    1444:   if (fnorm) *fnorm = linesearch->fnorm;
    1445:   if (ynorm) *ynorm = linesearch->ynorm;
    1446:   return(0);
    1447: }

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

    1454:    Input Parameters:
    1455: +  linesearch - linesearch context
    1456: .  xnorm - The norm of the current solution
    1457: .  fnorm - The norm of the current function
    1458: -  ynorm - The norm of the current update

    1460:    Level: advanced

    1462: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1463: @*/
    1464: PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
    1465: {
    1468:   linesearch->xnorm = xnorm;
    1469:   linesearch->fnorm = fnorm;
    1470:   linesearch->ynorm = ynorm;
    1471:   return(0);
    1472: }

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

    1479:    Input Parameters:
    1480: .  linesearch - linesearch context

    1482:    Options Database Keys:
    1483: .   -snes_linesearch_norms - turn norm computation on or off

    1485:    Level: intermediate

    1487: .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms()
    1488: @*/
    1489: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
    1490: {
    1492:   SNES           snes;

    1495:   if (linesearch->norms) {
    1496:     if (linesearch->ops->vinorm) {
    1497:       SNESLineSearchGetSNES(linesearch, &snes);
    1498:       VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
    1499:       VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1500:       (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
    1501:     } else {
    1502:       VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm);
    1503:       VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm);
    1504:       VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1505:       VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm);
    1506:       VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm);
    1507:       VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm);
    1508:     }
    1509:   }
    1510:   return(0);
    1511: }

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

    1518:    Input Parameters:
    1519: +  linesearch  - linesearch context
    1520: -  flg  - indicates whether or not to compute norms

    1522:    Options Database Keys:
    1523: .   -snes_linesearch_norms - turn norm computation on or off

    1525:    Notes:
    1526:    This is most relevant to the SNESLINESEARCHBASIC line search type.

    1528:    Level: intermediate

    1530: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC
    1531: @*/
    1532: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
    1533: {
    1535:   linesearch->norms = flg;
    1536:   return(0);
    1537: }

    1541: /*@
    1542:    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context

    1544:    Input Parameters:
    1545: .  linesearch - linesearch context

    1547:    Output Parameters:
    1548: +  X - Solution vector
    1549: .  F - Function vector
    1550: .  Y - Search direction vector
    1551: .  W - Solution work vector
    1552: -  G - Function work vector

    1554:    Notes:
    1555:    At the beginning of a line search application, X should contain a
    1556:    solution and the vector F the function computed at X.  At the end of the
    1557:    line search application, X should contain the new solution, and F the
    1558:    function evaluated at the new solution.

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

    1562:    Level: advanced

    1564: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1565: @*/
    1566: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
    1567: {
    1570:   if (X) {
    1572:     *X = linesearch->vec_sol;
    1573:   }
    1574:   if (F) {
    1576:     *F = linesearch->vec_func;
    1577:   }
    1578:   if (Y) {
    1580:     *Y = linesearch->vec_update;
    1581:   }
    1582:   if (W) {
    1584:     *W = linesearch->vec_sol_new;
    1585:   }
    1586:   if (G) {
    1588:     *G = linesearch->vec_func_new;
    1589:   }
    1590:   return(0);
    1591: }

    1595: /*@
    1596:    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context

    1598:    Input Parameters:
    1599: +  linesearch - linesearch context
    1600: .  X - Solution vector
    1601: .  F - Function vector
    1602: .  Y - Search direction vector
    1603: .  W - Solution work vector
    1604: -  G - Function work vector

    1606:    Level: advanced

    1608: .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs()
    1609: @*/
    1610: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
    1611: {
    1614:   if (X) {
    1616:     linesearch->vec_sol = X;
    1617:   }
    1618:   if (F) {
    1620:     linesearch->vec_func = F;
    1621:   }
    1622:   if (Y) {
    1624:     linesearch->vec_update = Y;
    1625:   }
    1626:   if (W) {
    1628:     linesearch->vec_sol_new = W;
    1629:   }
    1630:   if (G) {
    1632:     linesearch->vec_func_new = G;
    1633:   }
    1634:   return(0);
    1635: }

    1639: /*@C
    1640:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
    1641:    SNES options in the database.

    1643:    Logically Collective on SNESLineSearch

    1645:    Input Parameters:
    1646: +  snes - the SNES context
    1647: -  prefix - the prefix to prepend to all option names

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

    1653:    Level: advanced

    1655: .keywords: SNESLineSearch, append, options, prefix, database

    1657: .seealso: SNESGetOptionsPrefix()
    1658: @*/
    1659: PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
    1660: {

    1665:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);
    1666:   return(0);
    1667: }

    1671: /*@C
    1672:    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
    1673:    SNESLineSearch options in the database.

    1675:    Not Collective

    1677:    Input Parameter:
    1678: .  linesearch - the SNESLineSearch context

    1680:    Output Parameter:
    1681: .  prefix - pointer to the prefix string used

    1683:    Notes:
    1684:    On the fortran side, the user should pass in a string 'prefix' of
    1685:    sufficient length to hold the prefix.

    1687:    Level: advanced

    1689: .keywords: SNESLineSearch, get, options, prefix, database

    1691: .seealso: SNESAppendOptionsPrefix()
    1692: @*/
    1693: PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
    1694: {

    1699:   PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);
    1700:   return(0);
    1701: }

    1705: /*@C
    1706:    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.

    1708:    Input Parameter:
    1709: +  linesearch - the SNESLineSearch context
    1710: -  nwork - the number of work vectors

    1712:    Level: developer

    1714:    Developers Note: This is PETSC_EXTERN because it may be used by user written plugin SNES implementations

    1716: .keywords: SNESLineSearch, work, vector

    1718: .seealso: SNESSetWorkVecs()
    1719: @*/
    1720: PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
    1721: {

    1725:   if (linesearch->vec_sol) {
    1726:     VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
    1727:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
    1728:   return(0);
    1729: }

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

    1736:    Input Parameters:
    1737: .  linesearch - linesearch context

    1739:    Output Parameters:
    1740: .  result - The success or failure status

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

    1746:    Level: intermediate

    1748: .seealso: SNESLineSearchSetReason(), SNESLineSearchReason
    1749: @*/
    1750: PetscErrorCode  SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
    1751: {
    1755:   *result = linesearch->result;
    1756:   return(0);
    1757: }

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

    1764:    Input Parameters:
    1765: +  linesearch - linesearch context
    1766: -  result - The success or failure status

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

    1772:    Level: developer

    1774: .seealso: SNESLineSearchGetSResult()
    1775: @*/
    1776: PetscErrorCode  SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
    1777: {
    1780:   linesearch->result = result;
    1781:   return(0);
    1782: }

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

    1789:    Input Parameters:
    1790: +  snes - nonlinear context obtained from SNESCreate()
    1791: .  projectfunc - function for projecting the function to the bounds
    1792: -  normfunc - function for computing the norm of an active set

    1794:    Logically Collective on SNES

    1796:    Calling sequence of projectfunc:
    1797: .vb
    1798:    projectfunc (SNES snes, Vec X)
    1799: .ve

    1801:     Input parameters for projectfunc:
    1802: +   snes - nonlinear context
    1803: -   X - current solution

    1805:     Output parameters for projectfunc:
    1806: .   X - Projected solution

    1808:    Calling sequence of normfunc:
    1809: .vb
    1810:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
    1811: .ve

    1813:     Input parameters for normfunc:
    1814: +   snes - nonlinear context
    1815: .   X - current solution
    1816: -   F - current residual

    1818:     Output parameters for normfunc:
    1819: .   fnorm - VI-specific norm of the function

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

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

    1827:     Level: developer

    1829: .keywords: SNES, line search, VI, nonlinear, set, line search

    1831: .seealso: SNESLineSearchGetVIFunctions(), SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck()
    1832: @*/
    1833: extern PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
    1834: {
    1837:   if (projectfunc) linesearch->ops->viproject = projectfunc;
    1838:   if (normfunc) linesearch->ops->vinorm = normfunc;
    1839:   return(0);
    1840: }

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

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

    1850:    Output Parameters:
    1851: +  projectfunc - function for projecting the function to the bounds
    1852: -  normfunc - function for computing the norm of an active set

    1854:    Logically Collective on SNES

    1856:     Level: developer

    1858: .keywords: SNES, line search, VI, nonlinear, get, line search

    1860: .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
    1861: @*/
    1862: extern PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
    1863: {
    1865:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
    1866:   if (normfunc) *normfunc = linesearch->ops->vinorm;
    1867:   return(0);
    1868: }

    1872: /*@C
    1873:   SNESLineSearchRegister - See SNESLineSearchRegister()

    1875:   Level: advanced
    1876: @*/
    1877: PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
    1878: {

    1882:   PetscFunctionListAdd(&SNESLineSearchList,sname,function);
    1883:   return(0);
    1884: }