Actual source code: linesearch.c

  1: #include <petsc/private/linesearchimpl.h>

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

  6: PetscClassId  SNESLINESEARCH_CLASSID;
  7: PetscLogEvent SNESLINESEARCH_Apply;

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

 12:    Logically Collective on SNESLineSearch

 14:    Input Parameters:
 15: .  ls - the SNESLineSearch context

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

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

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

 28:    Level: intermediate

 30: .seealso: SNESGetLineSearch(), SNESLineSearchMonitorDefault(), SNESLineSearchMonitorSet()
 31: @*/
 32: PetscErrorCode  SNESLineSearchMonitorCancel(SNESLineSearch ls)
 33: {
 34:   PetscInt       i;

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

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

 49:    Collective on SNES

 51:    Input Parameters:
 52: .  ls - the linesearch object

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

 58:    Level: developer

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

 66:   for (i=0; i<n; i++) {
 67:     (*ls->monitorftns[i])(ls,ls->monitorcontext[i]);
 68:   }
 69:   return 0;
 70: }

 72: /*@C
 73:    SNESLineSearchMonitorSet - Sets an ADDITIONAL function that is to be used at every
 74:    iteration of the nonlinear solver to display the iteration's
 75:    progress.

 77:    Logically Collective on SNESLineSearch

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

 87:    Notes:
 88:    Several different monitoring routines may be set by calling
 89:    SNESLineSearchMonitorSet() multiple times; all will be called in the
 90:    order in which they were set.

 92:    Fortran Notes:
 93:     Only a single monitor function can be set for each SNESLineSearch object

 95:    Level: intermediate

 97: .seealso: SNESGetLineSearch(), SNESLineSearchMonitorDefault(), SNESLineSearchMonitorCancel()
 98: @*/
 99: PetscErrorCode  SNESLineSearchMonitorSet(SNESLineSearch ls,PetscErrorCode (*f)(SNESLineSearch,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
100: {
101:   PetscInt       i;
102:   PetscBool      identical;

105:   for (i=0; i<ls->numbermonitors;i++) {
106:     PetscMonitorCompare((PetscErrorCode (*)(void))f,mctx,monitordestroy,(PetscErrorCode (*)(void))ls->monitorftns[i],ls->monitorcontext[i],ls->monitordestroy[i],&identical);
107:     if (identical) return 0;
108:   }
110:   ls->monitorftns[ls->numbermonitors]          = f;
111:   ls->monitordestroy[ls->numbermonitors]   = monitordestroy;
112:   ls->monitorcontext[ls->numbermonitors++] = (void*)mctx;
113:   return 0;
114: }

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

119:    Collective on SNESLineSearch

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

125:    Level: intermediate

127: .seealso: SNESGetLineSearch(), SNESMonitorSet(), SNESMonitorSolution()
128: @*/
129: PetscErrorCode  SNESLineSearchMonitorSolutionUpdate(SNESLineSearch ls,PetscViewerAndFormat *vf)
130: {
131:   PetscViewer    viewer = vf->viewer;
132:   Vec            Y,W,G;

134:   SNESLineSearchGetVecs(ls,NULL,NULL,&Y,&W,&G);
135:   PetscViewerPushFormat(viewer,vf->format);
136:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted update to solution \n");
137:   VecView(Y,viewer);
138:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted new solution \n");
139:   VecView(W,viewer);
140:   PetscViewerASCIIPrintf(viewer,"LineSearch attempted updated function value\n");
141:   VecView(G,viewer);
142:   PetscViewerPopFormat(viewer);
143:   return 0;
144: }

146: /*@
147:    SNESLineSearchCreate - Creates the line search context.

149:    Logically Collective on Comm

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

154:    Output Parameters:
155: .  outlinesearch - the new linesearch context

157:    Level: developer

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

163: .seealso: LineSearchDestroy(), SNESGetLineSearch()
164: @*/

166: PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch)
167: {
168:   SNESLineSearch linesearch;

171:   SNESInitializePackage();
172:   *outlinesearch = NULL;

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

176:   linesearch->vec_sol_new  = NULL;
177:   linesearch->vec_func_new = NULL;
178:   linesearch->vec_sol      = NULL;
179:   linesearch->vec_func     = NULL;
180:   linesearch->vec_update   = NULL;

182:   linesearch->lambda       = 1.0;
183:   linesearch->fnorm        = 1.0;
184:   linesearch->ynorm        = 1.0;
185:   linesearch->xnorm        = 1.0;
186:   linesearch->result       = SNES_LINESEARCH_SUCCEEDED;
187:   linesearch->norms        = PETSC_TRUE;
188:   linesearch->keeplambda   = PETSC_FALSE;
189:   linesearch->damping      = 1.0;
190:   linesearch->maxstep      = 1e8;
191:   linesearch->steptol      = 1e-12;
192:   linesearch->rtol         = 1e-8;
193:   linesearch->atol         = 1e-15;
194:   linesearch->ltol         = 1e-8;
195:   linesearch->precheckctx  = NULL;
196:   linesearch->postcheckctx = NULL;
197:   linesearch->max_its      = 1;
198:   linesearch->setupcalled  = PETSC_FALSE;
199:   linesearch->monitor      = NULL;
200:   *outlinesearch           = linesearch;
201:   return 0;
202: }

204: /*@
205:    SNESLineSearchSetUp - Prepares the line search for being applied by allocating
206:    any required vectors.

208:    Collective on SNESLineSearch

210:    Input Parameters:
211: .  linesearch - The LineSearch instance.

213:    Notes:
214:    For most cases, this needn't be called by users or outside of SNESLineSearchApply().
215:    The only current case where this is called outside of this is for the VI
216:    solvers, which modify the solution and work vectors before the first call
217:    of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be
218:    allocated upfront.

220:    Level: advanced

222: .seealso: SNESGetLineSearch(), SNESLineSearchReset()
223: @*/

225: PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch)
226: {
227:   if (!((PetscObject)linesearch)->type_name) {
228:     SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);
229:   }
230:   if (!linesearch->setupcalled) {
231:     if (!linesearch->vec_sol_new) {
232:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);
233:     }
234:     if (!linesearch->vec_func_new) {
235:       VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);
236:     }
237:     if (linesearch->ops->setup) {
238:       (*linesearch->ops->setup)(linesearch);
239:     }
240:     if (!linesearch->ops->snesfunc) SNESLineSearchSetFunction(linesearch,SNESComputeFunction);
241:     linesearch->lambda      = linesearch->damping;
242:     linesearch->setupcalled = PETSC_TRUE;
243:   }
244:   return 0;
245: }

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

