Actual source code: linesearch.c

petsc-3.5.4 2015-05-23
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:    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: developer

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

 28: .keywords: LineSearch, create, context

 30: .seealso: LineSearchDestroy(), SNESGetLineSearch()
 31: @*/

 33: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
 34: {
 36:   SNESLineSearch linesearch;

 40:   SNESInitializePackage();
 41:   *outlinesearch = NULL;

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

 45:   linesearch->ops->precheck  = NULL;
 46:   linesearch->ops->postcheck = NULL;

 48:   linesearch->vec_sol_new  = NULL;
 49:   linesearch->vec_func_new = NULL;
 50:   linesearch->vec_sol      = NULL;
 51:   linesearch->vec_func     = NULL;
 52:   linesearch->vec_update   = NULL;

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

 77: /*@
 78:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
 79:    any required vectors.

 81:    Collective on SNESLineSearch

 83:    Input Parameters:
 84: .  linesearch - The LineSearch instance.

 86:    Notes:
 87:    For most cases, this needn't be called by users or outside of SNESLineSearchApply().
 88:    The only current case where this is called outside of this is for the VI
 89:    solvers, which modify the solution and work vectors before the first call
 90:    of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be
 91:    allocated upfront.

 93:    Level: advanced

 95: .keywords: SNESLineSearch, SetUp

 97: .seealso: SNESLineSearchReset()
 98: @*/

100: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
101: {

105:   if (!((PetscObject)linesearch)->type_name) {
106:     SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);
107:   }
108:   if (!linesearch->setupcalled) {
109:     if (!linesearch->vec_sol_new) {
110:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
111:     }
112:     if (!linesearch->vec_func_new) {
113:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
114:     }
115:     if (linesearch->ops->setup) {
116:       (*linesearch->ops->setup)(linesearch);
117:     }
118:     if (!linesearch->ops->snesfunc) {SNESLineSearchSetFunction(linesearch,SNESComputeFunction);}
119:     linesearch->lambda      = linesearch->damping;
120:     linesearch->setupcalled = PETSC_TRUE;
121:   }
122:   return(0);
123: }


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

131:    Collective on SNESLineSearch

133:    Input Parameters:
134: .  linesearch - The LineSearch instance.

136:    Notes: Usually only called by SNESReset()

138:    Level: developer

140: .keywords: SNESLineSearch, Reset

142: .seealso: SNESLineSearchSetUp()
143: @*/

145: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
146: {

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

152:   VecDestroy(&linesearch->vec_sol_new);
153:   VecDestroy(&linesearch->vec_func_new);

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

157:   linesearch->nwork       = 0;
158:   linesearch->setupcalled = PETSC_FALSE;
159:   return(0);
160: }

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

167:    Input Parameters:
168: .  linesearch - the SNESLineSearch context
169: +  func       - function evaluation routine

171:    Level: developer

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

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

177: .seealso: SNESSetFunction()
178: @*/
179: PetscErrorCode  SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES,Vec,Vec))
180: {
183:   linesearch->ops->snesfunc = func;
184:   return(0);
185: }


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

191:      Synopsis:
192:      #include <petscsnes.h>
193:      SNESLineSearchPreCheckFunction(SNESLineSearch snes,Vec x,Vec y, PetscBool *changed);

195:        Input Parameters:
196: +      x - solution vector
197: .      y - search direction vector
198: -      changed - flag to indicate the precheck changed x or y.

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

203:    Level: advanced

205: .seealso:   SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck() 
206: M*/

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

215:    Logically Collective on SNESLineSearch

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

222:    Level: intermediate

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

226: .seealso: SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
227: @*/
228: PetscErrorCode  SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void *ctx)
229: {
232:   if (func) linesearch->ops->precheck = func;
233:   if (ctx) linesearch->precheckctx = ctx;
234:   return(0);
235: }

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

242:    Input Parameters:
243: .  linesearch - the SNESLineSearch context

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

249:    Level: intermediate

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

253: .seealso: SNESLineSearchGetPostCheck(), SNESLineSearchSetPreCheck()
254: @*/
255: PetscErrorCode  SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void **ctx)
256: {
259:   if (func) *func = linesearch->ops->precheck;
260:   if (ctx) *ctx = linesearch->precheckctx;
261:   return(0);
262: }

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

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

