xref: /petsc/src/snes/impls/tr/tr.c (revision d636dbe3a9c413b447e52fc0f7f06f5e4018d190)
14800dd8cSBarry Smith #ifndef lint
2*d636dbe3SBarry Smith static char vcid[] = "$Id: tr.c,v 1.26 1995/08/24 22:30:50 bsmith Exp bsmith $";
34800dd8cSBarry Smith #endif
44800dd8cSBarry Smith 
54800dd8cSBarry Smith #include <math.h>
6b9fa9cd0SBarry Smith #include "tr.h"                /*I   "snes.h"   I*/
7b16a3bb1SBarry Smith #include "pinclude/pviewer.h"
84800dd8cSBarry Smith 
9fbe28522SBarry Smith /*
10df60cc22SBarry Smith    This convergence test determines if the two norm of the
11df60cc22SBarry Smith    solution lies outside the trust region, if so it halts.
12df60cc22SBarry Smith */
139c49e667SLois Curfman McInnes int SNES_TR_KSPConverged_Private(KSP ksp,int n, double rnorm, void *ctx)
14df60cc22SBarry Smith {
15df60cc22SBarry Smith   SNES    snes = (SNES) ctx;
1698120f82SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
17df60cc22SBarry Smith   SNES_TR *neP = (SNES_TR*)snes->data;
18df60cc22SBarry Smith   Vec     x;
1998120f82SLois Curfman McInnes   double  norm;
2098120f82SLois Curfman McInnes   int     ierr, convinfo;
21df60cc22SBarry Smith 
2298120f82SLois Curfman McInnes   if (snes->ksp_ewconv) {
2398120f82SLois Curfman McInnes     if (!kctx) SETERRQ(1,
2498120f82SLois Curfman McInnes       "SNES_KSP_EW_Converged_Private: Convergence context does not exist");
2598120f82SLois Curfman McInnes     if (n == 0) SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);
2698120f82SLois Curfman McInnes     kctx->lresid_last = rnorm;
27df60cc22SBarry Smith   }
2898120f82SLois Curfman McInnes   convinfo = KSPDefaultConverged(ksp,n,rnorm,ctx);
299b04593eSLois Curfman McInnes   if (convinfo) {
309b04593eSLois Curfman McInnes     PLogInfo((PetscObject)snes,"SNES: KSP iterations=%d, rnorm=%g\n",n,rnorm);
319b04593eSLois Curfman McInnes     return convinfo;
329b04593eSLois Curfman McInnes   }
33df60cc22SBarry Smith 
34a935fc98SLois Curfman McInnes   /* Determine norm of solution */
3578b31e54SBarry Smith   ierr = KSPBuildSolution(ksp,0,&x); CHKERRQ(ierr);
3678b31e54SBarry Smith   ierr = VecNorm(x,&norm); CHKERRQ(ierr);
37df60cc22SBarry Smith   if (norm >= neP->delta) {
389b04593eSLois Curfman McInnes     PLogInfo((PetscObject)snes,"SNES: KSP iterations=%d, rnorm=%g\n",n,rnorm);
39a935fc98SLois Curfman McInnes     PLogInfo((PetscObject)snes,
409b04593eSLois Curfman McInnes       "SNES: Ending linear iteration early, delta %g length %g\n",neP->delta,norm);
41df60cc22SBarry Smith     return 1;
42df60cc22SBarry Smith   }
43df60cc22SBarry Smith   return(0);
44df60cc22SBarry Smith }
45df60cc22SBarry Smith /*
46ddbbdb52SLois Curfman McInnes    SNESSolve_TR - Implements Newton's Method with a very simple trust
47ddbbdb52SLois Curfman McInnes    region approach for solving systems of nonlinear equations.
484800dd8cSBarry Smith 
494800dd8cSBarry Smith    The basic algorithm is taken from "The Minpack Project", by More',
504800dd8cSBarry Smith    Sorensen, Garbow, Hillstrom, pages 88-111 of "Sources and Development
51ddbbdb52SLois Curfman McInnes    of Mathematical Software", Wayne Cowell, editor.
52ddbbdb52SLois Curfman McInnes 
534800dd8cSBarry Smith    This is intended as a model implementation, since it does not
544800dd8cSBarry Smith    necessarily have many of the bells and whistles of other
554800dd8cSBarry Smith    implementations.
564800dd8cSBarry Smith */
57fbe28522SBarry Smith static int SNESSolve_TR(SNES snes,int *its)
584800dd8cSBarry Smith {
59fbe28522SBarry Smith   SNES_TR      *neP = (SNES_TR *) snes->data;
606b5873e3SBarry Smith   Vec          X, F, Y, G, TMP, Ytmp;
61ddbbdb52SLois Curfman McInnes   int          maxits, i, history_len, ierr, lits;
62df60cc22SBarry Smith   MatStructure flg = ALLMAT_DIFFERENT_NONZERO_PATTERN;
63fbe28522SBarry Smith   double       rho, fnorm, gnorm, gpnorm, xnorm, delta,norm;
644800dd8cSBarry Smith   double       *history, ynorm;
65eafb4bcbSBarry Smith   Scalar       one = 1.0,cnorm;
66df60cc22SBarry Smith   KSP          ksp;
67df60cc22SBarry Smith   SLES         sles;
684800dd8cSBarry Smith 
69fbe28522SBarry Smith   history	= snes->conv_hist;	/* convergence history */
70fbe28522SBarry Smith   history_len	= snes->conv_hist_len;	/* convergence history length */
71fbe28522SBarry Smith   maxits	= snes->max_its;	/* maximum number of iterations */
72fbe28522SBarry Smith   X		= snes->vec_sol;	/* solution vector */
7339e2f89bSBarry Smith   F		= snes->vec_func;	/* residual vector */
74fbe28522SBarry Smith   Y		= snes->work[0];	/* work vectors */
75fbe28522SBarry Smith   G		= snes->work[1];
766b5873e3SBarry Smith   Ytmp          = snes->work[2];
774800dd8cSBarry Smith 
7878b31e54SBarry Smith   ierr = SNESComputeInitialGuess(snes,X); CHKERRQ(ierr); /* X <- X_0 */
79393d2d9aSLois Curfman McInnes   ierr = VecNorm(X,&xnorm); CHKERRQ(ierr);               /* xnorm = || X || */
804800dd8cSBarry Smith 
8178b31e54SBarry Smith   ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr);   /* (+/-) F(X) */
82393d2d9aSLois Curfman McInnes   ierr = VecNorm(F, &fnorm ); CHKERRQ(ierr);             /* fnorm <- || F || */
83fbe28522SBarry Smith   snes->norm = fnorm;
844800dd8cSBarry Smith   if (history && history_len > 0) history[0] = fnorm;
854800dd8cSBarry Smith   delta = neP->delta0*fnorm;
864800dd8cSBarry Smith   neP->delta = delta;
87bbb6d6a8SBarry Smith   if (snes->monitor)
88bbb6d6a8SBarry Smith     {ierr = (*snes->monitor)(snes,0,fnorm,snes->monP); CHKERRQ(ierr);}
894800dd8cSBarry Smith 
90a935fc98SLois Curfman McInnes   /* Set the stopping criteria to use the More' trick. */
9178b31e54SBarry Smith   ierr = SNESGetSLES(snes,&sles); CHKERRQ(ierr);
9278b31e54SBarry Smith   ierr = SLESGetKSP(sles,&ksp); CHKERRQ(ierr);
939c49e667SLois Curfman McInnes   ierr = KSPSetConvergenceTest(ksp,SNES_TR_KSPConverged_Private,(void *)snes);
9478b31e54SBarry Smith   CHKERRQ(ierr);
95df60cc22SBarry Smith 
964800dd8cSBarry Smith   for ( i=0; i<maxits; i++ ) {
97fbe28522SBarry Smith      snes->iter = i+1;
98df60cc22SBarry Smith      ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,
99bbb6d6a8SBarry Smith                                              &flg); CHKERRQ(ierr);
100a935fc98SLois Curfman McInnes      ierr = SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,
101a935fc98SLois Curfman McInnes                             flg); CHKERRQ(ierr);
10278b31e54SBarry Smith      ierr = SLESSolve(snes->sles,F,Ytmp,&lits); CHKERRQ(ierr);
103393d2d9aSLois Curfman McInnes      ierr = VecNorm(Ytmp,&norm); CHKERRQ(ierr);
1046b5873e3SBarry Smith      while(1) {
105393d2d9aSLois Curfman McInnes        ierr = VecCopy(Ytmp,Y); CHKERRQ(ierr);
106fbe28522SBarry Smith        /* Scale Y if need be and predict new value of F norm */
1076b5873e3SBarry Smith 
108eafb4bcbSBarry Smith        if (norm >= delta) {
109fbe28522SBarry Smith          norm = delta/norm;
110fbe28522SBarry Smith          gpnorm = (1.0 - norm)*fnorm;
111eafb4bcbSBarry Smith          cnorm = norm;
112df60cc22SBarry Smith          PLogInfo((PetscObject)snes, "Scaling direction by %g \n",norm );
113393d2d9aSLois Curfman McInnes          ierr = VecScale(&cnorm,Y); CHKERRQ(ierr);
114eafb4bcbSBarry Smith          norm = gpnorm;
115fbe28522SBarry Smith          ynorm = delta;
116fbe28522SBarry Smith        } else {
117fbe28522SBarry Smith          gpnorm = 0.0;
118fbe28522SBarry Smith          PLogInfo((PetscObject)snes,"Direction is in Trust Region \n" );
119fbe28522SBarry Smith          ynorm = norm;
120fbe28522SBarry Smith        }
121393d2d9aSLois Curfman McInnes        ierr = VecAXPY(&one,X,Y); CHKERRQ(ierr);             /* Y <- X + Y */
12281b6cf68SLois Curfman McInnes        ierr = VecCopy(X,snes->vec_sol_update_always); CHKERRQ(ierr);
12378b31e54SBarry Smith        ierr = SNESComputeFunction(snes,Y,G); CHKERRQ(ierr); /* (+/-) F(X) */
124393d2d9aSLois Curfman McInnes        ierr = VecNorm(G,&gnorm); CHKERRQ(ierr);             /* gnorm <- || g || */
1254800dd8cSBarry Smith        if (fnorm == gpnorm) rho = 0.0;
126fbe28522SBarry Smith        else rho = (fnorm*fnorm - gnorm*gnorm)/(fnorm*fnorm - gpnorm*gpnorm);
1274800dd8cSBarry Smith 
1284800dd8cSBarry Smith        /* Update size of trust region */
1294800dd8cSBarry Smith        if      (rho < neP->mu)  delta *= neP->delta1;
1304800dd8cSBarry Smith        else if (rho < neP->eta) delta *= neP->delta2;
1314800dd8cSBarry Smith        else                     delta *= neP->delta3;
132fbe28522SBarry Smith        PLogInfo((PetscObject)snes,"%d:  f_norm=%g, g_norm=%g, ynorm=%g\n",
1334800dd8cSBarry Smith                                              i, fnorm, gnorm, ynorm );
134fbe28522SBarry Smith        PLogInfo((PetscObject)snes,"gpred=%g, rho=%g, delta=%g,iters=%d\n",
135fbe28522SBarry Smith                                                gpnorm, rho, delta, lits);
1364800dd8cSBarry Smith        neP->delta = delta;
1374800dd8cSBarry Smith        if (rho > neP->sigma) break;
138eafb4bcbSBarry Smith        PLogInfo((PetscObject)snes,"Trying again in smaller region\n");
1396b5873e3SBarry Smith        /* check to see if progress is hopeless */
14052392280SLois Curfman McInnes        neP->itflag = 0;
14152392280SLois Curfman McInnes        if ((*snes->converged)(snes,xnorm,ynorm,fnorm,snes->cnvP)) {
14252392280SLois Curfman McInnes          /* We're not progressing, so return with the current iterate */
14352392280SLois Curfman McInnes          if (X != snes->vec_sol) {
144393d2d9aSLois Curfman McInnes            ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr);
14552392280SLois Curfman McInnes            snes->vec_sol_always = snes->vec_sol;
14652392280SLois Curfman McInnes            snes->vec_func_always = snes->vec_func;
14752392280SLois Curfman McInnes          }
14852392280SLois Curfman McInnes        }
14952392280SLois Curfman McInnes        snes->nfailures++;
1504800dd8cSBarry Smith      }
1514800dd8cSBarry Smith      fnorm = gnorm;
152fbe28522SBarry Smith      snes->norm = fnorm;
1534800dd8cSBarry Smith      if (history && history_len > i+1) history[i+1] = fnorm;
15439e2f89bSBarry Smith      TMP = F; F = G; snes->vec_func_always = F; G = TMP;
15539e2f89bSBarry Smith      TMP = X; X = Y; snes->vec_sol_always = X; Y = TMP;
156fbe28522SBarry Smith      VecNorm(X, &xnorm );		/* xnorm = || X || */
157bbb6d6a8SBarry Smith      if (snes->monitor)
158393d2d9aSLois Curfman McInnes        {ierr = (*snes->monitor)(snes,i+1,fnorm,snes->monP); CHKERRQ(ierr);}
1594800dd8cSBarry Smith 
1604800dd8cSBarry Smith      /* Test for convergence */
16152392280SLois Curfman McInnes      neP->itflag = 1;
162bbb6d6a8SBarry Smith      if ((*snes->converged)( snes, xnorm, ynorm, fnorm,snes->cnvP )) {
1634800dd8cSBarry Smith        /* Verify solution is in corect location */
16439e2f89bSBarry Smith        if (X != snes->vec_sol) {
165393d2d9aSLois Curfman McInnes          ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr);
16639e2f89bSBarry Smith          snes->vec_sol_always = snes->vec_sol;
16739e2f89bSBarry Smith          snes->vec_func_always = snes->vec_func;
16839e2f89bSBarry Smith        }
1694800dd8cSBarry Smith        break;
1704800dd8cSBarry Smith      }
1714800dd8cSBarry Smith    }
17252392280SLois Curfman McInnes   if (i == maxits) {
17352392280SLois Curfman McInnes     PLogInfo((PetscObject)snes,
17452392280SLois Curfman McInnes       "Maximum number of iterations has been reached: %d\n",maxits);
17552392280SLois Curfman McInnes     i--;
17652392280SLois Curfman McInnes   }
17752392280SLois Curfman McInnes   *its = i+1;
178fbe28522SBarry Smith   return 0;
1794800dd8cSBarry Smith }
1804800dd8cSBarry Smith /*------------------------------------------------------------*/
181fbe28522SBarry Smith static int SNESSetUp_TR( SNES snes )
1824800dd8cSBarry Smith {
183fbe28522SBarry Smith   int ierr;
18481b6cf68SLois Curfman McInnes   snes->nwork = 4;
18578b31e54SBarry Smith   ierr = VecGetVecs(snes->vec_sol,snes->nwork,&snes->work ); CHKERRQ(ierr);
186393d2d9aSLois Curfman McInnes   PLogObjectParents(snes,snes->nwork,snes->work);
18781b6cf68SLois Curfman McInnes   snes->vec_sol_update_always = snes->work[3];
188fbe28522SBarry Smith   return 0;
1894800dd8cSBarry Smith }
1904800dd8cSBarry Smith /*------------------------------------------------------------*/
191fbe28522SBarry Smith static int SNESDestroy_TR(PetscObject obj )
1924800dd8cSBarry Smith {
193fbe28522SBarry Smith   SNES snes = (SNES) obj;
194393d2d9aSLois Curfman McInnes   int  ierr;
195393d2d9aSLois Curfman McInnes   ierr = VecFreeVecs(snes->work,snes->nwork); CHKERRQ(ierr);
19678b31e54SBarry Smith   PETSCFREE(snes->data);
197fbe28522SBarry Smith   return 0;
1984800dd8cSBarry Smith }
1994800dd8cSBarry Smith /*------------------------------------------------------------*/
2004800dd8cSBarry Smith 
201fbe28522SBarry Smith static int SNESSetFromOptions_TR(SNES snes)
2024800dd8cSBarry Smith {
203fbe28522SBarry Smith   SNES_TR *ctx = (SNES_TR *)snes->data;
204fbe28522SBarry Smith   double  tmp;
2054800dd8cSBarry Smith 
206df60cc22SBarry Smith   if (OptionsGetDouble(snes->prefix,"-mu",&tmp)) {ctx->mu = tmp;}
207df60cc22SBarry Smith   if (OptionsGetDouble(snes->prefix,"-eta",&tmp)) {ctx->eta = tmp;}
208df60cc22SBarry Smith   if (OptionsGetDouble(snes->prefix,"-sigma",&tmp)) {ctx->sigma = tmp;}
209df60cc22SBarry Smith   if (OptionsGetDouble(snes->prefix,"-delta0",&tmp)) {ctx->delta0 = tmp;}
210df60cc22SBarry Smith   if (OptionsGetDouble(snes->prefix,"-delta1",&tmp)) {ctx->delta1 = tmp;}
211df60cc22SBarry Smith   if (OptionsGetDouble(snes->prefix,"-delta2",&tmp)) {ctx->delta2 = tmp;}
212df60cc22SBarry Smith   if (OptionsGetDouble(snes->prefix,"-delta3",&tmp)) {ctx->delta3 = tmp;}
213fbe28522SBarry Smith   return 0;
2144800dd8cSBarry Smith }
2154800dd8cSBarry Smith 
216fbe28522SBarry Smith static int SNESPrintHelp_TR(SNES snes)
2174800dd8cSBarry Smith {
218fbe28522SBarry Smith   SNES_TR *ctx = (SNES_TR *)snes->data;
21952392280SLois Curfman McInnes   char    *p;
22052392280SLois Curfman McInnes   if (snes->prefix) p = snes->prefix; else p = "-";
22152392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout," method tr (system of nonlinear equations):\n");
22252392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout,"   %ssnes_trust_region_mu mu (default %g)\n",p,ctx->mu);
22352392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout,"   %ssnes_trust_region_eta eta (default %g)\n",p,ctx->eta);
22452392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout,"   %ssnes_trust_region_sigma sigma (default %g)\n",p,ctx->sigma);
22552392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout,"   %ssnes_trust_region_delta0 delta0 (default %g)\n",p,ctx->delta0);
22652392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout,"   %ssnes_trust_region_delta1 delta1 (default %g)\n",p,ctx->delta1);
22752392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout,"   %ssnes_trust_region_delta2 delta2 (default %g)\n",p,ctx->delta2);
22852392280SLois Curfman McInnes   MPIU_fprintf(snes->comm,stdout,"   %ssnes_trust_region_delta3 delta3 (default %g)\n",p,ctx->delta3);
229fbe28522SBarry Smith   return 0;
2304800dd8cSBarry Smith }
2314800dd8cSBarry Smith 
232a935fc98SLois Curfman McInnes static int SNESView_TR(PetscObject obj,Viewer viewer)
233a935fc98SLois Curfman McInnes {
234a935fc98SLois Curfman McInnes   SNES    snes = (SNES)obj;
235a935fc98SLois Curfman McInnes   SNES_TR *tr = (SNES_TR *)snes->data;
236*d636dbe3SBarry Smith   FILE    *fd;
237*d636dbe3SBarry Smith   ierr = ViewerFileGetPointer_Private(viewer,&fd); CHKERRQ(ierr);
238a935fc98SLois Curfman McInnes 
239a935fc98SLois Curfman McInnes   MPIU_fprintf(snes->comm,fd,"    mu=%g, eta=%g, sigma=%g\n",
240a935fc98SLois Curfman McInnes     tr->mu,tr->eta,tr->sigma);
241a935fc98SLois Curfman McInnes   MPIU_fprintf(snes->comm,fd,
242a935fc98SLois Curfman McInnes     "    delta0=%g, delta1=%g, delta2=%g, delta3=%g\n",
243a935fc98SLois Curfman McInnes     tr->delta0,tr->delta1,tr->delta2,tr->delta3);
244a935fc98SLois Curfman McInnes   return 0;
245a935fc98SLois Curfman McInnes }
246a935fc98SLois Curfman McInnes 
24752392280SLois Curfman McInnes /* ---------------------------------------------------------------- */
24852392280SLois Curfman McInnes /*@
24952392280SLois Curfman McInnes    SNESTrustRegionDefaultConverged - Default test for monitoring the
25052392280SLois Curfman McInnes    convergence of the trust region method SNES_EQ_TR for solving systems
25152392280SLois Curfman McInnes    of nonlinear equations.
25252392280SLois Curfman McInnes 
25352392280SLois Curfman McInnes    Input Parameters:
25452392280SLois Curfman McInnes .  snes - the SNES context
25552392280SLois Curfman McInnes .  xnorm - 2-norm of current iterate
25652392280SLois Curfman McInnes .  pnorm - 2-norm of current step
25752392280SLois Curfman McInnes .  fnorm - 2-norm of function
25852392280SLois Curfman McInnes .  dummy - unused context
25952392280SLois Curfman McInnes 
26052392280SLois Curfman McInnes    Returns:
26152392280SLois Curfman McInnes $  1  if  ( delta < xnorm*deltatol ),
26252392280SLois Curfman McInnes $  2  if  ( fnorm < atol ),
26352392280SLois Curfman McInnes $  3  if  ( pnorm < xtol*xnorm ),
26452392280SLois Curfman McInnes $ -2  if  ( nfct > maxf ),
26552392280SLois Curfman McInnes $ -1  if  ( delta < xnorm*epsmch ),
26652392280SLois Curfman McInnes $  0  otherwise,
26752392280SLois Curfman McInnes 
26852392280SLois Curfman McInnes    where
26952392280SLois Curfman McInnes $    delta    - trust region paramenter
27052392280SLois Curfman McInnes $    deltatol - trust region size tolerance,
27152392280SLois Curfman McInnes $               set with SNESSetTrustRegionTolerance()
27252392280SLois Curfman McInnes $    maxf - maximum number of function evaluations,
27352392280SLois Curfman McInnes $           set with SNESSetMaxFunctionEvaluations()
27452392280SLois Curfman McInnes $    nfct - number of function evaluations,
27552392280SLois Curfman McInnes $    atol - absolute function norm tolerance,
27652392280SLois Curfman McInnes $           set with SNESSetAbsoluteTolerance()
27752392280SLois Curfman McInnes $    xtol - relative function norm tolerance,
27852392280SLois Curfman McInnes $           set with SNESSetRelativeTolerance()
27952392280SLois Curfman McInnes 
28052392280SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
28152392280SLois Curfman McInnes 
28252392280SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
28352392280SLois Curfman McInnes @*/
28452392280SLois Curfman McInnes int SNESTrustRegionDefaultConverged(SNES snes,double xnorm,double pnorm,
28552392280SLois Curfman McInnes                          double fnorm,void *dummy)
28652392280SLois Curfman McInnes {
28752392280SLois Curfman McInnes   SNES_TR *neP = (SNES_TR *)snes->data;
28852392280SLois Curfman McInnes   double  epsmch = 1.0e-14;   /* This must be fixed */
28952392280SLois Curfman McInnes   int     info;
29052392280SLois Curfman McInnes   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) SETERRQ(1,
29152392280SLois Curfman McInnes     "SNESDefaultConverged:For SNES_NONLINEAR_EQUATIONS method only");
29252392280SLois Curfman McInnes 
29352392280SLois Curfman McInnes   if (neP->delta < xnorm * snes->deltatol) {
29452392280SLois Curfman McInnes     PLogInfo((PetscObject)snes,
29552392280SLois Curfman McInnes       "SNES: Converged due to trust region param %g < %g * %g\n",neP->delta,
29652392280SLois Curfman McInnes        xnorm, snes->deltatol);
29752392280SLois Curfman McInnes     return 1;
29852392280SLois Curfman McInnes   }
29952392280SLois Curfman McInnes   if (neP->itflag) {
30052392280SLois Curfman McInnes     info = SNESDefaultConverged(snes,xnorm,pnorm,fnorm,dummy);
30152392280SLois Curfman McInnes     if (info) return info;
30252392280SLois Curfman McInnes   }
30352392280SLois Curfman McInnes   if (neP->delta < xnorm * epsmch) {
30452392280SLois Curfman McInnes     PLogInfo((PetscObject)snes,
30552392280SLois Curfman McInnes       "SNES: Converged due to trust region param %g < %g * %g\n",neP->delta,
30652392280SLois Curfman McInnes        xnorm, epsmch);
30752392280SLois Curfman McInnes     return -1;
30852392280SLois Curfman McInnes   }
30952392280SLois Curfman McInnes   return 0;
31052392280SLois Curfman McInnes }
31152392280SLois Curfman McInnes /* ------------------------------------------------------------ */
312fbe28522SBarry Smith int SNESCreate_TR(SNES snes )
3134800dd8cSBarry Smith {
314fbe28522SBarry Smith   SNES_TR *neP;
3154800dd8cSBarry Smith 
316369a4401SLois Curfman McInnes   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) SETERRQ(1,
317369a4401SLois Curfman McInnes     "SNESCreate_TR: Valid for SNES_NONLINEAR_EQUATIONS problems only");
31825c7317fSLois Curfman McInnes   snes->type 		= SNES_EQ_NTR;
31906be10caSBarry Smith   snes->setup		= SNESSetUp_TR;
32006be10caSBarry Smith   snes->solve		= SNESSolve_TR;
321fbe28522SBarry Smith   snes->destroy		= SNESDestroy_TR;
32252392280SLois Curfman McInnes   snes->converged	= SNESTrustRegionDefaultConverged;
32306be10caSBarry Smith   snes->printhelp       = SNESPrintHelp_TR;
32406be10caSBarry Smith   snes->setfromoptions  = SNESSetFromOptions_TR;
325a935fc98SLois Curfman McInnes   snes->view            = SNESView_TR;
326fbe28522SBarry Smith 
32778b31e54SBarry Smith   neP			= PETSCNEW(SNES_TR); CHKPTRQ(neP);
32880b4ade8SLois Curfman McInnes   PLogObjectMemory(snes,sizeof(SNES_TR));
329fbe28522SBarry Smith   snes->data	        = (void *) neP;
330fbe28522SBarry Smith   neP->mu		= 0.25;
331fbe28522SBarry Smith   neP->eta		= 0.75;
332fbe28522SBarry Smith   neP->delta		= 0.0;
333fbe28522SBarry Smith   neP->delta0		= 0.2;
334fbe28522SBarry Smith   neP->delta1		= 0.3;
335fbe28522SBarry Smith   neP->delta2		= 0.75;
336fbe28522SBarry Smith   neP->delta3		= 2.0;
337fbe28522SBarry Smith   neP->sigma		= 0.0001;
338fbe28522SBarry Smith   neP->itflag		= 0;
33952392280SLois Curfman McInnes   neP->rnorm0		= 0;
34052392280SLois Curfman McInnes   neP->ttol		= 0;
3416b5873e3SBarry Smith   return 0;
3424800dd8cSBarry Smith }
343