250:    Collective on SNESLineSearch

252:    Input Parameters:
253: .  linesearch - The LineSearch instance.

255:    Notes:
256:     Usually only called by SNESReset()

258:    Level: developer

260: .seealso: SNESGetLineSearch(), SNESLineSearchSetUp()
261: @*/

263: PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch)
264: {
265:   if (linesearch->ops->reset) (*linesearch->ops->reset)(linesearch);

267:   VecDestroy(&linesearch->vec_sol_new);
268:   VecDestroy(&linesearch->vec_func_new);

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

272:   linesearch->nwork       = 0;
273:   linesearch->setupcalled = PETSC_FALSE;
274:   return 0;
275: }

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

280:    Input Parameters:
281: .  linesearch - the SNESLineSearch context
282: +  func       - function evaluation routine

284:    Level: developer

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

289: .seealso: SNESGetLineSearch(), SNESSetFunction()
290: @*/
291: PetscErrorCode  SNESLineSearchSetFunction(SNESLineSearch linesearch, PetscErrorCode (*func)(SNES,Vec,Vec))
292: {
294:   linesearch->ops->snesfunc = func;
295:   return 0;
296: }

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

303:    Logically Collective on SNESLineSearch

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

310:    Level: intermediate

312: .seealso: SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
313: @*/
314: PetscErrorCode  SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void *ctx)
315: {
317:   if (func) linesearch->ops->precheck = func;
318:   if (ctx) linesearch->precheckctx = ctx;
319:   return 0;
320: }

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

325:    Input Parameter:
326: .  linesearch - the SNESLineSearch context

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

332:    Level: intermediate

334: .seealso: SNESGetLineSearch(), SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck()
335: @*/
336: PetscErrorCode  SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**func)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void **ctx)
337: {
339:   if (func) *func = linesearch->ops->precheck;
340:   if (ctx) *ctx = linesearch->precheckctx;
341:   return 0;
342: }

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

348:    Logically Collective on SNESLineSearch

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

355:    Level: intermediate

357: .seealso: SNESGetLineSearch(), SNESLineSearchPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchGetPostCheck()
358: @*/
359: PetscErrorCode  SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*func)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx)
360: {
362:   if (func) linesearch->ops->postcheck = func;
363:   if (ctx) linesearch->postcheckctx = ctx;
364:   return 0;
365: }

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

370:    Input Parameter:
371: .  linesearch - the SNESLineSearch context

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

377:    Level: intermediate

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

389: /*@
390:    SNESLineSearchPreCheck - Prepares the line search for being applied.

392:    Logically Collective on SNESLineSearch

394:    Input Parameters:
395: +  linesearch - The linesearch instance.
396: .  X - The current solution
397: -  Y - The step direction

399:    Output Parameters:
400: .  changed - Indicator that the precheck routine has changed anything

402:    Level: developer

404: .seealso: SNESGetLineSearch(), SNESLineSearchPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck()
405: @*/
406: PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed)
407: {
408:   *changed = PETSC_FALSE;
409:   if (linesearch->ops->precheck) {
410:     (*linesearch->ops->precheck)(linesearch, X, Y, changed, linesearch->precheckctx);
412:   }
413:   return 0;
414: }

416: /*@
417:    SNESLineSearchPostCheck - Prepares the line search for being applied.

419:    Logically Collective on SNESLineSearch

421:    Input Parameters:
422: +  linesearch - The linesearch context
423: .  X - The last solution
424: .  Y - The step direction
425: -  W - The updated solution, W = X + lambda*Y for some lambda

427:    Output Parameters:
428: +  changed_Y - Indicator if the direction Y has been changed.
429: -  changed_W - Indicator if the new candidate solution W has been changed.

431:    Level: developer

433: .seealso: SNESGetLineSearch(), SNESLineSearchPreCheck(), SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchSetPrecheck(), SNESLineSearchGetPrecheck()
434: @*/
435: PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W)
436: {
437:   *changed_Y = PETSC_FALSE;
438:   *changed_W = PETSC_FALSE;
439:   if (linesearch->ops->postcheck) {
440:     (*linesearch->ops->postcheck)(linesearch,X,Y,W,changed_Y,changed_W,linesearch->postcheckctx);
443:   }
444:   return 0;
445: }

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

450:    Logically Collective on SNESLineSearch

452:    Input Parameters:
453: +  linesearch - linesearch context
454: .  X - base state for this step
455: -  ctx - context for this function