271:      Input Parameters:
272: +      x - old solution vector
273: .      y - search direction vector
274: .      w - new solution vector
275: .      changed_y - indicates that the line search changed y
276: -      changed_w - indicates that the line search changed w

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

281:    Level: advanced

283: .seealso:   SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchGetPostCheck()
284: M*/

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

292:    Logically Collective on SNESLineSearch

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

299:    Level: intermediate

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

303: .seealso: SNESLineSearchSetPreCheck()
304: @*/
305: PetscErrorCode  SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx)
306: {
309:   if (func) linesearch->ops->postcheck = func;
310:   if (ctx) linesearch->postcheckctx = ctx;
311:   return(0);
312: }

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

319:    Input Parameters:
320: .  linesearch - the SNESLineSearch context

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

326:    Level: intermediate

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

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

343: /*@
344:    SNESLineSearchPreCheck - Prepares the line search for being applied.

346:    Logically Collective on SNESLineSearch

348:    Input Parameters:
349: +  linesearch - The linesearch instance.
350: .  X - The current solution
351: -  Y - The step direction

353:    Output Parameters:
354: .  changed - Indicator that the precheck routine has changed anything

356:    Level: developer

358: .keywords: SNESLineSearch, Create

360: .seealso: SNESLineSearchPostCheck()
361: @*/
362: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed)
363: {

367:   *changed = PETSC_FALSE;
368:   if (linesearch->ops->precheck) {
369:     (*linesearch->ops->precheck)(linesearch, X, Y, changed, linesearch->precheckctx);
371:   }
372:   return(0);
373: }

377: /*@
378:    SNESLineSearchPostCheck - Prepares the line search for being applied.

380:    Logically Collective on SNESLineSearch

382:    Input Parameters:
383: +  linesearch - The linesearch context
384: .  X - The last solution
385: .  Y - The step direction
386: -  W - The updated solution, W = X + lambda*Y for some lambda

388:    Output Parameters:
389: +  changed_Y - Indicator if the direction Y has been changed.
390: -  changed_W - Indicator if the new candidate solution W has been changed.

392:    Level: developer

394: .keywords: SNESLineSearch, Create

396: .seealso: SNESLineSearchPreCheck()
397: @*/
398: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W)
399: {

403:   *changed_Y = PETSC_FALSE;
404:   *changed_W = PETSC_FALSE;
405:   if (linesearch->ops->postcheck) {
406:     (*linesearch->ops->postcheck)(linesearch,X,Y,W,changed_Y,changed_W,linesearch->postcheckctx);
409:   }
410:   return(0);
411: }

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

418:    Logically Collective on SNESLineSearch

420:    Input Arguments:
421: +  linesearch - linesearch context
422: .  X - base state for this step
423: .  Y - initial correction

425:    Output Arguments:
426: +  Y - correction, possibly modified
427: -  changed - flag indicating that Y was modified

429:    Options Database Key:
430: +  -snes_linesearch_precheck_picard - activate this routine
431: -  -snes_linesearch_precheck_picard_angle - angle

433:    Level: advanced

435:    Notes:
436:    This function should be passed to SNESLineSearchSetPreCheck()

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

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

445: .seealso: SNESLineSearchSetPreCheck()
446: @*/
447: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed,void *ctx)
448: {
450:   PetscReal      angle = *(PetscReal*)linesearch->precheckctx;
451:   Vec            Ylast;
452:   PetscScalar    dot;
453:   PetscInt       iter;
454:   PetscReal      ynorm,ylastnorm,theta,angle_radians;
455:   SNES           snes;

458:   SNESLineSearchGetSNES(linesearch, &snes);
459:   PetscObjectQuery((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject*)&Ylast);
460:   if (!Ylast) {
461:     VecDuplicate(Y,&Ylast);
462:     PetscObjectCompose((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject)Ylast);
463:     PetscObjectDereference((PetscObject)Ylast);
464:   }
465:   SNESGetIterationNumber(snes,&iter);
466:   if (iter < 2) {
467:     VecCopy(Y,Ylast);
468:     *changed = PETSC_FALSE;
469:     return(0);
470:   }

472:   VecDot(Y,Ylast,&dot);
473:   VecNorm(Y,NORM_2,&ynorm);
474:   VecNorm(Ylast,NORM_2,&ylastnorm);
475:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
476:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm),-1.0,1.0));
477:   angle_radians = angle * PETSC_PI / 180.;
478:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
479:     /* Modify the step Y */
480:     PetscReal alpha,ydiffnorm;
481:     VecAXPY(Ylast,-1.0,Y);
482:     VecNorm(Ylast,NORM_2,&ydiffnorm);
483:     alpha = ylastnorm / ydiffnorm;
484:     VecCopy(Y,Ylast);
485:     VecScale(Y,alpha);
486:     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);
487:   } else {
488:     PetscInfo2(snes,"Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n",(double)(theta*180./PETSC_PI),(double)angle);
489:     VecCopy(Y,Ylast);
490:     *changed = PETSC_FALSE;
491:   }
492:   return(0);
493: }

