xref: /petsc/src/snes/impls/tr/tr.c (revision 5e28bcb6eb89755d887ff19df10fe7e2cb7942ae) !
14800dd8cSBarry Smith 
2c6db04a5SJed Brown #include <../src/snes/impls/tr/trimpl.h>                /*I   "petscsnes.h"   I*/
34800dd8cSBarry Smith 
4971273eeSBarry Smith typedef struct {
5971273eeSBarry Smith   SNES           snes;
6df8705c3SBarry Smith   /*  Information on the regular SNES convergence test; which may have been user provided */
7df8705c3SBarry Smith   PetscErrorCode (*convtest)(KSP,PetscInt,PetscReal,KSPConvergedReason*,void*);
8df8705c3SBarry Smith   PetscErrorCode (*convdestroy)(void*);
9df8705c3SBarry Smith   void           *convctx;
10971273eeSBarry Smith } SNES_TR_KSPConverged_Ctx;
11971273eeSBarry Smith 
12470880abSPatrick Sanan static PetscErrorCode SNESTR_KSPConverged_Private(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *cctx)
13df60cc22SBarry Smith {
14971273eeSBarry Smith   SNES_TR_KSPConverged_Ctx *ctx = (SNES_TR_KSPConverged_Ctx*)cctx;
15971273eeSBarry Smith   SNES                     snes = ctx->snes;
1604d7464bSBarry Smith   SNES_NEWTONTR            *neP = (SNES_NEWTONTR*)snes->data;
17df60cc22SBarry Smith   Vec                      x;
18064f8208SBarry Smith   PetscReal                nrm;
19dfbe8321SBarry Smith   PetscErrorCode           ierr;
20df60cc22SBarry Smith 
213a40ed3dSBarry Smith   PetscFunctionBegin;
22df8705c3SBarry Smith   ierr = (*ctx->convtest)(ksp,n,rnorm,reason,ctx->convctx);CHKERRQ(ierr);
23329f5518SBarry Smith   if (*reason) {
24df8705c3SBarry Smith     ierr = PetscInfo2(snes,"Default or user provided convergence test KSP iterations=%D, rnorm=%g\n",n,(double)rnorm);CHKERRQ(ierr);
259b04593eSLois Curfman McInnes   }
26a935fc98SLois Curfman McInnes   /* Determine norm of solution */
2778b31e54SBarry Smith   ierr = KSPBuildSolution(ksp,0,&x);CHKERRQ(ierr);
28064f8208SBarry Smith   ierr = VecNorm(x,NORM_2,&nrm);CHKERRQ(ierr);
29064f8208SBarry Smith   if (nrm >= neP->delta) {
3057622a8eSBarry Smith     ierr    = PetscInfo2(snes,"Ending linear iteration early, delta=%g, length=%g\n",(double)neP->delta,(double)nrm);CHKERRQ(ierr);
31329f5518SBarry Smith     *reason = KSP_CONVERGED_STEP_LENGTH;
32df60cc22SBarry Smith   }
333a40ed3dSBarry Smith   PetscFunctionReturn(0);
34df60cc22SBarry Smith }
3582bf6240SBarry Smith 
36470880abSPatrick Sanan static PetscErrorCode SNESTR_KSPConverged_Destroy(void *cctx)
37971273eeSBarry Smith {
38971273eeSBarry Smith   SNES_TR_KSPConverged_Ctx *ctx = (SNES_TR_KSPConverged_Ctx*)cctx;
39971273eeSBarry Smith   PetscErrorCode           ierr;
40971273eeSBarry Smith 
41971273eeSBarry Smith   PetscFunctionBegin;
42df8705c3SBarry Smith   ierr = (*ctx->convdestroy)(ctx->convctx);CHKERRQ(ierr);
43971273eeSBarry Smith   ierr = PetscFree(ctx);CHKERRQ(ierr);
44971273eeSBarry Smith   PetscFunctionReturn(0);
45971273eeSBarry Smith }
46971273eeSBarry Smith 
4785385478SLisandro Dalcin /* ---------------------------------------------------------------- */
4885385478SLisandro Dalcin /*
49470880abSPatrick Sanan    SNESTR_Converged_Private -test convergence JUST for
5085385478SLisandro Dalcin    the trust region tolerance.
5185385478SLisandro Dalcin 
5285385478SLisandro Dalcin */
53470880abSPatrick Sanan static PetscErrorCode SNESTR_Converged_Private(SNES snes,PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
5485385478SLisandro Dalcin {
5504d7464bSBarry Smith   SNES_NEWTONTR  *neP = (SNES_NEWTONTR*)snes->data;
5685385478SLisandro Dalcin   PetscErrorCode ierr;
5785385478SLisandro Dalcin 
5885385478SLisandro Dalcin   PetscFunctionBegin;
5985385478SLisandro Dalcin   *reason = SNES_CONVERGED_ITERATING;
6085385478SLisandro Dalcin   if (neP->delta < xnorm * snes->deltatol) {
6157622a8eSBarry Smith     ierr    = PetscInfo3(snes,"Converged due to trust region param %g<%g*%g\n",(double)neP->delta,(double)xnorm,(double)snes->deltatol);CHKERRQ(ierr);
621c6b2ff8SBarry Smith     *reason = SNES_DIVERGED_TR_DELTA;
63e71169deSBarry Smith   } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) {
6485385478SLisandro Dalcin     ierr    = PetscInfo1(snes,"Exceeded maximum number of function evaluations: %D\n",snes->max_funcs);CHKERRQ(ierr);
6585385478SLisandro Dalcin     *reason = SNES_DIVERGED_FUNCTION_COUNT;
6685385478SLisandro Dalcin   }
6785385478SLisandro Dalcin   PetscFunctionReturn(0);
6885385478SLisandro Dalcin }
6985385478SLisandro Dalcin 
707cb011f5SBarry Smith /*@C
71c9368356SGlenn Hammond    SNESNewtonTRSetPreCheck - Sets a user function that is called before the search step has been determined.
72c9368356SGlenn Hammond        Allows the user a chance to change or override the decision of the line search routine.
73c9368356SGlenn Hammond 
74c9368356SGlenn Hammond    Logically Collective on snes
75c9368356SGlenn Hammond 
76c9368356SGlenn Hammond    Input Parameters:
77c9368356SGlenn Hammond +  snes - the nonlinear solver object
78c9368356SGlenn Hammond .  func - [optional] function evaluation routine, see SNESNewtonTRPreCheck()  for the calling sequence
79c9368356SGlenn Hammond -  ctx  - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
80c9368356SGlenn Hammond 
81c9368356SGlenn Hammond    Level: intermediate
82c9368356SGlenn Hammond 
83c9368356SGlenn Hammond    Note: This function is called BEFORE the function evaluation within the SNESNEWTONTR solver.
84c9368356SGlenn Hammond 
853312a946SBarry Smith .seealso: SNESNewtonTRPreCheck(), SNESNewtonTRGetPreCheck(), SNESNewtonTRSetPostCheck(), SNESNewtonTRGetPostCheck()
86c9368356SGlenn Hammond @*/
87c9368356SGlenn Hammond PetscErrorCode  SNESNewtonTRSetPreCheck(SNES snes, PetscErrorCode (*func)(SNES,Vec,Vec,PetscBool*,void*),void *ctx)
88c9368356SGlenn Hammond {
89c9368356SGlenn Hammond   SNES_NEWTONTR  *tr = (SNES_NEWTONTR*)snes->data;
90c9368356SGlenn Hammond 
91c9368356SGlenn Hammond   PetscFunctionBegin;
92c9368356SGlenn Hammond   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
93c9368356SGlenn Hammond   if (func) tr->precheck    = func;
94c9368356SGlenn Hammond   if (ctx)  tr->precheckctx = ctx;
95c9368356SGlenn Hammond   PetscFunctionReturn(0);
96c9368356SGlenn Hammond }
97c9368356SGlenn Hammond 
98c9368356SGlenn Hammond /*@C
99c9368356SGlenn Hammond    SNESNewtonTRGetPreCheck - Gets the pre-check function
100c9368356SGlenn Hammond 
101c9368356SGlenn Hammond    Not collective
102c9368356SGlenn Hammond 
103c9368356SGlenn Hammond    Input Parameter:
104c9368356SGlenn Hammond .  snes - the nonlinear solver context
105c9368356SGlenn Hammond 
106c9368356SGlenn Hammond    Output Parameters:
107c9368356SGlenn Hammond +  func - [optional] function evaluation routine, see for the calling sequence SNESNewtonTRPreCheck()
108c9368356SGlenn Hammond -  ctx  - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
109c9368356SGlenn Hammond 
110c9368356SGlenn Hammond    Level: intermediate
111c9368356SGlenn Hammond 
112c9368356SGlenn Hammond .seealso: SNESNewtonTRSetPreCheck(), SNESNewtonTRPreCheck()
113c9368356SGlenn Hammond @*/
114c9368356SGlenn Hammond PetscErrorCode  SNESNewtonTRGetPreCheck(SNES snes, PetscErrorCode (**func)(SNES,Vec,Vec,PetscBool*,void*),void **ctx)
115c9368356SGlenn Hammond {
116c9368356SGlenn Hammond   SNES_NEWTONTR  *tr = (SNES_NEWTONTR*)snes->data;
117c9368356SGlenn Hammond 
118c9368356SGlenn Hammond   PetscFunctionBegin;
119c9368356SGlenn Hammond   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
120c9368356SGlenn Hammond   if (func) *func = tr->precheck;
121c9368356SGlenn Hammond   if (ctx)  *ctx  = tr->precheckctx;
122c9368356SGlenn Hammond   PetscFunctionReturn(0);
123c9368356SGlenn Hammond }
124c9368356SGlenn Hammond 
125c9368356SGlenn Hammond /*@C
1267cb011f5SBarry Smith    SNESNewtonTRSetPostCheck - Sets a user function that is called after the search step has been determined but before the next
1277cb011f5SBarry Smith        function evaluation. Allows the user a chance to change or override the decision of the line search routine
1287cb011f5SBarry Smith 
1297cb011f5SBarry Smith    Logically Collective on snes
1307cb011f5SBarry Smith 
1317cb011f5SBarry Smith    Input Parameters:
1327cb011f5SBarry Smith +  snes - the nonlinear solver object
1337cb011f5SBarry Smith .  func - [optional] function evaluation routine, see SNESNewtonTRPostCheck()  for the calling sequence
1347cb011f5SBarry Smith -  ctx  - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
1357cb011f5SBarry Smith 
1367cb011f5SBarry Smith    Level: intermediate
1377cb011f5SBarry Smith 
138c9368356SGlenn Hammond    Note: This function is called BEFORE the function evaluation within the SNESNEWTONTR solver while the function set in
1397cb011f5SBarry Smith    SNESLineSearchSetPostCheck() is called AFTER the function evaluation.
1407cb011f5SBarry Smith 
1417cb011f5SBarry Smith .seealso: SNESNewtonTRPostCheck(), SNESNewtonTRGetPostCheck()
1427cb011f5SBarry Smith @*/
143c9368356SGlenn Hammond PetscErrorCode  SNESNewtonTRSetPostCheck(SNES snes, PetscErrorCode (*func)(SNES,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx)
1447cb011f5SBarry Smith {
1457cb011f5SBarry Smith   SNES_NEWTONTR  *tr = (SNES_NEWTONTR*)snes->data;
1467cb011f5SBarry Smith 
1477cb011f5SBarry Smith   PetscFunctionBegin;
1487cb011f5SBarry Smith   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1497cb011f5SBarry Smith   if (func) tr->postcheck    = func;
1507cb011f5SBarry Smith   if (ctx)  tr->postcheckctx = ctx;
1517cb011f5SBarry Smith   PetscFunctionReturn(0);
1527cb011f5SBarry Smith }
1537cb011f5SBarry Smith 
1547cb011f5SBarry Smith /*@C
1557cb011f5SBarry Smith    SNESNewtonTRGetPostCheck - Gets the post-check function
1567cb011f5SBarry Smith 
1577cb011f5SBarry Smith    Not collective
1587cb011f5SBarry Smith 
1597cb011f5SBarry Smith    Input Parameter:
1607cb011f5SBarry Smith .  snes - the nonlinear solver context
1617cb011f5SBarry Smith 
1627cb011f5SBarry Smith    Output Parameters:
1637cb011f5SBarry Smith +  func - [optional] function evaluation routine, see for the calling sequence SNESNewtonTRPostCheck()
1647cb011f5SBarry Smith -  ctx  - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
1657cb011f5SBarry Smith 
1667cb011f5SBarry Smith    Level: intermediate
1677cb011f5SBarry Smith 
1687cb011f5SBarry Smith .seealso: SNESNewtonTRSetPostCheck(), SNESNewtonTRPostCheck()
1697cb011f5SBarry Smith @*/
170c9368356SGlenn Hammond PetscErrorCode  SNESNewtonTRGetPostCheck(SNES snes, PetscErrorCode (**func)(SNES,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void **ctx)
1717cb011f5SBarry Smith {
1727cb011f5SBarry Smith   SNES_NEWTONTR  *tr = (SNES_NEWTONTR*)snes->data;
1737cb011f5SBarry Smith 
1747cb011f5SBarry Smith   PetscFunctionBegin;
1757cb011f5SBarry Smith   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1767cb011f5SBarry Smith   if (func) *func = tr->postcheck;
1777cb011f5SBarry Smith   if (ctx)  *ctx  = tr->postcheckctx;
1787cb011f5SBarry Smith   PetscFunctionReturn(0);
1797cb011f5SBarry Smith }
1807cb011f5SBarry Smith 
1817cb011f5SBarry Smith /*@C
182c9368356SGlenn Hammond    SNESNewtonTRPreCheck - Called before the step has been determined in SNESNEWTONTR
183c9368356SGlenn Hammond 
184c9368356SGlenn Hammond    Logically Collective on snes
185c9368356SGlenn Hammond 
186c9368356SGlenn Hammond    Input Parameters:
187c9368356SGlenn Hammond +  snes - the solver
188c9368356SGlenn Hammond .  X - The last solution
189c9368356SGlenn Hammond -  Y - The step direction
190c9368356SGlenn Hammond 
191c9368356SGlenn Hammond    Output Parameters:
192c9368356SGlenn Hammond .  changed_Y - Indicator that the step direction Y has been changed.
193c9368356SGlenn Hammond 
194c9368356SGlenn Hammond    Level: developer
195c9368356SGlenn Hammond 
196c9368356SGlenn Hammond .seealso: SNESNewtonTRSetPreCheck(), SNESNewtonTRGetPreCheck()
197c9368356SGlenn Hammond @*/
198c9368356SGlenn Hammond static PetscErrorCode SNESNewtonTRPreCheck(SNES snes,Vec X,Vec Y,PetscBool *changed_Y)
199c9368356SGlenn Hammond {
200c9368356SGlenn Hammond   SNES_NEWTONTR  *tr = (SNES_NEWTONTR*)snes->data;
201c9368356SGlenn Hammond   PetscErrorCode ierr;
202c9368356SGlenn Hammond 
203c9368356SGlenn Hammond   PetscFunctionBegin;
204c9368356SGlenn Hammond   *changed_Y = PETSC_FALSE;
205c9368356SGlenn Hammond   if (tr->precheck) {
206c9368356SGlenn Hammond     ierr = (*tr->precheck)(snes,X,Y,changed_Y,tr->precheckctx);CHKERRQ(ierr);
207c9368356SGlenn Hammond     PetscValidLogicalCollectiveBool(snes,*changed_Y,4);
208c9368356SGlenn Hammond   }
209c9368356SGlenn Hammond   PetscFunctionReturn(0);
210c9368356SGlenn Hammond }
211c9368356SGlenn Hammond 
212c9368356SGlenn Hammond /*@C
2137cb011f5SBarry Smith    SNESNewtonTRPostCheck - Called after the step has been determined in SNESNEWTONTR but before the function evaluation
2147cb011f5SBarry Smith 
2157cb011f5SBarry Smith    Logically Collective on snes
2167cb011f5SBarry Smith 
2177cb011f5SBarry Smith    Input Parameters:
2187cb011f5SBarry Smith +  snes - the solver.  X - The last solution
2197cb011f5SBarry Smith .  Y - The full step direction
2203312a946SBarry Smith -  W - The updated solution, W = X - Y
2217cb011f5SBarry Smith 
2227cb011f5SBarry Smith    Output Parameters:
2233312a946SBarry Smith +  changed_Y - indicator if step has been changed
2243312a946SBarry Smith -  changed_W - Indicator if the new candidate solution W has been changed.
2257cb011f5SBarry Smith 
2267cb011f5SBarry Smith    Notes:
2273312a946SBarry Smith      If Y is changed then W is recomputed as X - Y
2287cb011f5SBarry Smith 
2297cb011f5SBarry Smith    Level: developer
2307cb011f5SBarry Smith 
2317cb011f5SBarry Smith .seealso: SNESNewtonTRSetPostCheck(), SNESNewtonTRGetPostCheck()
2327cb011f5SBarry Smith @*/
233c9368356SGlenn Hammond static PetscErrorCode SNESNewtonTRPostCheck(SNES snes,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W)
2347cb011f5SBarry Smith {
2357cb011f5SBarry Smith   SNES_NEWTONTR  *tr = (SNES_NEWTONTR*)snes->data;
2367cb011f5SBarry Smith   PetscErrorCode ierr;
2377cb011f5SBarry Smith 
2387cb011f5SBarry Smith   PetscFunctionBegin;
239c9368356SGlenn Hammond   *changed_Y = PETSC_FALSE;
2407cb011f5SBarry Smith   *changed_W = PETSC_FALSE;
2417cb011f5SBarry Smith   if (tr->postcheck) {
242c9368356SGlenn Hammond     ierr = (*tr->postcheck)(snes,X,Y,W,changed_Y,changed_W,tr->postcheckctx);CHKERRQ(ierr);
243c9368356SGlenn Hammond     PetscValidLogicalCollectiveBool(snes,*changed_Y,5);
2447cb011f5SBarry Smith     PetscValidLogicalCollectiveBool(snes,*changed_W,6);
2457cb011f5SBarry Smith   }
2467cb011f5SBarry Smith   PetscFunctionReturn(0);
2477cb011f5SBarry Smith }
24885385478SLisandro Dalcin 
249df60cc22SBarry Smith /*
25004d7464bSBarry Smith    SNESSolve_NEWTONTR - Implements Newton's Method with a very simple trust
251ddbbdb52SLois Curfman McInnes    region approach for solving systems of nonlinear equations.
2524800dd8cSBarry Smith 
253ddbbdb52SLois Curfman McInnes 
2544800dd8cSBarry Smith */
25504d7464bSBarry Smith static PetscErrorCode SNESSolve_NEWTONTR(SNES snes)
2564800dd8cSBarry Smith {
25704d7464bSBarry Smith   SNES_NEWTONTR            *neP = (SNES_NEWTONTR*)snes->data;
258c9368356SGlenn Hammond   Vec                      X,F,Y,G,Ytmp,W;
2596849ba73SBarry Smith   PetscErrorCode           ierr;
260a7cc72afSBarry Smith   PetscInt                 maxits,i,lits;
26185385478SLisandro Dalcin   PetscReal                rho,fnorm,gnorm,gpnorm,xnorm=0,delta,nrm,ynorm,norm1;
26279f36460SBarry Smith   PetscScalar              cnorm;
263df60cc22SBarry Smith   KSP                      ksp;
2643f149594SLisandro Dalcin   SNESConvergedReason      reason = SNES_CONVERGED_ITERATING;
265df8705c3SBarry Smith   PetscBool                breakout = PETSC_FALSE;
266df8705c3SBarry Smith   SNES_TR_KSPConverged_Ctx *ctx;
267*5e28bcb6Sprj-   PetscErrorCode           (*convtest)(KSP,PetscInt,PetscReal,KSPConvergedReason*,void*),(*convdestroy)(void*);
268*5e28bcb6Sprj-   void                     *convctx;
2694800dd8cSBarry Smith 
2703a40ed3dSBarry Smith   PetscFunctionBegin;
2716c4ed002SBarry Smith   if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name);
272c579b300SPatrick Farrell 
273fbe28522SBarry Smith   maxits = snes->max_its;               /* maximum number of iterations */
274fbe28522SBarry Smith   X      = snes->vec_sol;               /* solution vector */
27539e2f89bSBarry Smith   F      = snes->vec_func;              /* residual vector */
276fbe28522SBarry Smith   Y      = snes->work[0];               /* work vectors */
277fbe28522SBarry Smith   G      = snes->work[1];
2786b5873e3SBarry Smith   Ytmp   = snes->work[2];
279c9368356SGlenn Hammond   W      = snes->work[3];
2804800dd8cSBarry Smith 
281e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
2824c49b128SBarry Smith   snes->iter = 0;
283e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
2844800dd8cSBarry Smith 
285df8705c3SBarry Smith   /* Set the linear stopping criteria to use the More' trick. */
286df8705c3SBarry Smith   ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
287*5e28bcb6Sprj-   ierr = KSPGetConvergenceTest(ksp,&convtest,&convctx,&convdestroy);CHKERRQ(ierr);
288df8705c3SBarry Smith   if (convtest != SNESTR_KSPConverged_Private) {
289df8705c3SBarry Smith     ierr                  = PetscNew(&ctx);CHKERRQ(ierr);
290df8705c3SBarry Smith     ctx->snes             = snes;
291df8705c3SBarry Smith     ierr                  = KSPGetAndClearConvergenceTest(ksp,&ctx->convtest,&ctx->convctx,&ctx->convdestroy);CHKERRQ(ierr);
292df8705c3SBarry Smith     ierr                  = KSPSetConvergenceTest(ksp,SNESTR_KSPConverged_Private,ctx,SNESTR_KSPConverged_Destroy);CHKERRQ(ierr);
293df8705c3SBarry Smith     ierr                  = PetscInfo(snes,"Using Krylov convergence test SNESTR_KSPConverged_Private\n");CHKERRQ(ierr);
294df8705c3SBarry Smith   }
295df8705c3SBarry Smith 
296e4ed7901SPeter Brune   if (!snes->vec_func_init_set) {
2975334005bSBarry Smith     ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);          /* F(X) */
2981aa26658SKarl Rupp   } else snes->vec_func_init_set = PETSC_FALSE;
299e4ed7901SPeter Brune 
300cddf8d76SBarry Smith   ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr);             /* fnorm <- || F || */
301422a814eSBarry Smith   SNESCheckFunctionNorm(snes,fnorm);
3028b84755bSBarry Smith   ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr);             /* fnorm <- || F || */
303e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
304fbe28522SBarry Smith   snes->norm = fnorm;
305e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
3068b84755bSBarry Smith   delta      = xnorm ? neP->delta0*xnorm : neP->delta0;
3074800dd8cSBarry Smith   neP->delta = delta;
308a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
3097a03ce2fSLisandro Dalcin   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
310b37302c6SLois Curfman McInnes 
31185385478SLisandro Dalcin   /* test convergence */
31285385478SLisandro Dalcin   ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
31385385478SLisandro Dalcin   if (snes->reason) PetscFunctionReturn(0);
3143f149594SLisandro Dalcin 
315df60cc22SBarry Smith 
3164800dd8cSBarry Smith   for (i=0; i<maxits; i++) {
31799a96b7cSMatthew Knepley 
31899a96b7cSMatthew Knepley     /* Call general purpose update function */
319e7788613SBarry Smith     if (snes->ops->update) {
320e7788613SBarry Smith       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
32199a96b7cSMatthew Knepley     }
32299a96b7cSMatthew Knepley 
32385385478SLisandro Dalcin     /* Solve J Y = F, where J is Jacobian matrix */
324d1e9a80fSBarry Smith     ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr);
32507b62357SFande Kong     SNESCheckJacobianDomainerror(snes);
32623ee1639SBarry Smith     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr);
327d4211eb9SBarry Smith     ierr = KSPSolve(snes->ksp,F,Ytmp);CHKERRQ(ierr);
3283f149594SLisandro Dalcin     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
3291aa26658SKarl Rupp 
330329f5518SBarry Smith     snes->linear_its += lits;
3311aa26658SKarl Rupp 
332ae15b995SBarry Smith     ierr  = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
333064f8208SBarry Smith     ierr  = VecNorm(Ytmp,NORM_2,&nrm);CHKERRQ(ierr);
334064f8208SBarry Smith     norm1 = nrm;
3356b5873e3SBarry Smith     while (1) {
336c9368356SGlenn Hammond       PetscBool changed_y;
3377cb011f5SBarry Smith       PetscBool changed_w;
338393d2d9aSLois Curfman McInnes       ierr = VecCopy(Ytmp,Y);CHKERRQ(ierr);
339064f8208SBarry Smith       nrm  = norm1;
3406b5873e3SBarry Smith 
3412deea200SLois Curfman McInnes       /* Scale Y if need be and predict new value of F norm */
342064f8208SBarry Smith       if (nrm >= delta) {
343064f8208SBarry Smith         nrm    = delta/nrm;
344064f8208SBarry Smith         gpnorm = (1.0 - nrm)*fnorm;
345064f8208SBarry Smith         cnorm  = nrm;
34657622a8eSBarry Smith         ierr   = PetscInfo1(snes,"Scaling direction by %g\n",(double)nrm);CHKERRQ(ierr);
3472dcb1b2aSMatthew Knepley         ierr   = VecScale(Y,cnorm);CHKERRQ(ierr);
348064f8208SBarry Smith         nrm    = gpnorm;
349fbe28522SBarry Smith         ynorm  = delta;
350fbe28522SBarry Smith       } else {
351fbe28522SBarry Smith         gpnorm = 0.0;
352ae15b995SBarry Smith         ierr   = PetscInfo(snes,"Direction is in Trust Region\n");CHKERRQ(ierr);
353064f8208SBarry Smith         ynorm  = nrm;
354fbe28522SBarry Smith       }
355c9368356SGlenn Hammond       /* PreCheck() allows for updates to Y prior to W <- X - Y */
356c9368356SGlenn Hammond       ierr = SNESNewtonTRPreCheck(snes,X,Y,&changed_y);CHKERRQ(ierr);
357c9368356SGlenn Hammond       ierr = VecWAXPY(W,-1.0,Y,X);CHKERRQ(ierr);         /* W <- X - Y */
358c9368356SGlenn Hammond       ierr = SNESNewtonTRPostCheck(snes,X,Y,W,&changed_y,&changed_w);CHKERRQ(ierr);
359c9368356SGlenn Hammond       if (changed_y) ierr = VecWAXPY(W,-1.0,Y,X);CHKERRQ(ierr);
360c1cd17f6SGlenn Hammond       ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
361c9368356SGlenn Hammond       ierr = SNESComputeFunction(snes,W,G);CHKERRQ(ierr); /*  F(X) */
362cddf8d76SBarry Smith       ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr);      /* gnorm <- || g || */
3637551ef16SBarry Smith       SNESCheckFunctionNorm(snes,gnorm);
3644800dd8cSBarry Smith       if (fnorm == gpnorm) rho = 0.0;
365fbe28522SBarry Smith       else rho = (fnorm*fnorm - gnorm*gnorm)/(fnorm*fnorm - gpnorm*gpnorm);
3664800dd8cSBarry Smith 
3674800dd8cSBarry Smith       /* Update size of trust region */
3684800dd8cSBarry Smith       if      (rho < neP->mu)  delta *= neP->delta1;
3694800dd8cSBarry Smith       else if (rho < neP->eta) delta *= neP->delta2;
3704800dd8cSBarry Smith       else                     delta *= neP->delta3;
37157622a8eSBarry Smith       ierr = PetscInfo3(snes,"fnorm=%g, gnorm=%g, ynorm=%g\n",(double)fnorm,(double)gnorm,(double)ynorm);CHKERRQ(ierr);
37257622a8eSBarry Smith       ierr = PetscInfo3(snes,"gpred=%g, rho=%g, delta=%g\n",(double)gpnorm,(double)rho,(double)delta);CHKERRQ(ierr);
3731aa26658SKarl Rupp 
3744800dd8cSBarry Smith       neP->delta = delta;
3754800dd8cSBarry Smith       if (rho > neP->sigma) break;
376ae15b995SBarry Smith       ierr = PetscInfo(snes,"Trying again in smaller region\n");CHKERRQ(ierr);
3776b5873e3SBarry Smith       /* check to see if progress is hopeless */
378ef87ac0dSKris Buschelman       neP->itflag = PETSC_FALSE;
379470880abSPatrick Sanan       ierr        = SNESTR_Converged_Private(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr);
38085385478SLisandro Dalcin       if (!reason) {ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr);}
3817cb011f5SBarry Smith       if (reason == SNES_CONVERGED_SNORM_RELATIVE) reason = SNES_DIVERGED_INNER;
382184914b5SBarry Smith       if (reason) {
38352392280SLois Curfman McInnes         /* We're not progressing, so return with the current iterate */
3847a03ce2fSLisandro Dalcin         ierr     = SNESMonitor(snes,i+1,fnorm);CHKERRQ(ierr);
385a7cc72afSBarry Smith         breakout = PETSC_TRUE;
386454a90a3SBarry Smith         break;
38752392280SLois Curfman McInnes       }
38850ffb88aSMatthew Knepley       snes->numFailures++;
3894800dd8cSBarry Smith     }
3901acabf8cSLois Curfman McInnes     if (!breakout) {
39185385478SLisandro Dalcin       /* Update function and solution vectors */
3924800dd8cSBarry Smith       fnorm = gnorm;
39385385478SLisandro Dalcin       ierr  = VecCopy(G,F);CHKERRQ(ierr);
394c9368356SGlenn Hammond       ierr  = VecCopy(W,X);CHKERRQ(ierr);
39585385478SLisandro Dalcin       /* Monitor convergence */
396e04113cfSBarry Smith       ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
397c509a162SBarry Smith       snes->iter = i+1;
398fbe28522SBarry Smith       snes->norm = fnorm;
399c1e67a49SFande Kong       snes->xnorm = xnorm;
400c1e67a49SFande Kong       snes->ynorm = ynorm;
401e04113cfSBarry Smith       ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
402a71f0d7dSBarry Smith       ierr       = SNESLogConvergenceHistory(snes,snes->norm,lits);CHKERRQ(ierr);
4037a03ce2fSLisandro Dalcin       ierr       = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
40485385478SLisandro Dalcin       /* Test for convergence, xnorm = || X || */
405ef87ac0dSKris Buschelman       neP->itflag = PETSC_TRUE;
406e2a6519dSDmitry Karpeev       if (snes->ops->converged != SNESConvergedSkip) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
407e7788613SBarry Smith       ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr);
4083f149594SLisandro Dalcin       if (reason) break;
4091aa26658SKarl Rupp     } else break;
41038442cffSBarry Smith   }
41152392280SLois Curfman McInnes   if (i == maxits) {
412ae15b995SBarry Smith     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
41385385478SLisandro Dalcin     if (!reason) reason = SNES_DIVERGED_MAX_IT;
41452392280SLois Curfman McInnes   }
415e04113cfSBarry Smith   ierr         = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
416184914b5SBarry Smith   snes->reason = reason;
417e04113cfSBarry Smith   ierr         = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
418*5e28bcb6Sprj-   if (convtest != SNESTR_KSPConverged_Private) {
419*5e28bcb6Sprj-     ierr       = KSPGetAndClearConvergenceTest(ksp,&ctx->convtest,&ctx->convctx,&ctx->convdestroy);CHKERRQ(ierr);
420*5e28bcb6Sprj-     ierr       = PetscFree(ctx);CHKERRQ(ierr);
421*5e28bcb6Sprj-     ierr       = KSPSetConvergenceTest(ksp,convtest,convctx,convdestroy);CHKERRQ(ierr);
422*5e28bcb6Sprj-   }
4233a40ed3dSBarry Smith   PetscFunctionReturn(0);
4244800dd8cSBarry Smith }
4254800dd8cSBarry Smith /*------------------------------------------------------------*/
42604d7464bSBarry Smith static PetscErrorCode SNESSetUp_NEWTONTR(SNES snes)
4274800dd8cSBarry Smith {
428dfbe8321SBarry Smith   PetscErrorCode ierr;
4293a40ed3dSBarry Smith 
4303a40ed3dSBarry Smith   PetscFunctionBegin;
431c9368356SGlenn Hammond   ierr = SNESSetWorkVecs(snes,4);CHKERRQ(ierr);
4326cab3a1bSJed Brown   ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4333a40ed3dSBarry Smith   PetscFunctionReturn(0);
4344800dd8cSBarry Smith }
4356b8b9a38SLisandro Dalcin 
43604d7464bSBarry Smith PetscErrorCode SNESReset_NEWTONTR(SNES snes)
4376b8b9a38SLisandro Dalcin {
4386b8b9a38SLisandro Dalcin 
4396b8b9a38SLisandro Dalcin   PetscFunctionBegin;
4406b8b9a38SLisandro Dalcin   PetscFunctionReturn(0);
4416b8b9a38SLisandro Dalcin }
4426b8b9a38SLisandro Dalcin 
44304d7464bSBarry Smith static PetscErrorCode SNESDestroy_NEWTONTR(SNES snes)
4444800dd8cSBarry Smith {
445dfbe8321SBarry Smith   PetscErrorCode ierr;
4465baf8537SBarry Smith 
4473a40ed3dSBarry Smith   PetscFunctionBegin;
44804d7464bSBarry Smith   ierr = SNESReset_NEWTONTR(snes);CHKERRQ(ierr);
449606d414cSSatish Balay   ierr = PetscFree(snes->data);CHKERRQ(ierr);
4503a40ed3dSBarry Smith   PetscFunctionReturn(0);
4514800dd8cSBarry Smith }
4524800dd8cSBarry Smith /*------------------------------------------------------------*/
4534800dd8cSBarry Smith 
4544416b707SBarry Smith static PetscErrorCode SNESSetFromOptions_NEWTONTR(PetscOptionItems *PetscOptionsObject,SNES snes)
4554800dd8cSBarry Smith {
45604d7464bSBarry Smith   SNES_NEWTONTR  *ctx = (SNES_NEWTONTR*)snes->data;
457dfbe8321SBarry Smith   PetscErrorCode ierr;
4584800dd8cSBarry Smith 
4593a40ed3dSBarry Smith   PetscFunctionBegin;
460e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNES trust region options for nonlinear equations");CHKERRQ(ierr);
46194ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_trtol","Trust region tolerance","SNESSetTrustRegionTolerance",snes->deltatol,&snes->deltatol,NULL);CHKERRQ(ierr);
46294ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_tr_mu","mu","None",ctx->mu,&ctx->mu,NULL);CHKERRQ(ierr);
46394ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_tr_eta","eta","None",ctx->eta,&ctx->eta,NULL);CHKERRQ(ierr);
46494ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_tr_sigma","sigma","None",ctx->sigma,&ctx->sigma,NULL);CHKERRQ(ierr);
46594ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_tr_delta0","delta0","None",ctx->delta0,&ctx->delta0,NULL);CHKERRQ(ierr);
46694ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_tr_delta1","delta1","None",ctx->delta1,&ctx->delta1,NULL);CHKERRQ(ierr);
46794ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_tr_delta2","delta2","None",ctx->delta2,&ctx->delta2,NULL);CHKERRQ(ierr);
46894ae4db5SBarry Smith   ierr = PetscOptionsReal("-snes_tr_delta3","delta3","None",ctx->delta3,&ctx->delta3,NULL);CHKERRQ(ierr);
469b0a32e0cSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
4703a40ed3dSBarry Smith   PetscFunctionReturn(0);
4714800dd8cSBarry Smith }
4724800dd8cSBarry Smith 
47304d7464bSBarry Smith static PetscErrorCode SNESView_NEWTONTR(SNES snes,PetscViewer viewer)
474a935fc98SLois Curfman McInnes {
47504d7464bSBarry Smith   SNES_NEWTONTR  *tr = (SNES_NEWTONTR*)snes->data;
476dfbe8321SBarry Smith   PetscErrorCode ierr;
477ace3abfcSBarry Smith   PetscBool      iascii;
478a935fc98SLois Curfman McInnes 
4793a40ed3dSBarry Smith   PetscFunctionBegin;
480251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
48132077d6dSBarry Smith   if (iascii) {
48254fe5c21SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Trust region tolerance (-snes_trtol)\n",(double)snes->deltatol);CHKERRQ(ierr);
48357622a8eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  mu=%g, eta=%g, sigma=%g\n",(double)tr->mu,(double)tr->eta,(double)tr->sigma);CHKERRQ(ierr);
48457622a8eSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  delta0=%g, delta1=%g, delta2=%g, delta3=%g\n",(double)tr->delta0,(double)tr->delta1,(double)tr->delta2,(double)tr->delta3);CHKERRQ(ierr);
48519bcc07fSBarry Smith   }
4863a40ed3dSBarry Smith   PetscFunctionReturn(0);
487a935fc98SLois Curfman McInnes }
48852392280SLois Curfman McInnes /* ------------------------------------------------------------ */
489ebe3b25bSBarry Smith /*MC
49004d7464bSBarry Smith       SNESNEWTONTR - Newton based nonlinear solver that uses a trust region
491ebe3b25bSBarry Smith 
492ebe3b25bSBarry Smith    Options Database:
4938e434772SBarry Smith +    -snes_trtol <tol> - trust region tolerance
4948e434772SBarry Smith .    -snes_tr_mu <mu> - trust region parameter
4958e434772SBarry Smith .    -snes_tr_eta <eta> - trust region parameter
4968e434772SBarry Smith .    -snes_tr_sigma <sigma> - trust region parameter
4978b84755bSBarry Smith .    -snes_tr_delta0 <delta0> -  initial size of the trust region is delta0*norm2(x)
4988e434772SBarry Smith .    -snes_tr_delta1 <delta1> - trust region parameter
4998e434772SBarry Smith .    -snes_tr_delta2 <delta2> - trust region parameter
5008e434772SBarry Smith -    -snes_tr_delta3 <delta3> - trust region parameter
501ebe3b25bSBarry Smith 
502ebe3b25bSBarry Smith    The basic algorithm is taken from "The Minpack Project", by More',
503ebe3b25bSBarry Smith    Sorensen, Garbow, Hillstrom, pages 88-111 of "Sources and Development
504ebe3b25bSBarry Smith    of Mathematical Software", Wayne Cowell, editor.
505ebe3b25bSBarry Smith 
506ee3001cbSBarry Smith    Level: intermediate
507ee3001cbSBarry Smith 
50804d7464bSBarry Smith .seealso:  SNESCreate(), SNES, SNESSetType(), SNESNEWTONLS, SNESSetTrustRegionTolerance()
509ebe3b25bSBarry Smith 
510ebe3b25bSBarry Smith M*/
5118cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_NEWTONTR(SNES snes)
5124800dd8cSBarry Smith {
51304d7464bSBarry Smith   SNES_NEWTONTR  *neP;
514dfbe8321SBarry Smith   PetscErrorCode ierr;
5154800dd8cSBarry Smith 
5163a40ed3dSBarry Smith   PetscFunctionBegin;
51704d7464bSBarry Smith   snes->ops->setup          = SNESSetUp_NEWTONTR;
51804d7464bSBarry Smith   snes->ops->solve          = SNESSolve_NEWTONTR;
51904d7464bSBarry Smith   snes->ops->destroy        = SNESDestroy_NEWTONTR;
52004d7464bSBarry Smith   snes->ops->setfromoptions = SNESSetFromOptions_NEWTONTR;
52104d7464bSBarry Smith   snes->ops->view           = SNESView_NEWTONTR;
52204d7464bSBarry Smith   snes->ops->reset          = SNESReset_NEWTONTR;
523fbe28522SBarry Smith 
52442f4f86dSBarry Smith   snes->usesksp = PETSC_TRUE;
525efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
52642f4f86dSBarry Smith 
5274fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
5284fc747eaSLawrence Mitchell 
529b00a9115SJed Brown   ierr        = PetscNewLog(snes,&neP);CHKERRQ(ierr);
530fbe28522SBarry Smith   snes->data  = (void*)neP;
531fbe28522SBarry Smith   neP->mu     = 0.25;
532fbe28522SBarry Smith   neP->eta    = 0.75;
533fbe28522SBarry Smith   neP->delta  = 0.0;
534fbe28522SBarry Smith   neP->delta0 = 0.2;
535fbe28522SBarry Smith   neP->delta1 = 0.3;
536fbe28522SBarry Smith   neP->delta2 = 0.75;
537fbe28522SBarry Smith   neP->delta3 = 2.0;
538fbe28522SBarry Smith   neP->sigma  = 0.0001;
539ef87ac0dSKris Buschelman   neP->itflag = PETSC_FALSE;
54075567043SBarry Smith   neP->rnorm0 = 0.0;
54175567043SBarry Smith   neP->ttol   = 0.0;
5423a40ed3dSBarry Smith   PetscFunctionReturn(0);
5434800dd8cSBarry Smith }
54482bf6240SBarry Smith 
545