457:    Input/Output Parameter:
458: .  Y - correction, possibly modified

460:    Output Parameter:
461: .  changed - flag indicating that Y was modified

463:    Options Database Key:
464: +  -snes_linesearch_precheck_picard - activate this routine
465: -  -snes_linesearch_precheck_picard_angle - angle

467:    Level: advanced

469:    Notes:
470:    This function should be passed to SNESLineSearchSetPreCheck()

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

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

479: .seealso: SNESGetLineSearch(), SNESLineSearchSetPreCheck()
480: @*/
481: PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed,void *ctx)
482: {
483:   PetscReal      angle = *(PetscReal*)linesearch->precheckctx;
484:   Vec            Ylast;
485:   PetscScalar    dot;
486:   PetscInt       iter;
487:   PetscReal      ynorm,ylastnorm,theta,angle_radians;
488:   SNES           snes;

490:   SNESLineSearchGetSNES(linesearch, &snes);
491:   PetscObjectQuery((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject*)&Ylast);
492:   if (!Ylast) {
493:     VecDuplicate(Y,&Ylast);
494:     PetscObjectCompose((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject)Ylast);
495:     PetscObjectDereference((PetscObject)Ylast);
496:   }
497:   SNESGetIterationNumber(snes,&iter);
498:   if (iter < 2) {
499:     VecCopy(Y,Ylast);
500:     *changed = PETSC_FALSE;
501:     return 0;
502:   }

504:   VecDot(Y,Ylast,&dot);
505:   VecNorm(Y,NORM_2,&ynorm);
506:   VecNorm(Ylast,NORM_2,&ylastnorm);
507:   /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */
508:   theta         = PetscAcosReal((PetscReal)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm),-1.0,1.0));
509:   angle_radians = angle * PETSC_PI / 180.;
510:   if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) {
511:     /* Modify the step Y */
512:     PetscReal alpha,ydiffnorm;
513:     VecAXPY(Ylast,-1.0,Y);
514:     VecNorm(Ylast,NORM_2,&ydiffnorm);
515:     alpha = (ydiffnorm > .001*ylastnorm) ? ylastnorm / ydiffnorm : 1000.0;
516:     VecCopy(Y,Ylast);
517:     VecScale(Y,alpha);
518:     PetscInfo(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);
519:     *changed = PETSC_TRUE;
520:   } else {
521:     PetscInfo(snes,"Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n",(double)(theta*180./PETSC_PI),(double)angle);
522:     VecCopy(Y,Ylast);
523:     *changed = PETSC_FALSE;
524:   }
525:   return 0;
526: }

528: /*@
529:    SNESLineSearchApply - Computes the line-search update.

531:    Collective on SNESLineSearch

533:    Input Parameters:
534: +  linesearch - The linesearch context
535: -  Y - The search direction

537:    Input/Output Parameters:
538: +  X - The current solution, on output the new solution
539: .  F - The current function, on output the new function
540: -  fnorm - The current norm, on output the new function norm

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

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

558:    Level: Intermediate

560: .seealso: SNESGetLineSearch(), SNESLineSearchCreate(), SNESLineSearchPreCheck(), SNESLineSearchPostCheck(), SNESSolve(), SNESComputeFunction(), SNESLineSearchSetComputeNorms(),
561:           SNESLineSearchType, SNESLineSearchSetType()
562: @*/
563: PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y)
564: {

570:   linesearch->result = SNES_LINESEARCH_SUCCEEDED;

572:   linesearch->vec_sol    = X;
573:   linesearch->vec_update = Y;
574:   linesearch->vec_func   = F;

576:   SNESLineSearchSetUp(linesearch);

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

580:   if (fnorm) linesearch->fnorm = *fnorm;
581:   else {
582:     VecNorm(F, NORM_2, &linesearch->fnorm);
583:   }

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

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

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

591:   if (fnorm) *fnorm = linesearch->fnorm;
592:   return 0;
593: }

595: /*@
596:    SNESLineSearchDestroy - Destroys the line search instance.

598:    Collective on SNESLineSearch

600:    Input Parameters:
601: .  linesearch - The linesearch context

603:    Level: developer

605: .seealso: SNESGetLineSearch(), SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy()
606: @*/
607: PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch)
608: {
609:   if (!*linesearch) return 0;
611:   if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = NULL; return 0;}
612:   PetscObjectSAWsViewOff((PetscObject)*linesearch);
613:   SNESLineSearchReset(*linesearch);
614:   if ((*linesearch)->ops->destroy) (*linesearch)->ops->destroy(*linesearch);
615:   PetscViewerDestroy(&(*linesearch)->monitor);
616:   SNESLineSearchMonitorCancel((*linesearch));
617:   PetscHeaderDestroy(linesearch);
618:   return 0;
619: }

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

624:    Input Parameters:
625: +  linesearch - the linesearch object
626: -  viewer - an ASCII PetscViewer or NULL to turn off monitor

628:    Logically Collective on SNESLineSearch

630:    Options Database:
631: .   -snes_linesearch_monitor [:filename] - enables the monitor

633:    Level: intermediate

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

639: .seealso: SNESGetLineSearch(), SNESLineSearchGetDefaultMonitor(), PetscViewer, SNESLineSearchSetMonitor()
640: @*/
641: PetscErrorCode  SNESLineSearchSetDefaultMonitor(SNESLineSearch linesearch, PetscViewer viewer)
642: {
643:   if (viewer) PetscObjectReference((PetscObject)viewer);
644:   PetscViewerDestroy(&linesearch->monitor);
645:   linesearch->monitor = viewer;
646:   return 0;
647: }