497: /*@
498:    SNESLineSearchApply - Computes the line-search update.

500:    Collective on SNESLineSearch

502:    Input Parameters:
503: +  linesearch - The linesearch context
504: .  X - The current solution
505: .  F - The current function
506: .  fnorm - The current norm
507: -  Y - The search direction

509:    Output Parameters:
510: +  X - The new solution
511: .  F - The new function
512: -  fnorm - The new function norm

514:    Options Database Keys:
515: + -snes_linesearch_type - basic, bt, l2, cp, shell
516: . -snes_linesearch_monitor - Print progress of line searches
517: . -snes_linesearch_damping - The linesearch damping parameter
518: . -snes_linesearch_norms   - Turn on/off the linesearch norms
519: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess
520: - -snes_linesearch_max_it - The number of iterations for iterative line searches

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

530:    Level: Intermediate

532: .keywords: SNESLineSearch, Create

534: .seealso: SNESLineSearchCreate(), SNESLineSearchPreCheck(), SNESLineSearchPostCheck(), SNESSolve(), SNESComputeFunction()
535: @*/
536: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y)
537: {


546:   linesearch->success = PETSC_TRUE;

548:   linesearch->vec_sol    = X;
549:   linesearch->vec_update = Y;
550:   linesearch->vec_func   = F;

552:   SNESLineSearchSetUp(linesearch);

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

556:   if (fnorm) linesearch->fnorm = *fnorm;
557:   else {
558:     VecNorm(F, NORM_2, &linesearch->fnorm);
559:   }

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

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

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

567:   if (fnorm) *fnorm = linesearch->fnorm;
568:   return(0);
569: }

573: /*@
574:    SNESLineSearchDestroy - Destroys the line search instance.

576:    Collective on SNESLineSearch

578:    Input Parameters:
579: .  linesearch - The linesearch context

581:    Level: Intermediate

583: .keywords: SNESLineSearch, Destroy

585: .seealso: SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy()
586: @*/
587: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch)
588: {

592:   if (!*linesearch) return(0);
594:   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = 0; return(0);}
595:   PetscObjectSAWsViewOff((PetscObject)*linesearch);
596:   SNESLineSearchReset(*linesearch);
597:   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
598:   PetscViewerDestroy(&(*linesearch)->monitor);
599:   PetscHeaderDestroy(linesearch);
600:   return(0);
601: }

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

608:    Input Parameters:
609: +  snes - nonlinear context obtained from SNESCreate()
610: -  flg - PETSC_TRUE to monitor the line search

612:    Logically Collective on SNES

614:    Options Database:
615: .   -snes_linesearch_monitor - enables the monitor

617:    Level: intermediate

619: .seealso: SNESLineSearchGetMonitor(), PetscViewer
620: @*/
621: PetscErrorCode  SNESLineSearchSetMonitor(SNESLineSearch linesearch, PetscBool flg)
622: {

626:   if (flg && !linesearch->monitor) {
627:     PetscViewerASCIIOpen(PetscObjectComm((PetscObject)linesearch),"stdout",&linesearch->monitor);
628:   } else if (!flg && linesearch->monitor) {
629:     PetscViewerDestroy(&linesearch->monitor);
630:   }
631:   return(0);
632: }

636: /*@
637:    SNESLineSearchGetMonitor - Gets the PetscViewer instance for the line search monitor.

639:    Input Parameter:
640: .  linesearch - linesearch context

642:    Output Parameter:
643: .  monitor - monitor context

645:    Logically Collective on SNES

647:    Options Database Keys:
648: .   -snes_linesearch_monitor - enables the monitor

650:    Level: intermediate

652: .seealso: SNESLineSearchSetMonitor(), PetscViewer
653: @*/
654: PetscErrorCode  SNESLineSearchGetMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
655: {
658:   if (monitor) {
660:     *monitor = linesearch->monitor;
661:   }
662:   return(0);
663: }

