Date: 2013-07-02T14:50:47+00:00

Actual source code: linesearch.c
petsc-3.4.2 2013-07-02

      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:    SNESLineSearchCreate - Creates the line search context.

     14:    Logically Collective on Comm

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

     19:    Output Parameters:
     20: .  outlinesearch - the new linesearch context

     22:    Level: beginner

     24: .keywords: LineSearch, create, context

     26: .seealso: LineSearchDestroy()
     27: @*/

     29: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
     30: {
     32:   SNESLineSearch linesearch;

     36:   *outlinesearch = NULL;

     38:   PetscHeaderCreate(linesearch,_p_LineSearch,struct _LineSearchOps,SNESLINESEARCH_CLASSID, "SNESLineSearch","Linesearch","SNESLineSearch",comm,SNESLineSearchDestroy,SNESLineSearchView);

     40:   linesearch->ops->precheck  = NULL;
     41:   linesearch->ops->postcheck = NULL;

     43:   linesearch->vec_sol_new  = NULL;
     44:   linesearch->vec_func_new = NULL;
     45:   linesearch->vec_sol      = NULL;
     46:   linesearch->vec_func     = NULL;
     47:   linesearch->vec_update   = NULL;

     49:   linesearch->lambda       = 1.0;
     50:   linesearch->fnorm        = 1.0;
     51:   linesearch->ynorm        = 1.0;
     52:   linesearch->xnorm        = 1.0;
     53:   linesearch->success      = PETSC_TRUE;
     54:   linesearch->norms        = PETSC_TRUE;
     55:   linesearch->keeplambda   = PETSC_FALSE;
     56:   linesearch->damping      = 1.0;
     57:   linesearch->maxstep      = 1e8;
     58:   linesearch->steptol      = 1e-12;
     59:   linesearch->rtol         = 1e-8;
     60:   linesearch->atol         = 1e-15;
     61:   linesearch->ltol         = 1e-8;
     62:   linesearch->precheckctx  = NULL;
     63:   linesearch->postcheckctx = NULL;
     64:   linesearch->max_its      = 1;
     65:   linesearch->setupcalled  = PETSC_FALSE;
     66:   *outlinesearch           = linesearch;
     67:   return(0);
     68: }

     72: /*@
     73:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
     74:    any required vectors.

     76:    Collective on SNESLineSearch

     78:    Input Parameters:
     79: .  linesearch - The LineSearch instance.

     81:    Notes:
     82:    For most cases, this needn't be called outside of SNESLineSearchApply().
     83:    The only current case where this is called outside of this is for the VI
     84:    solvers, which modify the solution and work vectors before the first call
     85:    of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be
     86:    allocated upfront.

     88:    Level: advanced

     90: .keywords: SNESLineSearch, SetUp

     92: .seealso: SNESLineSearchReset()
     93: @*/

     95: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
     96: {

    100:   if (!((PetscObject)linesearch)->type_name) {
    101:     SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);
    102:   }
    103:   if (!linesearch->setupcalled) {
    104:     if (!linesearch->vec_sol_new) {
    105:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
    106:     }
    107:     if (!linesearch->vec_func_new) {
    108:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
    109:     }
    110:     if (linesearch->ops->setup) {
    111:       (*linesearch->ops->setup)(linesearch);
    112:     }
    113:     linesearch->lambda      = linesearch->damping;
    114:     linesearch->setupcalled = PETSC_TRUE;
    115:   }
    116:   return(0);
    117: }

    122: /*@
    123:    SNESLineSearchReset - Undoes the SetUp and deletes any Vecs or Mats allocated by the line search.

    125:    Collective on SNESLineSearch

    127:    Input Parameters:
    128: .  linesearch - The LineSearch instance.

    130:    Level: intermediate

    132: .keywords: SNESLineSearch, Reset

    134: .seealso: SNESLineSearchSetUp()
    135: @*/

    137: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
    138: {

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

    144:   VecDestroy(&linesearch->vec_sol_new);
    145:   VecDestroy(&linesearch->vec_func_new);

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

    149:   linesearch->nwork       = 0;
    150:   linesearch->setupcalled = PETSC_FALSE;
    151:   return(0);
    152: }

    154: /*MC
    155:     SNESLineSearchPreCheckFunction - functional form passed to check before line search is called

    157:      Synopsis:
    158:      #include "petscsnes.h"
    159:      SNESLineSearchPreCheckFunction(SNESLineSearch snes,Vec x,Vec y, PetscBool *changed);

    161:        Input Parameters:
    162: +      x - solution vector
    163: .      y - search direction vector
    164: -      changed - flag to indicate the precheck changed x or y.

    166:    Level: advanced

    168: .seealso:   SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck()
    169: M*/

    173: /*@C
    174:    SNESLineSearchSetPreCheck - Sets a pre-check function for the line search routine.

    176:    Logically Collective on SNESLineSearch

    178:    Input Parameters:
    179: +  linesearch - the SNESLineSearch context
    180: .  SNESLineSearchPreCheckFunction - [optional] function evaluation routine
    181: -  ctx        - [optional] user-defined context for private data for the
    182:                 function evaluation routine (may be NULL)

    185:    Level: intermediate

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

    189: .seealso: SNESLineSearchSetPostCheck()
    190: @*/
    191: PetscErrorCode  SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*SNESLineSearchPreCheckFunction)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void *ctx)
    192: {
    195:   if (SNESLineSearchPreCheckFunction) linesearch->ops->precheck = SNESLineSearchPreCheckFunction;
    196:   if (ctx) linesearch->precheckctx = ctx;
    197:   return(0);
    198: }

    202: /*@C
    203:    SNESLineSearchSetPreCheck - Gets the pre-check function for the line search routine.

    205:    Input Parameters:
    206: .  linesearch - the SNESLineSearch context

    208:    Output Parameters:
    209: +  func       - [optional] function evaluation routine
    210: -  ctx        - [optional] user-defined context for private data for the
    211:                 function evaluation routine (may be NULL)

    213:    Level: intermediate

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

    217: .seealso: SNESLineSearchGetPostCheck(), SNESLineSearchSetPreCheck()
    218: @*/
    219: PetscErrorCode  SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**SNESLineSearchPreCheckFunction)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void **ctx)
    220: {
    223:   if (SNESLineSearchPreCheckFunction) *SNESLineSearchPreCheckFunction = linesearch->ops->precheck;
    224:   if (ctx) *ctx = linesearch->precheckctx;
    225:   return(0);
    226: }

    228: /*MC
    229:     SNESLineSearchPostheckFunction - functional form that is called after line search is complete

    231:      Synopsis:
    232:      #include "petscsnes.h"
    233:      SNESLineSearchPostheckFunction(SNESLineSearch linesearch,Vec x,Vec y,  Vec w, *changed_y, PetscBool *changed_w);

    235:      Input Parameters:
    236: +      x - old solution vector
    237: .      y - search direction vector
    238: .      w - new solution vector
    239: .      changed_y - indicates that the line search changed y
    240: -      changed_w - indicates that the line search changed w

    242:    Level: advanced

    244: .seealso:   SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck()
    245: M*/

    249: /*@C
    250:    SNESLineSearchSetPostCheck - Sets a post-check function for the line search routine.

    252:    Logically Collective on SNESLineSearch

    254:    Input Parameters:
    255: +  linesearch - the SNESLineSearch context
    256: .  SNESLineSearchPostCheckFunction - [optional] function evaluation routine
    257: -  ctx        - [optional] user-defined context for private data for the
    258:                 function evaluation routine (may be NULL)

    260:    Level: intermediate

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

    264: .seealso: SNESLineSearchSetPreCheck()
    265: @*/
    266: PetscErrorCode  SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*SNESLineSearchPostCheckFunction)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx)
    267: {
    270:   if (SNESLineSearchPostCheckFunction) linesearch->ops->postcheck = SNESLineSearchPostCheckFunction;
    271:   if (ctx) linesearch->postcheckctx = ctx;
    272:   return(0);
    273: }

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

    280:    Input Parameters:
    281: .  linesearch - the SNESLineSearch context

    283:    Output Parameters:
    284: +  SNESLineSearchPostCheckFunction - [optional] function evaluation routine
    285: -  ctx        - [optional] user-defined context for private data for the
    286:                 function evaluation routine (may be NULL)

    288:    Level: intermediate

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

    292: .seealso: SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck()
    293: @*/
    294: PetscErrorCode  SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**SNESLineSearchPostCheckFunction)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void **ctx)
    295: {
    298:   if (SNESLineSearchPostCheckFunction) *SNESLineSearchPostCheckFunction = linesearch->ops->postcheck;
    299:   if (ctx) *ctx = linesearch->postcheckctx;
    300:   return(0);
    301: }

    305: /*@
    306:    SNESLineSearchPreCheck - Prepares the line search for being applied.

    308:    Logically Collective on SNESLineSearch

    310:    Input Parameters:
    311: +  linesearch - The linesearch instance.
    312: .  X - The current solution
    313: -  Y - The step direction

    315:    Output Parameters:
    316: .  changed - Indicator that the precheck routine has changed anything

    318:    Level: Beginner

    320: .keywords: SNESLineSearch, Create

    322: .seealso: SNESLineSearchPostCheck()
    323: @*/
    324: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed)
    325: {

    329:   *changed = PETSC_FALSE;
    330:   if (linesearch->ops->precheck) {
    331:     (*linesearch->ops->precheck)(linesearch, X, Y, changed, linesearch->precheckctx);
    333:   }
    334:   return(0);
    335: }

    339: /*@
    340:    SNESLineSearchPostCheck - Prepares the line search for being applied.

    342:    Logically Collective on SNESLineSearch

    344:    Input Parameters:
    345: +  linesearch - The linesearch context
    346: .  X - The last solution
    347: .  Y - The step direction
    348: -  W - The updated solution, W = X + lambda*Y for some lambda

    350:    Output Parameters:
    351: +  changed_Y - Indicator if the direction Y has been changed.
    352: -  changed_W - Indicator if the new candidate solution W has been changed.

    354:    Level: Intermediate

    356: .keywords: SNESLineSearch, Create

    358: .seealso: SNESLineSearchPreCheck()
    359: @*/
    360: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W)
    361: {

    365:   *changed_Y = PETSC_FALSE;
    366:   *changed_W = PETSC_FALSE;
    367:   if (linesearch->ops->postcheck) {
    368:     (*linesearch->ops->postcheck)(linesearch,X,Y,W,changed_Y,changed_W,linesearch->postcheckctx);
    371:   }
    372:   return(0);
    373: }

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

    380:    Logically Collective on SNESLineSearch

    382:    Input Arguments:
    383: +  linesearch - linesearch context
    384: .  X - base state for this step
    385: .  Y - initial correction

    387:    Output Arguments:
    388: +  Y - correction, possibly modified
    389: -  changed - flag indicating that Y was modified

    391:    Options Database Key:
    392: +  -snes_linesearch_precheck_picard - activate this routine
    393: -  -snes_linesearch_precheck_picard_angle - angle

    395:    Level: advanced

    397:    Notes:
    398:    This function should be passed to SNESLineSearchSetPreCheck()

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

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

    407: .seealso: SNESLineSearchSetPreCheck()
    408: @*/
    409: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed,void *ctx)
    410: {
    412:   PetscReal      angle = *(PetscReal*)linesearch->precheckctx;
    413:   Vec            Ylast;
    414:   PetscScalar    dot;
    415:   PetscInt       iter;
    416:   PetscReal      ynorm,ylastnorm,theta,angle_radians;
    417:   SNES           snes;

    420:   SNESLineSearchGetSNES(linesearch, &snes);
    421:   PetscObjectQuery((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject*)&Ylast);
    422:   if (!Ylast) {
    423:     VecDuplicate(Y,&Ylast);
    424:     PetscObjectCompose((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject)Ylast);
    425:     PetscObjectDereference((PetscObject)Ylast);
    426:   }
    427:   SNESGetIterationNumber(snes,&iter);
    428:   if (iter < 2) {
    429:     VecCopy(Y,Ylast);
    430:     *changed = PETSC_FALSE;
    431:     return(0);
    432:   }

    434:   VecDot(Y,Ylast,&dot);
    435:   VecNorm(Y,NORM_2,&ynorm);
    436:   VecNorm(Ylast,NORM_2,&ylastnorm);
    437:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
    438:   theta         = acos((double)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm),-1.0,1.0));
    439:   angle_radians = angle * PETSC_PI / 180.;
    440:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
    441:     /* Modify the step Y */
    442:     PetscReal alpha,ydiffnorm;
    443:     VecAXPY(Ylast,-1.0,Y);
    444:     VecNorm(Ylast,NORM_2,&ydiffnorm);
    445:     alpha = ylastnorm / ydiffnorm;
    446:     VecCopy(Y,Ylast);
    447:     VecScale(Y,alpha);
    448:     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);
    449:   } else {
    450:     PetscInfo2(snes,"Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n",(double)(theta*180./PETSC_PI),(double)angle);
    451:     VecCopy(Y,Ylast);
    452:     *changed = PETSC_FALSE;
    453:   }
    454:   return(0);
    455: }

    459: /*@
    460:    SNESLineSearchApply - Computes the line-search update.

    462:    Collective on SNESLineSearch

    464:    Input Parameters:
    465: +  linesearch - The linesearch context
    466: .  X - The current solution
    467: .  F - The current function
    468: .  fnorm - The current norm
    469: -  Y - The search direction

    471:    Output Parameters:
    472: +  X - The new solution
    473: .  F - The new function
    474: -  fnorm - The new function norm

    476:    Options Database Keys:
    477: + -snes_linesearch_type - basic, bt, l2, cp, shell
    478: . -snes_linesearch_monitor - Print progress of line searches
    479: . -snes_linesearch_damping - The linesearch damping parameter
    480: . -snes_linesearch_norms   - Turn on/off the linesearch norms
    481: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
    482: - -snes_linesearch_max_it - The number of iterations for iterative line searches

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

    492:    Level: Intermediate

    494: .keywords: SNESLineSearch, Create

    496: .seealso: SNESLineSearchCreate(), SNESLineSearchPreCheck(), SNESLineSearchPostCheck(), SNESSolve(), SNESComputeFunction()
    497: @*/
    498: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y)
    499: {

    508:   linesearch->success = PETSC_TRUE;

    510:   linesearch->vec_sol    = X;
    511:   linesearch->vec_update = Y;
    512:   linesearch->vec_func   = F;

    514:   SNESLineSearchSetUp(linesearch);

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

    518:   if (fnorm) linesearch->fnorm = *fnorm;
    519:   else {
    520:     VecNorm(F, NORM_2, &linesearch->fnorm);
    521:   }

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

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

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

    529:   if (fnorm) *fnorm = linesearch->fnorm;
    530:   return(0);
    531: }

    535: /*@
    536:    SNESLineSearchDestroy - Destroys the line search instance.

    538:    Collective on SNESLineSearch

    540:    Input Parameters:
    541: .  linesearch - The linesearch context

    543:    Level: Intermediate

    545: .keywords: SNESLineSearch, Destroy

    547: .seealso: SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy()
    548: @*/
    549: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch)
    550: {

    554:   if (!*linesearch) return(0);
    556:   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = 0; return(0);}
    557:   PetscObjectAMSViewOff((PetscObject)*linesearch);
    558:   SNESLineSearchReset(*linesearch);
    559:   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
    560:   PetscViewerDestroy(&(*linesearch)->monitor);
    561:   PetscHeaderDestroy(linesearch);
    562:   return(0);
    563: }

    567: /*@
    568:    SNESLineSearchSetMonitor - Turns on/off printing useful information and debugging output about the line search.

    570:    Input Parameters:
    571: +  snes - nonlinear context obtained from SNESCreate()
    572: -  flg - PETSC_TRUE to monitor the line search

    574:    Logically Collective on SNES

    576:    Options Database:
    577: .   -snes_linesearch_monitor - enables the monitor

    579:    Level: intermediate

    582: .seealso: SNESLineSearchGetMonitor(), PetscViewer
    583: @*/
    584: PetscErrorCode  SNESLineSearchSetMonitor(SNESLineSearch linesearch, PetscBool flg)
    585: {

    589:   if (flg && !linesearch->monitor) {
    590:     PetscViewerASCIIOpen(PetscObjectComm((PetscObject)linesearch),"stdout",&linesearch->monitor);
    591:   } else if (!flg && linesearch->monitor) {
    592:     PetscViewerDestroy(&linesearch->monitor);
    593:   }
    594:   return(0);
    595: }

    599: /*@
    600:    SNESLineSearchGetMonitor - Gets the PetscViewer instance for the line search monitor.

    602:    Input Parameters:
    603: .  linesearch - linesearch context

    605:    Input Parameters:
    606: .  monitor - monitor context

    608:    Logically Collective on SNES

    611:    Options Database Keys:
    612: .   -snes_linesearch_monitor - enables the monitor

    614:    Level: intermediate

    617: .seealso: SNESLineSearchSetMonitor(), PetscViewer
    618: @*/
    619: PetscErrorCode  SNESLineSearchGetMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
    620: {
    623:   if (monitor) {
    625:     *monitor = linesearch->monitor;
    626:   }
    627:   return(0);
    628: }

    632: /*@
    633:    SNESLineSearchSetFromOptions - Sets options for the line search

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

    638:    Options Database Keys:
    639: + -snes_linesearch_type <type> - basic, bt, l2, cp, shell
    640: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
    641: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch type
    642: . -snes_linesearch_minlambda - The minimum step length
    643: . -snes_linesearch_maxstep - The maximum step size
    644: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
    645: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
    646: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
    647: . -snes_linesearch_max_it - The number of iterations for iterative line searches
    648: . -snes_linesearch_monitor - Print progress of line searches
    649: . -snes_linesearch_damping - The linesearch damping parameter
    650: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
    651: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
    652: - -snes_linesearch_precheck_picard_angle - Angle used in picard precheck method

    654:    Logically Collective on SNESLineSearch

    656:    Level: intermediate

    658: .seealso: SNESLineSearchCreate(), SNESLineSearchSetOrder(), SNESLineSearchSetType(), SNESLineSearchSetTolerances(), SNESLineSearchSetDamping(), SNESLineSearchPreCheckPicard()
    659: @*/
    660: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
    661: {
    663:   const char     *deft = SNESLINESEARCHBASIC;
    664:   char           type[256];
    665:   PetscBool      flg, set;

    668:   if (!SNESLineSearchRegisterAllCalled) {SNESLineSearchRegisterAll();}

    670:   PetscObjectOptionsBegin((PetscObject)linesearch);
    671:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
    672:   PetscOptionsList("-snes_linesearch_type","Linesearch type","SNESLineSearchSetType",SNESLineSearchList,deft,type,256,&flg);
    673:   if (flg) {
    674:     SNESLineSearchSetType(linesearch,type);
    675:   } else if (!((PetscObject)linesearch)->type_name) {
    676:     SNESLineSearchSetType(linesearch,deft);
    677:   }

    679:   PetscOptionsBool("-snes_linesearch_monitor","Print progress of line searches","SNESSNESLineSearchSetMonitor",
    680:                           linesearch->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);
    681:   if (set) {SNESLineSearchSetMonitor(linesearch,flg);}

    683:   /* tolerances */
    684:   PetscOptionsReal("-snes_linesearch_minlambda","Minimum step length","SNESLineSearchSetTolerances",linesearch->steptol,&linesearch->steptol,0);
    685:   PetscOptionsReal("-snes_linesearch_maxstep","Maximum step size","SNESLineSearchSetTolerances",linesearch->maxstep,&linesearch->maxstep,0);
    686:   PetscOptionsReal("-snes_linesearch_rtol","Relative tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->rtol,&linesearch->rtol,0);
    687:   PetscOptionsReal("-snes_linesearch_atol","Absolute tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->atol,&linesearch->atol,0);
    688:   PetscOptionsReal("-snes_linesearch_ltol","Change in lambda tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->ltol,&linesearch->ltol,0);
    689:   PetscOptionsInt("-snes_linesearch_max_it","Maximum iterations for iterative line searches","SNESLineSearchSetTolerances",linesearch->max_its,&linesearch->max_its,0);

    691:   /* damping parameters */
    692:   PetscOptionsReal("-snes_linesearch_damping","Line search damping and initial step guess","SNESLineSearchSetDamping",linesearch->damping,&linesearch->damping,0);

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

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

    702:       PetscOptionsReal("-snes_linesearch_precheck_picard_angle","Maximum angle at which to activate the correction",
    703:                               "none",linesearch->precheck_picard_angle,&linesearch->precheck_picard_angle,NULL);
    704:       SNESLineSearchSetPreCheck(linesearch,SNESLineSearchPreCheckPicard,&linesearch->precheck_picard_angle);
    705:     } else {
    706:       SNESLineSearchSetPreCheck(linesearch,NULL,NULL);
    707:     }
    708:   }
    709:   PetscOptionsInt("-snes_linesearch_order","Order of approximation used in the line search","SNESLineSearchSetOrder",linesearch->order,&linesearch->order,0);
    710:   PetscOptionsBool("-snes_linesearch_norms","Compute final norms in line search","SNESLineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,0);

    712:   if (linesearch->ops->setfromoptions) {
    713:     (*linesearch->ops->setfromoptions)(linesearch);
    714:   }

    716:   PetscObjectProcessOptionsHandlers((PetscObject)linesearch);
    717:   PetscOptionsEnd();
    718:   return(0);
    719: }

    723: /*@
    724:    SNESLineSearchView - Prints useful information about the line search not
    725:    related to an individual call.

    727:    Input Parameters:
    728: .  linesearch - linesearch context

    730:    Logically Collective on SNESLineSearch

    732:    Level: intermediate

    734: .seealso: SNESLineSearchCreate()
    735: @*/
    736: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
    737: {
    739:   PetscBool      iascii;

    743:   if (!viewer) {
    744:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch),&viewer);
    745:   }

    749:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    750:   if (iascii) {
    751:     PetscObjectPrintClassNamePrefixType((PetscObject)linesearch,viewer,"SNESLineSearch Object");
    752:     if (linesearch->ops->view) {
    753:       PetscViewerASCIIPushTab(viewer);
    754:       (*linesearch->ops->view)(linesearch,viewer);
    755:       PetscViewerASCIIPopTab(viewer);
    756:     }
    757:     PetscViewerASCIIPrintf(viewer,"  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol);
    758:     PetscViewerASCIIPrintf(viewer,"  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol);
    759:     PetscViewerASCIIPrintf(viewer,"  maximum iterations=%D\n", linesearch->max_its);
    760:     if (linesearch->ops->precheck) {
    761:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
    762:         PetscViewerASCIIPrintf(viewer,"  using precheck step to speed up Picard convergence\n", linesearch->max_its);
    763:       } else {
    764:         PetscViewerASCIIPrintf(viewer,"  using user-defined precheck step\n", linesearch->max_its);
    765:       }
    766:     }
    767:     if (linesearch->ops->postcheck) {
    768:       PetscViewerASCIIPrintf(viewer,"  using user-defined postcheck step\n", linesearch->max_its);
    769:     }
    770:   }
    771:   return(0);
    772: }

    776: /*@C
    777:    SNESLineSearchSetType - Sets the linesearch type

    779:    Input Parameters:
    780: +  linesearch - linesearch context
    781: -  type - The type of line search to be used

    783:    Available Types:
    784: +  basic - Simple damping line search.
    785: .  bt - Backtracking line search over the L2 norm of the function
    786: .  l2 - Secant line search over the L2 norm of the function
    787: .  cp - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
    788: -  shell - User provided SNESLineSearch implementation

    790:    Logically Collective on SNESLineSearch

    792:    Level: intermediate

    795: .seealso: SNESLineSearchCreate()
    796: @*/
    797: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
    798: {
    799:   PetscErrorCode ierr,(*r)(SNESLineSearch);
    800:   PetscBool      match;

    806:   PetscObjectTypeCompare((PetscObject)linesearch,type,&match);
    807:   if (match) return(0);

    809:   PetscFunctionListFind(SNESLineSearchList,type,&r);
    810:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type);
    811:   /* Destroy the previous private linesearch context */
    812:   if (linesearch->ops->destroy) {
    813:     (*(linesearch)->ops->destroy)(linesearch);

    815:     linesearch->ops->destroy = NULL;
    816:   }
    817:   /* Reinitialize function pointers in SNESLineSearchOps structure */
    818:   linesearch->ops->apply          = 0;
    819:   linesearch->ops->view           = 0;
    820:   linesearch->ops->setfromoptions = 0;
    821:   linesearch->ops->destroy        = 0;

    823:   PetscObjectChangeTypeName((PetscObject)linesearch,type);
    824:   (*r)(linesearch);
    825:   return(0);
    826: }

    830: /*@
    831:    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.

    833:    Input Parameters:
    834: +  linesearch - linesearch context
    835: -  snes - The snes instance

    837:    Level: developer

    839:    Notes:
    840:    This happens automatically when the line search is gotten/created with
    841:    SNESGetLineSearch().  This routine is therefore mainly called within SNES
    842:    implementations.

    844:    Level: developer

    846: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    847: @*/
    848: PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
    849: {
    853:   linesearch->snes = snes;
    854:   return(0);
    855: }

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

    865:    Input Parameters:
    866: .  linesearch - linesearch context

    868:    Output Parameters:
    869: .  snes - The snes instance

    871:    Level: developer

    873: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
    874: @*/
    875: PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
    876: {
    880:   *snes = linesearch->snes;
    881:   return(0);
    882: }

    886: /*@
    887:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

    889:    Input Parameters:
    890: .  linesearch - linesearch context

    892:    Output Parameters:
    893: .  lambda - The last steplength computed during SNESLineSearchApply()

    895:    Level: advanced

    897:    Notes:
    898:    This is useful in methods where the solver is ill-scaled and
    899:    requires some adaptive notion of the difference in scale between the
    900:    solution and the function.  For instance, SNESQN may be scaled by the
    901:    line search lambda using the argument -snes_qn_scaling ls.

    904: .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply()
    905: @*/
    906: PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
    907: {
    911:   *lambda = linesearch->lambda;
    912:   return(0);
    913: }

    917: /*@
    918:    SNESLineSearchSetLambda - Sets the linesearch steplength.

    920:    Input Parameters:
    921: +  linesearch - linesearch context
    922: -  lambda - The last steplength.

    924:    Notes:
    925:    This routine is typically used within implementations of SNESLineSearchApply
    926:    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
    927:    added in order to facilitate Quasi-Newton methods that use the previous steplength
    928:    as an inner scaling parameter.

    930:    Level: advanced

    932: .seealso: SNESLineSearchGetLambda()
    933: @*/
    934: PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
    935: {
    938:   linesearch->lambda = lambda;
    939:   return(0);
    940: }

    942: #undef  __FUNCT__
    944: /*@
    945:    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
    946:    tolerances for the relative and absolute change in the function norm, the change
    947:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
    948:    and the maximum number of iterations the line search procedure may take.

    950:    Input Parameters:
    951: .  linesearch - linesearch context

    953:    Output Parameters:
    954: +  steptol - The minimum steplength
    955: .  maxstep - The maximum steplength
    956: .  rtol    - The relative tolerance for iterative line searches
    957: .  atol    - The absolute tolerance for iterative line searches
    958: .  ltol    - The change in lambda tolerance for iterative line searches
    959: -  max_it  - The maximum number of iterations of the line search

    961:    Level: intermediate

    963:    Notes:
    964:    Different line searches may implement these parameters slightly differently as
    965:    the type requires.

    967: .seealso: SNESLineSearchSetTolerances()
    968: @*/
    969: PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
    970: {
    973:   if (steptol) {
    975:     *steptol = linesearch->steptol;
    976:   }
    977:   if (maxstep) {
    979:     *maxstep = linesearch->maxstep;
    980:   }
    981:   if (rtol) {
    983:     *rtol = linesearch->rtol;
    984:   }
    985:   if (atol) {
    987:     *atol = linesearch->atol;
    988:   }
    989:   if (ltol) {
    991:     *ltol = linesearch->ltol;
    992:   }
    993:   if (max_its) {
    995:     *max_its = linesearch->max_its;
    996:   }
    997:   return(0);
    998: }

    1000: #undef  __FUNCT__
    1002: /*@
    1003:    SNESLineSearchSetTolerances -  Gets the tolerances for the linesearch.  These include
    1004:    tolerances for the relative and absolute change in the function norm, the change
    1005:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
    1006:    and the maximum number of iterations the line search procedure may take.

    1008:    Input Parameters:
    1009: +  linesearch - linesearch context
    1010: .  steptol - The minimum steplength
    1011: .  maxstep - The maximum steplength
    1012: .  rtol    - The relative tolerance for iterative line searches
    1013: .  atol    - The absolute tolerance for iterative line searches
    1014: .  ltol    - The change in lambda tolerance for iterative line searches
    1015: -  max_it  - The maximum number of iterations of the line search

    1017:    Notes:
    1018:    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
    1019:    place of an argument.

    1021:    Level: intermediate

    1023: .seealso: SNESLineSearchGetTolerances()
    1024: @*/
    1025: PetscErrorCode  SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
    1026: {

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

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

    1046:   if (rtol != PETSC_DEFAULT) {
    1047:     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);
    1048:     linesearch->rtol = rtol;
    1049:   }

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

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

    1061:   if (max_its != PETSC_DEFAULT) {
    1062:     if (max_its < 0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",max_its);
    1063:     linesearch->max_its = max_its;
    1064:   }
    1065:   return(0);
    1066: }

    1070: /*@
    1071:    SNESLineSearchGetDamping - Gets the line search damping parameter.

    1073:    Input Parameters:
    1074: .  linesearch - linesearch context

    1076:    Output Parameters:
    1077: .  damping - The damping parameter

    1079:    Level: advanced

    1081: .seealso: SNESLineSearchGetStepTolerance(), SNESQN
    1082: @*/

    1084: PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
    1085: {
    1089:   *damping = linesearch->damping;
    1090:   return(0);
    1091: }

    1095: /*@
    1096:    SNESLineSearchSetDamping - Sets the line search damping paramter.

    1098:    Input Parameters:
    1099: .  linesearch - linesearch context
    1100: .  damping - The damping parameter

    1102:    Level: intermediate

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

    1111: .seealso: SNESLineSearchGetDamping()
    1112: @*/
    1113: PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
    1114: {
    1117:   linesearch->damping = damping;
    1118:   return(0);
    1119: }

    1123: /*@
    1124:    SNESLineSearchGetOrder - Gets the line search approximation order.

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

    1129:    Output Parameters:
    1130: .  order - The order

    1132:    Possible Values for order:
    1133: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1134: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1135: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1137:    Level: intermediate

    1139: .seealso: SNESLineSearchSetOrder()
    1140: @*/

    1142: PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
    1143: {
    1147:   *order = linesearch->order;
    1148:   return(0);
    1149: }

    1153: /*@
    1154:    SNESLineSearchSetOrder - Sets the line search damping paramter.

    1156:    Input Parameters:
    1157: .  linesearch - linesearch context
    1158: .  order - The damping parameter

    1160:    Level: intermediate

    1162:    Possible Values for order:
    1163: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
    1164: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
    1165: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

    1167:    Notes:
    1168:    Variable orders are supported by the following line searches:
    1169: +  bt - cubic and quadratic
    1170: -  cp - linear and quadratic

    1172: .seealso: SNESLineSearchGetOrder()
    1173: @*/
    1174: PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
    1175: {
    1178:   linesearch->order = order;
    1179:   return(0);
    1180: }

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

    1187:    Input Parameters:
    1188: .  linesearch - linesearch context

    1190:    Output Parameters:
    1191: +  xnorm - The norm of the current solution
    1192: .  fnorm - The norm of the current function
    1193: -  ynorm - The norm of the current update

    1195:    Notes:
    1196:    This function is mainly called from SNES implementations.

    1198:    Level: developer

    1200: .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs()
    1201: @*/
    1202: PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
    1203: {
    1206:   if (xnorm) *xnorm = linesearch->xnorm;
    1207:   if (fnorm) *fnorm = linesearch->fnorm;
    1208:   if (ynorm) *ynorm = linesearch->ynorm;
    1209:   return(0);
    1210: }

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

    1217:    Input Parameters:
    1218: +  linesearch - linesearch context
    1219: .  xnorm - The norm of the current solution
    1220: .  fnorm - The norm of the current function
    1221: -  ynorm - The norm of the current update

    1223:    Level: advanced

    1225: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1226: @*/
    1227: PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
    1228: {
    1231:   linesearch->xnorm = xnorm;
    1232:   linesearch->fnorm = fnorm;
    1233:   linesearch->ynorm = ynorm;
    1234:   return(0);
    1235: }

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

    1242:    Input Parameters:
    1243: .  linesearch - linesearch context

    1245:    Options Database Keys:
    1246: .   -snes_linesearch_norms - turn norm computation on or off

    1248:    Level: intermediate

    1250: .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms()
    1251: @*/
    1252: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
    1253: {
    1255:   SNES           snes;

    1258:   if (linesearch->norms) {
    1259:     if (linesearch->ops->vinorm) {
    1260:       SNESLineSearchGetSNES(linesearch, &snes);
    1261:       VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
    1262:       VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1263:       (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
    1264:     } else {
    1265:       VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm);
    1266:       VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm);
    1267:       VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
    1268:       VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm);
    1269:       VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm);
    1270:       VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm);
    1271:     }
    1272:   }
    1273:   return(0);
    1274: }

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

    1281:    Input Parameters:
    1282: +  linesearch  - linesearch context
    1283: -  flg  - indicates whether or not to compute norms

    1285:    Options Database Keys:
    1286: .   -snes_linesearch_norms - turn norm computation on or off

    1288:    Notes:
    1289:    This is most relevant to the SNESLINESEARCHBASIC line search type.

    1291:    Level: intermediate

    1293: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC
    1294: @*/
    1295: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
    1296: {
    1298:   linesearch->norms = flg;
    1299:   return(0);
    1300: }

    1304: /*@
    1305:    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context

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

    1310:    Output Parameters:
    1311: +  X - Solution vector
    1312: .  F - Function vector
    1313: .  Y - Search direction vector
    1314: .  W - Solution work vector
    1315: -  G - Function work vector

    1317:    Notes:
    1318:    At the beginning of a line search application, X should contain a
    1319:    solution and the vector F the function computed at X.  At the end of the
    1320:    line search application, X should contain the new solution, and F the
    1321:    function evaluated at the new solution.

    1323:    Level: advanced

    1325: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
    1326: @*/
    1327: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
    1328: {
    1331:   if (X) {
    1333:     *X = linesearch->vec_sol;
    1334:   }
    1335:   if (F) {
    1337:     *F = linesearch->vec_func;
    1338:   }
    1339:   if (Y) {
    1341:     *Y = linesearch->vec_update;
    1342:   }
    1343:   if (W) {
    1345:     *W = linesearch->vec_sol_new;
    1346:   }
    1347:   if (G) {
    1349:     *G = linesearch->vec_func_new;
    1350:   }
    1351:   return(0);
    1352: }

    1356: /*@
    1357:    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context

    1359:    Input Parameters:
    1360: +  linesearch - linesearch context
    1361: .  X - Solution vector
    1362: .  F - Function vector
    1363: .  Y - Search direction vector
    1364: .  W - Solution work vector
    1365: -  G - Function work vector

    1367:    Level: advanced

    1369: .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs()
    1370: @*/
    1371: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
    1372: {
    1375:   if (X) {
    1377:     linesearch->vec_sol = X;
    1378:   }
    1379:   if (F) {
    1381:     linesearch->vec_func = F;
    1382:   }
    1383:   if (Y) {
    1385:     linesearch->vec_update = Y;
    1386:   }
    1387:   if (W) {
    1389:     linesearch->vec_sol_new = W;
    1390:   }
    1391:   if (G) {
    1393:     linesearch->vec_func_new = G;
    1394:   }
    1395:   return(0);
    1396: }

    1400: /*@C
    1401:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
    1402:    SNES options in the database.

    1404:    Logically Collective on SNESLineSearch

    1406:    Input Parameters:
    1407: +  snes - the SNES context
    1408: -  prefix - the prefix to prepend to all option names

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

    1414:    Level: advanced

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

    1418: .seealso: SNESGetOptionsPrefix()
    1419: @*/
    1420: PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
    1421: {

    1426:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);
    1427:   return(0);
    1428: }

    1432: /*@C
    1433:    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
    1434:    SNESLineSearch options in the database.

    1436:    Not Collective

    1438:    Input Parameter:
    1439: .  linesearch - the SNESLineSearch context

    1441:    Output Parameter:
    1442: .  prefix - pointer to the prefix string used

    1444:    Notes:
    1445:    On the fortran side, the user should pass in a string 'prefix' of
    1446:    sufficient length to hold the prefix.

    1448:    Level: advanced

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

    1452: .seealso: SNESAppendOptionsPrefix()
    1453: @*/
    1454: PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
    1455: {

    1460:   PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);
    1461:   return(0);
    1462: }

    1466: /*@C
    1467:    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.

    1469:    Input Parameter:
    1470: +  linesearch - the SNESLineSearch context
    1471: -  nwork - the number of work vectors

    1473:    Level: developer

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

    1477: .keywords: SNESLineSearch, work, vector

    1479: .seealso: SNESSetWorkVecs()
    1480: @*/
    1481: PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
    1482: {

    1486:   if (linesearch->vec_sol) {
    1487:     VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
    1488:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
    1489:   return(0);
    1490: }

    1494: /*@
    1495:    SNESLineSearchGetSuccess - Gets the success/failure status of the last line search application

    1497:    Input Parameters:
    1498: .  linesearch - linesearch context

    1500:    Output Parameters:
    1501: .  success - The success or failure status

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

    1507:    Level: intermediate

    1509: .seealso: SNESLineSearchSetSuccess()
    1510: @*/
    1511: PetscErrorCode  SNESLineSearchGetSuccess(SNESLineSearch linesearch, PetscBool *success)
    1512: {
    1516:   if (success) *success = linesearch->success;
    1517:   return(0);
    1518: }

    1522: /*@
    1523:    SNESLineSearchSetSuccess - Sets the success/failure status of the last line search application

    1525:    Input Parameters:
    1526: +  linesearch - linesearch context
    1527: -  success - The success or failure status

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

    1533:    Level: developer

    1535: .seealso: SNESLineSearchGetSuccess()
    1536: @*/
    1537: PetscErrorCode  SNESLineSearchSetSuccess(SNESLineSearch linesearch, PetscBool success)
    1538: {
    1541:   linesearch->success = success;
    1542:   return(0);
    1543: }

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

    1550:    Input Parameters:
    1551: +  snes - nonlinear context obtained from SNESCreate()
    1552: .  projectfunc - function for projecting the function to the bounds
    1553: -  normfunc - function for computing the norm of an active set

    1555:    Logically Collective on SNES

    1557:    Calling sequence of projectfunc:
    1558: .vb
    1559:    projectfunc (SNES snes, Vec X)
    1560: .ve

    1562:     Input parameters for projectfunc:
    1563: +   snes - nonlinear context
    1564: -   X - current solution

    1566:     Output parameters for projectfunc:
    1567: .   X - Projected solution

    1569:    Calling sequence of normfunc:
    1570: .vb
    1571:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
    1572: .ve

    1574:     Input parameters for normfunc:
    1575: +   snes - nonlinear context
    1576: .   X - current solution
    1577: -   F - current residual

    1579:     Output parameters for normfunc:
    1580: .   fnorm - VI-specific norm of the function

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

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

    1588:     Level: developer

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

    1592: .seealso: SNESLineSearchGetVIFunctions(), SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck()
    1593: @*/
    1594: extern PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc)
    1595: {
    1598:   if (projectfunc) linesearch->ops->viproject = projectfunc;
    1599:   if (normfunc) linesearch->ops->vinorm = normfunc;
    1600:   return(0);
    1601: }

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

    1608:    Input Parameters:
    1609: .  snes - nonlinear context obtained from SNESCreate()

    1611:    Output Parameters:
    1612: +  projectfunc - function for projecting the function to the bounds
    1613: -  normfunc - function for computing the norm of an active set

    1615:    Logically Collective on SNES

    1617:     Level: developer

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

    1621: .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
    1622: @*/
    1623: extern PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
    1624: {
    1626:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
    1627:   if (normfunc) *normfunc = linesearch->ops->vinorm;
    1628:   return(0);
    1629: }

    1633: /*@C
    1634:   SNESLineSearchRegister - See SNESLineSearchRegister()

    1636:   Level: advanced
    1637: @*/
    1638: PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
    1639: {

    1643:   PetscFunctionListAdd(&SNESLineSearchList,sname,function);
    1644:   return(0);
    1645: }