649: /*@
650:    SNESLineSearchGetDefaultMonitor - Gets the PetscViewer instance for the line search monitor.

652:    Input Parameter:
653: .  linesearch - linesearch context

655:    Output Parameter:
656: .  monitor - monitor context

658:    Logically Collective on SNES

660:    Options Database Keys:
661: .   -snes_linesearch_monitor - enables the monitor

663:    Level: intermediate

665: .seealso: SNESGetLineSearch(), SNESLineSearchSetDefaultMonitor(), PetscViewer
666: @*/
667: PetscErrorCode  SNESLineSearchGetDefaultMonitor(SNESLineSearch linesearch, PetscViewer *monitor)
668: {
670:   *monitor = linesearch->monitor;
671:   return 0;
672: }

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

677:    Collective on SNESLineSearch

679:    Input Parameters:
680: +  ls - LineSearch object you wish to monitor
681: .  name - the monitor type one is seeking
682: .  help - message indicating what monitoring is done
683: .  manual - manual page for the monitor
684: .  monitor - the monitor function
685: -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the SNESLineSearch or PetscViewer objects

687:    Level: developer

689: .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
690:           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
691:           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
692:           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
693:           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
694:           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
695:           PetscOptionsFList(), PetscOptionsEList()
696: @*/
697: PetscErrorCode  SNESLineSearchMonitorSetFromOptions(SNESLineSearch ls,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(SNESLineSearch,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(SNESLineSearch,PetscViewerAndFormat*))
698: {
699:   PetscViewer       viewer;
700:   PetscViewerFormat format;
701:   PetscBool         flg;

703:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)ls),((PetscObject) ls)->options,((PetscObject)ls)->prefix,name,&viewer,&format,&flg);
704:   if (flg) {
705:     PetscViewerAndFormat *vf;
706:     PetscViewerAndFormatCreate(viewer,format,&vf);
707:     PetscObjectDereference((PetscObject)viewer);
708:     if (monitorsetup) {
709:       (*monitorsetup)(ls,vf);
710:     }
711:     SNESLineSearchMonitorSet(ls,(PetscErrorCode (*)(SNESLineSearch,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);
712:   }
713:   return 0;
714: }

716: /*@
717:    SNESLineSearchSetFromOptions - Sets options for the line search

719:    Input Parameter:
720: .  linesearch - linesearch context

722:    Options Database Keys:
723: + -snes_linesearch_type <type> - basic, bt, l2, cp, nleqerr, shell
724: . -snes_linesearch_order <order> - 1, 2, 3.  Most types only support certain orders (bt supports 2 or 3)
725: . -snes_linesearch_norms   - Turn on/off the linesearch norms for the basic linesearch typem (SNESLineSearchSetComputeNorms())
726: . -snes_linesearch_minlambda - The minimum step length
727: . -snes_linesearch_maxstep - The maximum step size
728: . -snes_linesearch_rtol - Relative tolerance for iterative line searches
729: . -snes_linesearch_atol - Absolute tolerance for iterative line searches
730: . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches
731: . -snes_linesearch_max_it - The number of iterations for iterative line searches
732: . -snes_linesearch_monitor [:filename] - Print progress of line searches
733: . -snes_linesearch_monitor_solution_update [viewer:filename:format] - view each update tried by line search routine
734: . -snes_linesearch_damping - The linesearch damping parameter
735: . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess.
736: . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method
737: - -snes_linesearch_precheck_picard_angle - Angle used in Picard precheck method

739:    Logically Collective on SNESLineSearch

741:    Level: intermediate

743: .seealso: SNESLineSearchCreate(), SNESLineSearchSetOrder(), SNESLineSearchSetType(), SNESLineSearchSetTolerances(), SNESLineSearchSetDamping(), SNESLineSearchPreCheckPicard(),
744:           SNESLineSearchType, SNESLineSearchSetComputeNorms()
745: @*/
746: PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch)
747: {
748:   PetscErrorCode    ierr;
749:   const char        *deft = SNESLINESEARCHBASIC;
750:   char              type[256];
751:   PetscBool         flg, set;
752:   PetscViewer       viewer;

754:   SNESLineSearchRegisterAll();

756:   PetscObjectOptionsBegin((PetscObject)linesearch);
757:   if (((PetscObject)linesearch)->type_name) deft = ((PetscObject)linesearch)->type_name;
758:   PetscOptionsFList("-snes_linesearch_type","Linesearch type","SNESLineSearchSetType",SNESLineSearchList,deft,type,256,&flg);
759:   if (flg) {
760:     SNESLineSearchSetType(linesearch,type);
761:   } else if (!((PetscObject)linesearch)->type_name) {
762:     SNESLineSearchSetType(linesearch,deft);
763:   }

765:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)linesearch),((PetscObject) linesearch)->options,((PetscObject)linesearch)->prefix,"-snes_linesearch_monitor",&viewer,NULL,&set);
766:   if (set) {
767:     SNESLineSearchSetDefaultMonitor(linesearch,viewer);
768:     PetscViewerDestroy(&viewer);
769:   }
770:   SNESLineSearchMonitorSetFromOptions(linesearch,"-snes_linesearch_monitor_solution_update","View correction at each iteration","SNESLineSearchMonitorSolutionUpdate",SNESLineSearchMonitorSolutionUpdate,NULL);