667: /*@
668:    SNESLineSearchSetFromOptions - Sets options for the line search

670:    Input Parameters:
671: .  linesearch - linesearch context

673:    Options Database Keys:
674: + -snes_linesearch_type <type> - basic, bt, l2, cp, shell
675: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
676: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch type
677: . -snes_linesearch_minlambda - The minimum step length
678: . -snes_linesearch_maxstep - The maximum step size
679: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
680: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
681: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
682: . -snes_linesearch_max_it - The number of iterations for iterative line searches
683: . -snes_linesearch_monitor - Print progress of line searches
684: . -snes_linesearch_damping - The linesearch damping parameter
685: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
686: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
687: - -snes_linesearch_precheck_picard_angle - Angle used in picard precheck method

689:    Logically Collective on SNESLineSearch

691:    Level: intermediate

693: .seealso: SNESLineSearchCreate(), SNESLineSearchSetOrder(), SNESLineSearchSetType(), SNESLineSearchSetTolerances(), SNESLineSearchSetDamping(), SNESLineSearchPreCheckPicard()
694: @*/
695: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
696: {
698:   const char     *deft = SNESLINESEARCHBASIC;
699:   char           type[256];
700:   PetscBool      flg, set;

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

705:   PetscObjectOptionsBegin((PetscObject)linesearch);
706:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
707:   PetscOptionsFList("-snes_linesearch_type","Linesearch type","SNESLineSearchSetType",SNESLineSearchList,deft,type,256,&flg);
708:   if (flg) {
709:     SNESLineSearchSetType(linesearch,type);
710:   } else if (!((PetscObject)linesearch)->type_name) {
711:     SNESLineSearchSetType(linesearch,deft);
712:   }

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

718:   /* tolerances */
719:   PetscOptionsReal("-snes_linesearch_minlambda","Minimum step length","SNESLineSearchSetTolerances",linesearch->steptol,&linesearch->steptol,0);
720:   PetscOptionsReal("-snes_linesearch_maxstep","Maximum step size","SNESLineSearchSetTolerances",linesearch->maxstep,&linesearch->maxstep,0);
721:   PetscOptionsReal("-snes_linesearch_rtol","Relative tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->rtol,&linesearch->rtol,0);
722:   PetscOptionsReal("-snes_linesearch_atol","Absolute tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->atol,&linesearch->atol,0);
723:   PetscOptionsReal("-snes_linesearch_ltol","Change in lambda tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->ltol,&linesearch->ltol,0);
724:   PetscOptionsInt("-snes_linesearch_max_it","Maximum iterations for iterative line searches","SNESLineSearchSetTolerances",linesearch->max_its,&linesearch->max_its,0);

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

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

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

737:       PetscOptionsReal("-snes_linesearch_precheck_picard_angle","Maximum angle at which to activate the correction",
738:                               "none",linesearch->precheck_picard_angle,&linesearch->precheck_picard_angle,NULL);
739:       SNESLineSearchSetPreCheck(linesearch,SNESLineSearchPreCheckPicard,&linesearch->precheck_picard_angle);
740:     } else {
741:       SNESLineSearchSetPreCheck(linesearch,NULL,NULL);
742:     }
743:   }
744:   PetscOptionsInt("-snes_linesearch_order","Order of approximation used in the line search","SNESLineSearchSetOrder",linesearch->order,&linesearch->order,0);
745:   PetscOptionsBool("-snes_linesearch_norms","Compute final norms in line search","SNESLineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,0);

747:   if (linesearch->ops->setfromoptions) {
748:     (*linesearch->ops->setfromoptions)(linesearch);
749:   }

751:   PetscObjectProcessOptionsHandlers((PetscObject)linesearch);
752:   PetscOptionsEnd();
753:   return(0);
754: }

758: /*@
759:    SNESLineSearchView - Prints useful information about the line search

761:    Input Parameters:
762: .  linesearch - linesearch context

764:    Logically Collective on SNESLineSearch

766:    Level: intermediate

768: .seealso: SNESLineSearchCreate(), SNESLineSearchMonitor()
769: @*/
770: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
771: {
773:   PetscBool      iascii;

777:   if (!viewer) {
778:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch),&viewer);
779:   }

783:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
784:   if (iascii) {
785:     PetscObjectPrintClassNamePrefixType((PetscObject)linesearch,viewer);
786:     if (linesearch->ops->view) {
787:       PetscViewerASCIIPushTab(viewer);
788:       (*linesearch->ops->view)(linesearch,viewer);
789:       PetscViewerASCIIPopTab(viewer);
790:     }
791:     PetscViewerASCIIPrintf(viewer,"  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol);
792:     PetscViewerASCIIPrintf(viewer,"  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol);
793:     PetscViewerASCIIPrintf(viewer,"  maximum iterations=%D\n", linesearch->max_its);
794:     if (linesearch->ops->precheck) {
795:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
796:         PetscViewerASCIIPrintf(viewer,"  using precheck step to speed up Picard convergence\n", linesearch->max_its);
797:       } else {
798:         PetscViewerASCIIPrintf(viewer,"  using user-defined precheck step\n", linesearch->max_its);
799:       }
800:     }
801:     if (linesearch->ops->postcheck) {
802:       PetscViewerASCIIPrintf(viewer,"  using user-defined postcheck step\n", linesearch->max_its);
803:     }
804:   }
805:   return(0);
806: }

810: /*@C
811:    SNESLineSearchSetType - Sets the linesearch type

813:    Logically Collective on SNESLineSearch

815:    Input Parameters:
816: +  linesearch - linesearch context
817: -  type - The type of line search to be used

819:    Available Types:
820: +  basic - Simple damping line search.
821: .  bt - Backtracking line search over the L2 norm of the function
822: .  l2 - Secant line search over the L2 norm of the function
823: .  cp - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
824: -  shell - User provided SNESLineSearch implementation

826:    Level: intermediate

828: .seealso: SNESLineSearchCreate()
829: @*/
830: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
831: {
832:   PetscErrorCode ierr,(*r)(SNESLineSearch);
833:   PetscBool      match;


839:   PetscObjectTypeCompare((PetscObject)linesearch,type,&match);
840:   if (match) return(0);

842:   PetscFunctionListFind(SNESLineSearchList,type,&r);
843:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type);
844:   /* Destroy the previous private linesearch context */
845:   if (linesearch->ops->destroy) {
846:     (*(linesearch)->ops->destroy)(linesearch);

848:     linesearch->ops->destroy = NULL;
849:   }
850:   /* Reinitialize function pointers in SNESLineSearchOps structure */
851:   linesearch->ops->apply          = 0;
852:   linesearch->ops->view           = 0;
853:   linesearch->ops->setfromoptions = 0;
854:   linesearch->ops->destroy        = 0;

856:   PetscObjectChangeTypeName((PetscObject)linesearch,type);
857:   (*r)(linesearch);
858:   return(0);
859: }