772:   /* tolerances */
773:   PetscOptionsReal("-snes_linesearch_minlambda","Minimum step length","SNESLineSearchSetTolerances",linesearch->steptol,&linesearch->steptol,NULL);
774:   PetscOptionsReal("-snes_linesearch_maxstep","Maximum step size","SNESLineSearchSetTolerances",linesearch->maxstep,&linesearch->maxstep,NULL);
775:   PetscOptionsReal("-snes_linesearch_rtol","Relative tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->rtol,&linesearch->rtol,NULL);
776:   PetscOptionsReal("-snes_linesearch_atol","Absolute tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->atol,&linesearch->atol,NULL);
777:   PetscOptionsReal("-snes_linesearch_ltol","Change in lambda tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->ltol,&linesearch->ltol,NULL);
778:   PetscOptionsInt("-snes_linesearch_max_it","Maximum iterations for iterative line searches","SNESLineSearchSetTolerances",linesearch->max_its,&linesearch->max_its,NULL);

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

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

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

791:       PetscOptionsReal("-snes_linesearch_precheck_picard_angle","Maximum angle at which to activate the correction",
792:                               "none",linesearch->precheck_picard_angle,&linesearch->precheck_picard_angle,NULL);
793:       SNESLineSearchSetPreCheck(linesearch,SNESLineSearchPreCheckPicard,&linesearch->precheck_picard_angle);
794:     } else {
795:       SNESLineSearchSetPreCheck(linesearch,NULL,NULL);
796:     }
797:   }
798:   PetscOptionsInt("-snes_linesearch_order","Order of approximation used in the line search","SNESLineSearchSetOrder",linesearch->order,&linesearch->order,NULL);
799:   PetscOptionsBool("-snes_linesearch_norms","Compute final norms in line search","SNESLineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,NULL);

801:   if (linesearch->ops->setfromoptions) {
802:     (*linesearch->ops->setfromoptions)(PetscOptionsObject,linesearch);
803:   }

805:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)linesearch);
806:   PetscOptionsEnd();
807:   return 0;
808: }

810: /*@
811:    SNESLineSearchView - Prints useful information about the line search

813:    Input Parameters:
814: .  linesearch - linesearch context

816:    Logically Collective on SNESLineSearch

818:    Level: intermediate

820: .seealso: SNESLineSearchCreate()
821: @*/
822: PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer)
823: {
824:   PetscBool      iascii;

827:   if (!viewer) {
828:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)linesearch),&viewer);
829:   }

833:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
834:   if (iascii) {
835:     PetscObjectPrintClassNamePrefixType((PetscObject)linesearch,viewer);
836:     if (linesearch->ops->view) {
837:       PetscViewerASCIIPushTab(viewer);
838:       (*linesearch->ops->view)(linesearch,viewer);
839:       PetscViewerASCIIPopTab(viewer);
840:     }
841:     PetscViewerASCIIPrintf(viewer,"  maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol);
842:     PetscViewerASCIIPrintf(viewer,"  tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol);
843:     PetscViewerASCIIPrintf(viewer,"  maximum iterations=%D\n", linesearch->max_its);
844:     if (linesearch->ops->precheck) {
845:       if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) {
846:         PetscViewerASCIIPrintf(viewer,"  using precheck step to speed up Picard convergence\n", linesearch->max_its);
847:       } else {
848:         PetscViewerASCIIPrintf(viewer,"  using user-defined precheck step\n", linesearch->max_its);
849:       }
850:     }
851:     if (linesearch->ops->postcheck) {
852:       PetscViewerASCIIPrintf(viewer,"  using user-defined postcheck step\n", linesearch->max_its);
853:     }
854:   }
855:   return 0;
856: }

858: /*@C
859:    SNESLineSearchGetType - Gets the linesearch type

861:    Logically Collective on SNESLineSearch

863:    Input Parameters:
864: .  linesearch - linesearch context

866:    Output Parameters:
867: -  type - The type of line search, or NULL if not set

869:    Level: intermediate

871: .seealso: SNESLineSearchCreate(), SNESLineSearchType, SNESLineSearchSetFromOptions(), SNESLineSearchSetType()
872: @*/
873: PetscErrorCode SNESLineSearchGetType(SNESLineSearch linesearch, SNESLineSearchType *type)
874: {
877:   *type = ((PetscObject)linesearch)->type_name;
878:   return 0;
879: }

881: /*@C
882:    SNESLineSearchSetType - Sets the linesearch type

884:    Logically Collective on SNESLineSearch

886:    Input Parameters:
887: +  linesearch - linesearch context
888: -  type - The type of line search to be used

890:    Available Types:
891: +  SNESLINESEARCHBASIC - Simple damping line search, defaults to using the full Newton step
892: .  SNESLINESEARCHBT - Backtracking line search over the L2 norm of the function
893: .  SNESLINESEARCHL2 - Secant line search over the L2 norm of the function
894: .  SNESLINESEARCHCP - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x)
895: .  SNESLINESEARCHNLEQERR - Affine-covariant error-oriented linesearch
896: -  SNESLINESEARCHSHELL - User provided SNESLineSearch implementation

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

901:    Level: intermediate

903: .seealso: SNESLineSearchCreate(), SNESLineSearchType, SNESLineSearchSetFromOptions(), SNESLineSearchGetType()
904: @*/
905: PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type)
906: {
907:   PetscBool      match;
908:   PetscErrorCode (*r)(SNESLineSearch);


913:   PetscObjectTypeCompare((PetscObject)linesearch,type,&match);
914:   if (match) return 0;

916:   PetscFunctionListFind(SNESLineSearchList,type,&r);
918:   /* Destroy the previous private linesearch context */
919:   if (linesearch->ops->destroy) {
920:     (*(linesearch)->ops->destroy)(linesearch);
921:     linesearch->ops->destroy = NULL;
922:   }
923:   /* Reinitialize function pointers in SNESLineSearchOps structure */
924:   linesearch->ops->apply          = NULL;
925:   linesearch->ops->view           = NULL;
926:   linesearch->ops->setfromoptions = NULL;
927:   linesearch->ops->destroy        = NULL;

929:   PetscObjectChangeTypeName((PetscObject)linesearch,type);
930:   (*r)(linesearch);
931:   return 0;
932: }