863: /*@
864:    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.

866:    Input Parameters:
867: +  linesearch - linesearch context
868: -  snes - The snes instance

870:    Level: developer

872:    Notes:
873:    This happens automatically when the line search is obtained/created with
874:    SNESGetLineSearch().  This routine is therefore mainly called within SNES
875:    implementations.

877:    Level: developer

879: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
880: @*/
881: PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
882: {
886:   linesearch->snes = snes;
887:   return(0);
888: }

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

898:    Input Parameters:
899: .  linesearch - linesearch context

901:    Output Parameters:
902: .  snes - The snes instance

904:    Level: developer

906: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
907: @*/
908: PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
909: {
913:   *snes = linesearch->snes;
914:   return(0);
915: }

919: /*@
920:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

922:    Input Parameters:
923: .  linesearch - linesearch context

925:    Output Parameters:
926: .  lambda - The last steplength computed during SNESLineSearchApply()

928:    Level: advanced

930:    Notes:
931:    This is useful in methods where the solver is ill-scaled and
932:    requires some adaptive notion of the difference in scale between the
933:    solution and the function.  For instance, SNESQN may be scaled by the
934:    line search lambda using the argument -snes_qn_scaling ls.

936: .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply()
937: @*/
938: PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
939: {
943:   *lambda = linesearch->lambda;
944:   return(0);
945: }

949: /*@
950:    SNESLineSearchSetLambda - Sets the linesearch steplength.

952:    Input Parameters:
953: +  linesearch - linesearch context
954: -  lambda - The last steplength.

956:    Notes:
957:    This routine is typically used within implementations of SNESLineSearchApply()
958:    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
959:    added in order to facilitate Quasi-Newton methods that use the previous steplength
960:    as an inner scaling parameter.

962:    Level: advanced

964: .seealso: SNESLineSearchGetLambda()
965: @*/
966: PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
967: {
970:   linesearch->lambda = lambda;
971:   return(0);
972: }

974: #undef  __FUNCT__
976: /*@
977:    SNESLineSearchGetTolerances - Gets the tolerances for the linesearch.  These include
978:    tolerances for the relative and absolute change in the function norm, the change
979:    in lambda for iterative line searches, the minimum steplength, the maximum steplength,
980:    and the maximum number of iterations the line search procedure may take.

982:    Input Parameters:
983: .  linesearch - linesearch context

985:    Output Parameters:
986: +  steptol - The minimum steplength
987: .  maxstep - The maximum steplength
988: .  rtol    - The relative tolerance for iterative line searches
989: .  atol    - The absolute tolerance for iterative line searches
990: .  ltol    - The change in lambda tolerance for iterative line searches
991: -  max_it  - The maximum number of iterations of the line search

993:    Level: intermediate

995:    Notes:
996:    Different line searches may implement these parameters slightly differently as
997:    the type requires.

999: .seealso: SNESLineSearchSetTolerances()
1000: @*/
1001: PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1002: {
1005:   if (steptol) {
1007:     *steptol = linesearch->steptol;
1008:   }
1009:   if (maxstep) {
1011:     *maxstep = linesearch->maxstep;
1012:   }
1013:   if (rtol) {
1015:     *rtol = linesearch->rtol;
1016:   }
1017:   if (atol) {
1019:     *atol = linesearch->atol;
1020:   }
1021:   if (ltol) {
1023:     *ltol = linesearch->ltol;
1024:   }
1025:   if (max_its) {
1027:     *max_its = linesearch->max_its;
1028:   }
1029:   return(0);
1030: }

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

1040:    Input Parameters:
1041: +  linesearch - linesearch context
1042: .  steptol - The minimum steplength
1043: .  maxstep - The maximum steplength
1044: .  rtol    - The relative tolerance for iterative line searches
1045: .  atol    - The absolute tolerance for iterative line searches
1046: .  ltol    - The change in lambda tolerance for iterative line searches
1047: -  max_it  - The maximum number of iterations of the line search

1049:    Notes:
1050:    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
1051:    place of an argument.

1053:    Level: intermediate

1055: .seealso: SNESLineSearchGetTolerances()
1056: @*/
1057: PetscErrorCode  SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
1058: {

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

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

1078:   if (rtol != PETSC_DEFAULT) {
1079:     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);
1080:     linesearch->rtol = rtol;
1081:   }

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

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

1093:   if (max_its != PETSC_DEFAULT) {
1094:     if (max_its < 0) SETERRQ1(PetscObjectComm((PetscObject)linesearch),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",max_its);
1095:     linesearch->max_its = max_its;
1096:   }
1097:   return(0);
1098: }

1102: /*@
1103:    SNESLineSearchGetDamping - Gets the line search damping parameter.

1105:    Input Parameters:
1106: .  linesearch - linesearch context

1108:    Output Parameters:
1109: .  damping - The damping parameter

1111:    Level: advanced

1113: .seealso: SNESLineSearchGetStepTolerance(), SNESQN
1114: @*/

1116: PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
1117: {
1121:   *damping = linesearch->damping;
1122:   return(0);
1123: }

1127: /*@
1128:    SNESLineSearchSetDamping - Sets the line search damping paramter.

1130:    Input Parameters:
1131: .  linesearch - linesearch context
1132: .  damping - The damping parameter

1134:    Level: intermediate

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

1143: .seealso: SNESLineSearchGetDamping()
1144: @*/
1145: PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
1146: {
1149:   linesearch->damping = damping;
1150:   return(0);
1151: }

1155: /*@
1156:    SNESLineSearchGetOrder - Gets the line search approximation order.

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

1161:    Output Parameters:
1162: .  order - The order

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

1169:    Level: intermediate

1171: .seealso: SNESLineSearchSetOrder()
1172: @*/

1174: PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
1175: {
1179:   *order = linesearch->order;
1180:   return(0);
1181: }