934: /*@
935:    SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation.

937:    Input Parameters:
938: +  linesearch - linesearch context
939: -  snes - The snes instance

941:    Level: developer

943:    Notes:
944:    This happens automatically when the line search is obtained/created with
945:    SNESGetLineSearch().  This routine is therefore mainly called within SNES
946:    implementations.

948:    Level: developer

950: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
951: @*/
952: PetscErrorCode  SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes)
953: {
956:   linesearch->snes = snes;
957:   return 0;
958: }

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

966:    Input Parameters:
967: .  linesearch - linesearch context

969:    Output Parameters:
970: .  snes - The snes instance

972:    Level: developer

974: .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES
975: @*/
976: PetscErrorCode  SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes)
977: {
980:   *snes = linesearch->snes;
981:   return 0;
982: }

984: /*@
985:    SNESLineSearchGetLambda - Gets the last linesearch steplength discovered.

987:    Input Parameters:
988: .  linesearch - linesearch context

990:    Output Parameters:
991: .  lambda - The last steplength computed during SNESLineSearchApply()

993:    Level: advanced

995:    Notes:
996:    This is useful in methods where the solver is ill-scaled and
997:    requires some adaptive notion of the difference in scale between the
998:    solution and the function.  For instance, SNESQN may be scaled by the
999:    line search lambda using the argument -snes_qn_scaling ls.

1001: .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply()
1002: @*/
1003: PetscErrorCode  SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda)
1004: {
1007:   *lambda = linesearch->lambda;
1008:   return 0;
1009: }

1011: /*@
1012:    SNESLineSearchSetLambda - Sets the linesearch steplength.

1014:    Input Parameters:
1015: +  linesearch - linesearch context
1016: -  lambda - The last steplength.

1018:    Notes:
1019:    This routine is typically used within implementations of SNESLineSearchApply()
1020:    to set the final steplength.  This routine (and SNESLineSearchGetLambda()) were
1021:    added in order to facilitate Quasi-Newton methods that use the previous steplength
1022:    as an inner scaling parameter.

1024:    Level: advanced

1026: .seealso: SNESLineSearchGetLambda()
1027: @*/
1028: PetscErrorCode  SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda)
1029: {
1031:   linesearch->lambda = lambda;
1032:   return 0;
1033: }

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

1041:    Input Parameter:
1042: .  linesearch - linesearch context

1044:    Output Parameters:
1045: +  steptol - The minimum steplength
1046: .  maxstep - The maximum steplength
1047: .  rtol    - The relative tolerance for iterative line searches
1048: .  atol    - The absolute tolerance for iterative line searches
1049: .  ltol    - The change in lambda tolerance for iterative line searches
1050: -  max_it  - The maximum number of iterations of the line search

1052:    Level: intermediate

1054:    Notes:
1055:    Different line searches may implement these parameters slightly differently as
1056:    the type requires.

1058: .seealso: SNESLineSearchSetTolerances()
1059: @*/
1060: PetscErrorCode  SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its)
1061: {
1063:   if (steptol) {
1065:     *steptol = linesearch->steptol;
1066:   }
1067:   if (maxstep) {
1069:     *maxstep = linesearch->maxstep;
1070:   }
1071:   if (rtol) {
1073:     *rtol = linesearch->rtol;
1074:   }
1075:   if (atol) {
1077:     *atol = linesearch->atol;
1078:   }
1079:   if (ltol) {
1081:     *ltol = linesearch->ltol;
1082:   }
1083:   if (max_its) {
1085:     *max_its = linesearch->max_its;
1086:   }
1087:   return 0;
1088: }

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

1096:    Input Parameters:
1097: +  linesearch - linesearch context
1098: .  steptol - The minimum steplength
1099: .  maxstep - The maximum steplength
1100: .  rtol    - The relative tolerance for iterative line searches
1101: .  atol    - The absolute tolerance for iterative line searches
1102: .  ltol    - The change in lambda tolerance for iterative line searches
1103: -  max_it  - The maximum number of iterations of the line search

1105:    Notes:
1106:    The user may choose to not set any of the tolerances using PETSC_DEFAULT in
1107:    place of an argument.

1109:    Level: intermediate

1111: .seealso: SNESLineSearchGetTolerances()
1112: @*/
1113: PetscErrorCode  SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its)
1114: {

1123:   if (steptol!= PETSC_DEFAULT) {
1125:     linesearch->steptol = steptol;
1126:   }

1128:   if (maxstep!= PETSC_DEFAULT) {
1130:     linesearch->maxstep = maxstep;
1131:   }

1133:   if (rtol != PETSC_DEFAULT) {
1135:     linesearch->rtol = rtol;
1136:   }

1138:   if (atol != PETSC_DEFAULT) {
1140:     linesearch->atol = atol;
1141:   }

1143:   if (ltol != PETSC_DEFAULT) {
1145:     linesearch->ltol = ltol;
1146:   }

1148:   if (max_its != PETSC_DEFAULT) {
1150:     linesearch->max_its = max_its;
1151:   }
1152:   return 0;
1153: }