1185: /*@
1186:    SNESLineSearchSetOrder - Sets the line search damping paramter.

1188:    Input Parameters:
1189: .  linesearch - linesearch context
1190: .  order - The damping parameter

1192:    Level: intermediate

1194:    Possible Values for order:
1195: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
1196: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
1197: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

1199:    Notes:
1200:    Variable orders are supported by the following line searches:
1201: +  bt - cubic and quadratic
1202: -  cp - linear and quadratic

1204: .seealso: SNESLineSearchGetOrder()
1205: @*/
1206: PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
1207: {
1210:   linesearch->order = order;
1211:   return(0);
1212: }

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

1219:    Input Parameters:
1220: .  linesearch - linesearch context

1222:    Output Parameters:
1223: +  xnorm - The norm of the current solution
1224: .  fnorm - The norm of the current function
1225: -  ynorm - The norm of the current update

1227:    Notes:
1228:    This function is mainly called from SNES implementations.

1230:    Level: developer

1232: .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs()
1233: @*/
1234: PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
1235: {
1238:   if (xnorm) *xnorm = linesearch->xnorm;
1239:   if (fnorm) *fnorm = linesearch->fnorm;
1240:   if (ynorm) *ynorm = linesearch->ynorm;
1241:   return(0);
1242: }

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

1249:    Input Parameters:
1250: +  linesearch - linesearch context
1251: .  xnorm - The norm of the current solution
1252: .  fnorm - The norm of the current function
1253: -  ynorm - The norm of the current update

1255:    Level: advanced

1257: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
1258: @*/
1259: PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1260: {
1263:   linesearch->xnorm = xnorm;
1264:   linesearch->fnorm = fnorm;
1265:   linesearch->ynorm = ynorm;
1266:   return(0);
1267: }

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

1274:    Input Parameters:
1275: .  linesearch - linesearch context

1277:    Options Database Keys:
1278: .   -snes_linesearch_norms - turn norm computation on or off

1280:    Level: intermediate

1282: .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms()
1283: @*/
1284: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1285: {
1287:   SNES           snes;

1290:   if (linesearch->norms) {
1291:     if (linesearch->ops->vinorm) {
1292:       SNESLineSearchGetSNES(linesearch, &snes);
1293:       VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1294:       VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1295:       (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
1296:     } else {
1297:       VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm);
1298:       VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm);
1299:       VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1300:       VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm);
1301:       VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm);
1302:       VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm);
1303:     }
1304:   }
1305:   return(0);
1306: }

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

1313:    Input Parameters:
1314: +  linesearch  - linesearch context
1315: -  flg  - indicates whether or not to compute norms

1317:    Options Database Keys:
1318: .   -snes_linesearch_norms - turn norm computation on or off

1320:    Notes:
1321:    This is most relevant to the SNESLINESEARCHBASIC line search type.

1323:    Level: intermediate

1325: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC
1326: @*/
1327: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1328: {
1330:   linesearch->norms = flg;
1331:   return(0);
1332: }

1336: /*@
1337:    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context

1339:    Input Parameters:
1340: .  linesearch - linesearch context

1342:    Output Parameters:
1343: +  X - Solution vector
1344: .  F - Function vector
1345: .  Y - Search direction vector
1346: .  W - Solution work vector
1347: -  G - Function work vector

1349:    Notes:
1350:    At the beginning of a line search application, X should contain a
1351:    solution and the vector F the function computed at X.  At the end of the
1352:    line search application, X should contain the new solution, and F the
1353:    function evaluated at the new solution.

1355:    Level: advanced

1357: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
1358: @*/
1359: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
1360: {
1363:   if (X) {
1365:     *X = linesearch->vec_sol;
1366:   }
1367:   if (F) {
1369:     *F = linesearch->vec_func;
1370:   }
1371:   if (Y) {
1373:     *Y = linesearch->vec_update;
1374:   }
1375:   if (W) {
1377:     *W = linesearch->vec_sol_new;
1378:   }
1379:   if (G) {
1381:     *G = linesearch->vec_func_new;
1382:   }
1383:   return(0);
1384: }

1388: /*@
1389:    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context

1391:    Input Parameters:
1392: +  linesearch - linesearch context
1393: .  X - Solution vector
1394: .  F - Function vector
1395: .  Y - Search direction vector
1396: .  W - Solution work vector
1397: -  G - Function work vector

1399:    Level: advanced

1401: .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs()
1402: @*/
1403: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
1404: {
1407:   if (X) {
1409:     linesearch->vec_sol = X;
1410:   }
1411:   if (F) {
1413:     linesearch->vec_func = F;
1414:   }
1415:   if (Y) {
1417:     linesearch->vec_update = Y;
1418:   }
1419:   if (W) {
1421:     linesearch->vec_sol_new = W;
1422:   }
1423:   if (G) {
1425:     linesearch->vec_func_new = G;
1426:   }
1427:   return(0);
1428: }

1432: /*@C
1433:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1434:    SNES options in the database.

1436:    Logically Collective on SNESLineSearch

1438:    Input Parameters:
1439: +  snes - the SNES context
1440: -  prefix - the prefix to prepend to all option names

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

1446:    Level: advanced

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

1450: .seealso: SNESGetOptionsPrefix()
1451: @*/
1452: PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
1453: {

1458:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);
1459:   return(0);
1460: }

1464: /*@C
1465:    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
1466:    SNESLineSearch options in the database.

1468:    Not Collective

1470:    Input Parameter:
1471: .  linesearch - the SNESLineSearch context

1473:    Output Parameter:
1474: .  prefix - pointer to the prefix string used

1476:    Notes:
1477:    On the fortran side, the user should pass in a string 'prefix' of
1478:    sufficient length to hold the prefix.

1480:    Level: advanced

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

1484: .seealso: SNESAppendOptionsPrefix()
1485: @*/
1486: PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
1487: {

1492:   PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);
1493:   return(0);
1494: }

1498: /*@C
1499:    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.

1501:    Input Parameter:
1502: +  linesearch - the SNESLineSearch context
1503: -  nwork - the number of work vectors

1505:    Level: developer

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

1509: .keywords: SNESLineSearch, work, vector

1511: .seealso: SNESSetWorkVecs()
1512: @*/
1513: PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1514: {

1518:   if (linesearch->vec_sol) {
1519:     VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
1520:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1521:   return(0);
1522: }

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

1529:    Input Parameters:
1530: .  linesearch - linesearch context

1532:    Output Parameters:
1533: .  success - The success or failure status

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

1539:    Level: intermediate

1541: .seealso: SNESLineSearchSetSuccess()
1542: @*/
1543: PetscErrorCode  SNESLineSearchGetSuccess(SNESLineSearch linesearch, PetscBool *success)
1544: {
1548:   if (success) *success = linesearch->success;
1549:   return(0);
1550: }

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

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

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

1565:    Level: developer

1567: .seealso: SNESLineSearchGetSuccess()
1568: @*/
1569: PetscErrorCode  SNESLineSearchSetSuccess(SNESLineSearch linesearch, PetscBool success)
1570: {
1573:   linesearch->success = success;
1574:   return(0);
1575: }

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

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

1587:    Logically Collective on SNES

1589:    Calling sequence of projectfunc:
1590: .vb
1591:    projectfunc (SNES snes, Vec X)
1592: .ve

1594:     Input parameters for projectfunc:
1595: +   snes - nonlinear context
1596: -   X - current solution

1598:     Output parameters for projectfunc:
1599: .   X - Projected solution

1601:    Calling sequence of normfunc:
1602: .vb
1603:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
1604: .ve

1606:     Input parameters for normfunc:
1607: +   snes - nonlinear context
1608: .   X - current solution
1609: -   F - current residual

1611:     Output parameters for normfunc:
1612: .   fnorm - VI-specific norm of the function

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

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

1620:     Level: developer

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

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

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

1640:    Input Parameters:
1641: .  snes - nonlinear context obtained from SNESCreate()

1643:    Output Parameters:
1644: +  projectfunc - function for projecting the function to the bounds
1645: -  normfunc - function for computing the norm of an active set

1647:    Logically Collective on SNES

1649:     Level: developer

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

1653: .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
1654: @*/
1655: extern PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
1656: {
1658:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
1659:   if (normfunc) *normfunc = linesearch->ops->vinorm;
1660:   return(0);
1661: }

1665: /*@C
1666:   SNESLineSearchRegister - See SNESLineSearchRegister()

1668:   Level: advanced
1669: @*/
1670: PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
1671: {

1675:   PetscFunctionListAdd(&SNESLineSearchList,sname,function);
1676:   return(0);
1677: }