1155: /*@
1156:    SNESLineSearchGetDamping - Gets the line search damping parameter.

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

1161:    Output Parameters:
1162: .  damping - The damping parameter

1164:    Level: advanced

1166: .seealso: SNESLineSearchGetStepTolerance(), SNESQN
1167: @*/

1169: PetscErrorCode  SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping)
1170: {
1173:   *damping = linesearch->damping;
1174:   return 0;
1175: }

1177: /*@
1178:    SNESLineSearchSetDamping - Sets the line search damping parameter.

1180:    Input Parameters:
1181: +  linesearch - linesearch context
1182: -  damping - The damping parameter

1184:    Options Database:
1185: .   -snes_linesearch_damping
1186:    Level: intermediate

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

1195: .seealso: SNESLineSearchGetDamping()
1196: @*/
1197: PetscErrorCode  SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping)
1198: {
1200:   linesearch->damping = damping;
1201:   return 0;
1202: }

1204: /*@
1205:    SNESLineSearchGetOrder - Gets the line search approximation order.

1207:    Input Parameters:
1208: .  linesearch - linesearch context

1210:    Output Parameters:
1211: .  order - The order

1213:    Possible Values for order:
1214: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
1215: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
1216: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

1218:    Level: intermediate

1220: .seealso: SNESLineSearchSetOrder()
1221: @*/

1223: PetscErrorCode  SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order)
1224: {
1227:   *order = linesearch->order;
1228:   return 0;
1229: }

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

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

1238:    Level: intermediate

1240:    Possible Values for order:
1241: +  1 or SNES_LINESEARCH_ORDER_LINEAR - linear order
1242: .  2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order
1243: -  3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order

1245:    Notes:
1246:    Variable orders are supported by the following line searches:
1247: +  bt - cubic and quadratic
1248: -  cp - linear and quadratic

1250: .seealso: SNESLineSearchGetOrder(), SNESLineSearchSetDamping()
1251: @*/
1252: PetscErrorCode  SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order)
1253: {
1255:   linesearch->order = order;
1256:   return 0;
1257: }

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

1262:    Input Parameter:
1263: .  linesearch - linesearch context

1265:    Output Parameters:
1266: +  xnorm - The norm of the current solution
1267: .  fnorm - The norm of the current function
1268: -  ynorm - The norm of the current update

1270:    Notes:
1271:    This function is mainly called from SNES implementations.

1273:    Level: developer

1275: .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs()
1276: @*/
1277: PetscErrorCode  SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm)
1278: {
1280:   if (xnorm) *xnorm = linesearch->xnorm;
1281:   if (fnorm) *fnorm = linesearch->fnorm;
1282:   if (ynorm) *ynorm = linesearch->ynorm;
1283:   return 0;
1284: }

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

1289:    Input Parameters:
1290: +  linesearch - linesearch context
1291: .  xnorm - The norm of the current solution
1292: .  fnorm - The norm of the current function
1293: -  ynorm - The norm of the current update

1295:    Level: advanced

1297: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
1298: @*/
1299: PetscErrorCode  SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm)
1300: {
1302:   linesearch->xnorm = xnorm;
1303:   linesearch->fnorm = fnorm;
1304:   linesearch->ynorm = ynorm;
1305:   return 0;
1306: }

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

1311:    Input Parameters:
1312: .  linesearch - linesearch context

1314:    Options Database Keys:
1315: .   -snes_linesearch_norms - turn norm computation on or off

1317:    Level: intermediate

1319: .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms()
1320: @*/
1321: PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch)
1322: {
1323:   SNES           snes;

1325:   if (linesearch->norms) {
1326:     if (linesearch->ops->vinorm) {
1327:       SNESLineSearchGetSNES(linesearch, &snes);
1328:       VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);
1329:       VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1330:       (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);
1331:     } else {
1332:       VecNormBegin(linesearch->vec_func,   NORM_2, &linesearch->fnorm);
1333:       VecNormBegin(linesearch->vec_sol,    NORM_2, &linesearch->xnorm);
1334:       VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);
1335:       VecNormEnd(linesearch->vec_func,     NORM_2, &linesearch->fnorm);
1336:       VecNormEnd(linesearch->vec_sol,      NORM_2, &linesearch->xnorm);
1337:       VecNormEnd(linesearch->vec_update,   NORM_2, &linesearch->ynorm);
1338:     }
1339:   }
1340:   return 0;
1341: }

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

1346:    Input Parameters:
1347: +  linesearch  - linesearch context
1348: -  flg  - indicates whether or not to compute norms

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

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

1356:    Level: intermediate

1358: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC
1359: @*/
1360: PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg)
1361: {
1362:   linesearch->norms = flg;
1363:   return 0;
1364: }

1366: /*@
1367:    SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context

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

1372:    Output Parameters:
1373: +  X - Solution vector
1374: .  F - Function vector
1375: .  Y - Search direction vector
1376: .  W - Solution work vector
1377: -  G - Function work vector

1379:    Notes:
1380:    At the beginning of a line search application, X should contain a
1381:    solution and the vector F the function computed at X.  At the end of the
1382:    line search application, X should contain the new solution, and F the
1383:    function evaluated at the new solution.

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

1387:    Level: advanced

1389: .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs()
1390: @*/
1391: PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G)
1392: {
1394:   if (X) {
1396:     *X = linesearch->vec_sol;
1397:   }
1398:   if (F) {
1400:     *F = linesearch->vec_func;
1401:   }
1402:   if (Y) {
1404:     *Y = linesearch->vec_update;
1405:   }
1406:   if (W) {
1408:     *W = linesearch->vec_sol_new;
1409:   }
1410:   if (G) {
1412:     *G = linesearch->vec_func_new;
1413:   }
1414:   return 0;
1415: }

1417: /*@
1418:    SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context

1420:    Input Parameters:
1421: +  linesearch - linesearch context
1422: .  X - Solution vector
1423: .  F - Function vector
1424: .  Y - Search direction vector
1425: .  W - Solution work vector
1426: -  G - Function work vector

1428:    Level: advanced

1430: .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs()
1431: @*/
1432: PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G)
1433: {
1435:   if (X) {
1437:     linesearch->vec_sol = X;
1438:   }
1439:   if (F) {
1441:     linesearch->vec_func = F;
1442:   }
1443:   if (Y) {
1445:     linesearch->vec_update = Y;
1446:   }
1447:   if (W) {
1449:     linesearch->vec_sol_new = W;
1450:   }
1451:   if (G) {
1453:     linesearch->vec_func_new = G;
1454:   }
1455:   return 0;
1456: }

1458: /*@C
1459:    SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all
1460:    SNES options in the database.

1462:    Logically Collective on SNESLineSearch

1464:    Input Parameters:
1465: +  snes - the SNES context
1466: -  prefix - the prefix to prepend to all option names

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

1472:    Level: advanced

1474: .seealso: SNESGetOptionsPrefix()
1475: @*/
1476: PetscErrorCode  SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[])
1477: {
1479:   PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);
1480:   return 0;
1481: }

1483: /*@C
1484:    SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all
1485:    SNESLineSearch options in the database.

1487:    Not Collective

1489:    Input Parameter:
1490: .  linesearch - the SNESLineSearch context

1492:    Output Parameter:
1493: .  prefix - pointer to the prefix string used

1495:    Notes:
1496:    On the fortran side, the user should pass in a string 'prefix' of
1497:    sufficient length to hold the prefix.

1499:    Level: advanced

1501: .seealso: SNESAppendOptionsPrefix()
1502: @*/
1503: PetscErrorCode  SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[])
1504: {
1506:   PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);
1507:   return 0;
1508: }

1510: /*@C
1511:    SNESLineSearchSetWorkVecs - Gets work vectors for the line search.

1513:    Input Parameters:
1514: +  linesearch - the SNESLineSearch context
1515: -  nwork - the number of work vectors

1517:    Level: developer

1519: .seealso: SNESSetWorkVecs()
1520: @*/
1521: PetscErrorCode  SNESLineSearchSetWorkVecs(SNESLineSearch linesearch, PetscInt nwork)
1522: {
1523:   if (linesearch->vec_sol) {
1524:     VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);
1525:   } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!");
1526:   return 0;
1527: }

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

1532:    Input Parameters:
1533: .  linesearch - linesearch context

1535:    Output Parameters:
1536: .  result - The success or failure status

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

1542:    Level: intermediate

1544: .seealso: SNESLineSearchSetReason(), SNESLineSearchReason
1545: @*/
1546: PetscErrorCode  SNESLineSearchGetReason(SNESLineSearch linesearch, SNESLineSearchReason *result)
1547: {
1550:   *result = linesearch->result;
1551:   return 0;
1552: }

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

1557:    Input Parameters:
1558: +  linesearch - linesearch context
1559: -  result - 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: SNESLineSearchGetSResult()
1568: @*/
1569: PetscErrorCode  SNESLineSearchSetReason(SNESLineSearch linesearch, SNESLineSearchReason result)
1570: {
1572:   linesearch->result = result;
1573:   return 0;
1574: }

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

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

1584:    Logically Collective on SNES

1586:    Calling sequence of projectfunc:
1587: .vb
1588:    projectfunc (SNES snes, Vec X)
1589: .ve

1591:     Input parameters for projectfunc:
1592: +   snes - nonlinear context
1593: -   X - current solution

1595:     Output parameters for projectfunc:
1596: .   X - Projected solution

1598:    Calling sequence of normfunc:
1599: .vb
1600:    projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm)
1601: .ve

1603:     Input parameters for normfunc:
1604: +   snes - nonlinear context
1605: .   X - current solution
1606: -   F - current residual

1608:     Output parameters for normfunc:
1609: .   fnorm - VI-specific norm of the function

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

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

1617:     Level: developer

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

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

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

1635:    Output Parameters:
1636: +  projectfunc - function for projecting the function to the bounds
1637: -  normfunc - function for computing the norm of an active set

1639:    Logically Collective on SNES

1641:     Level: developer

1643: .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck()
1644: @*/
1645: PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc)
1646: {
1647:   if (projectfunc) *projectfunc = linesearch->ops->viproject;
1648:   if (normfunc) *normfunc = linesearch->ops->vinorm;
1649:   return 0;
1650: }

1652: /*@C
1653:   SNESLineSearchRegister - See SNESLineSearchRegister()

1655:   Level: advanced
1656: @*/
1657: PetscErrorCode  SNESLineSearchRegister(const char sname[],PetscErrorCode (*function)(SNESLineSearch))
1658: {
1659:   SNESInitializePackage();
1660:   PetscFunctionListAdd(&SNESLineSearchList,sname,function);
1661:   return 0;
1662: }