xref: /petsc/src/tao/unconstrained/impls/nls/nls.c (revision a7e14dcfba0d07adf6226a919460249440ec94c7)
1*a7e14dcfSSatish Balay #include "taolinesearch.h"
2*a7e14dcfSSatish Balay #include "src/matrix/lmvmmat.h"
3*a7e14dcfSSatish Balay #include "nls.h"
4*a7e14dcfSSatish Balay 
5*a7e14dcfSSatish Balay #include "petscksp.h"
6*a7e14dcfSSatish Balay #include "petscpc.h"
7*a7e14dcfSSatish Balay #include "petsc-private/kspimpl.h"
8*a7e14dcfSSatish Balay #include "petsc-private/pcimpl.h"
9*a7e14dcfSSatish Balay 
10*a7e14dcfSSatish Balay #define NLS_KSP_CG	0
11*a7e14dcfSSatish Balay #define NLS_KSP_NASH	1
12*a7e14dcfSSatish Balay #define NLS_KSP_STCG	2
13*a7e14dcfSSatish Balay #define NLS_KSP_GLTR	3
14*a7e14dcfSSatish Balay #define NLS_KSP_PETSC	4
15*a7e14dcfSSatish Balay #define NLS_KSP_TYPES	5
16*a7e14dcfSSatish Balay 
17*a7e14dcfSSatish Balay #define NLS_PC_NONE	0
18*a7e14dcfSSatish Balay #define NLS_PC_AHESS	1
19*a7e14dcfSSatish Balay #define NLS_PC_BFGS	2
20*a7e14dcfSSatish Balay #define NLS_PC_PETSC	3
21*a7e14dcfSSatish Balay #define NLS_PC_TYPES	4
22*a7e14dcfSSatish Balay 
23*a7e14dcfSSatish Balay #define BFGS_SCALE_AHESS	0
24*a7e14dcfSSatish Balay #define BFGS_SCALE_PHESS	1
25*a7e14dcfSSatish Balay #define BFGS_SCALE_BFGS		2
26*a7e14dcfSSatish Balay #define BFGS_SCALE_TYPES	3
27*a7e14dcfSSatish Balay 
28*a7e14dcfSSatish Balay #define NLS_INIT_CONSTANT         0
29*a7e14dcfSSatish Balay #define NLS_INIT_DIRECTION        1
30*a7e14dcfSSatish Balay #define NLS_INIT_INTERPOLATION    2
31*a7e14dcfSSatish Balay #define NLS_INIT_TYPES            3
32*a7e14dcfSSatish Balay 
33*a7e14dcfSSatish Balay #define NLS_UPDATE_STEP           0
34*a7e14dcfSSatish Balay #define NLS_UPDATE_REDUCTION      1
35*a7e14dcfSSatish Balay #define NLS_UPDATE_INTERPOLATION  2
36*a7e14dcfSSatish Balay #define NLS_UPDATE_TYPES          3
37*a7e14dcfSSatish Balay 
38*a7e14dcfSSatish Balay static const char *NLS_KSP[64] = {
39*a7e14dcfSSatish Balay   "cg", "nash", "stcg", "gltr", "petsc"
40*a7e14dcfSSatish Balay };
41*a7e14dcfSSatish Balay 
42*a7e14dcfSSatish Balay static const char *NLS_PC[64] = {
43*a7e14dcfSSatish Balay   "none", "ahess", "bfgs", "petsc"
44*a7e14dcfSSatish Balay };
45*a7e14dcfSSatish Balay 
46*a7e14dcfSSatish Balay static const char *BFGS_SCALE[64] = {
47*a7e14dcfSSatish Balay   "ahess", "phess", "bfgs"
48*a7e14dcfSSatish Balay };
49*a7e14dcfSSatish Balay 
50*a7e14dcfSSatish Balay static const char *NLS_INIT[64] = {
51*a7e14dcfSSatish Balay   "constant", "direction", "interpolation"
52*a7e14dcfSSatish Balay };
53*a7e14dcfSSatish Balay 
54*a7e14dcfSSatish Balay static const char *NLS_UPDATE[64] = {
55*a7e14dcfSSatish Balay   "step", "reduction", "interpolation"
56*a7e14dcfSSatish Balay };
57*a7e14dcfSSatish Balay 
58*a7e14dcfSSatish Balay static PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x) ;
59*a7e14dcfSSatish Balay /* Routine for BFGS preconditioner
60*a7e14dcfSSatish Balay 
61*a7e14dcfSSatish Balay 
62*a7e14dcfSSatish Balay  Implements Newton's Method with a line search approach for solving
63*a7e14dcfSSatish Balay  unconstrained minimization problems.  A More'-Thuente line search
64*a7e14dcfSSatish Balay  is used to guarantee that the bfgs preconditioner remains positive
65*a7e14dcfSSatish Balay  definite.
66*a7e14dcfSSatish Balay 
67*a7e14dcfSSatish Balay  The method can shift the Hessian matrix.  The shifting procedure is
68*a7e14dcfSSatish Balay  adapted from the PATH algorithm for solving complementarity
69*a7e14dcfSSatish Balay  problems.
70*a7e14dcfSSatish Balay 
71*a7e14dcfSSatish Balay  The linear system solve should be done with a conjugate gradient
72*a7e14dcfSSatish Balay  method, although any method can be used. */
73*a7e14dcfSSatish Balay 
74*a7e14dcfSSatish Balay #define NLS_NEWTON 		0
75*a7e14dcfSSatish Balay #define NLS_BFGS 		1
76*a7e14dcfSSatish Balay #define NLS_SCALED_GRADIENT 	2
77*a7e14dcfSSatish Balay #define NLS_GRADIENT 		3
78*a7e14dcfSSatish Balay 
79*a7e14dcfSSatish Balay #undef __FUNCT__
80*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSolve_NLS"
81*a7e14dcfSSatish Balay static PetscErrorCode TaoSolve_NLS(TaoSolver tao)
82*a7e14dcfSSatish Balay {
83*a7e14dcfSSatish Balay   PetscErrorCode ierr;
84*a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
85*a7e14dcfSSatish Balay 
86*a7e14dcfSSatish Balay   PC pc;
87*a7e14dcfSSatish Balay 
88*a7e14dcfSSatish Balay   KSPConvergedReason ksp_reason;
89*a7e14dcfSSatish Balay   TaoLineSearchTerminationReason ls_reason;
90*a7e14dcfSSatish Balay   TaoSolverTerminationReason reason;
91*a7e14dcfSSatish Balay 
92*a7e14dcfSSatish Balay   PetscReal fmin, ftrial, f_full, prered, actred, kappa, sigma;
93*a7e14dcfSSatish Balay   PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius;
94*a7e14dcfSSatish Balay   PetscReal f, fold, gdx, gnorm, pert;
95*a7e14dcfSSatish Balay   PetscReal step = 1.0;
96*a7e14dcfSSatish Balay 
97*a7e14dcfSSatish Balay   PetscReal delta;
98*a7e14dcfSSatish Balay   PetscReal norm_d = 0.0, e_min;
99*a7e14dcfSSatish Balay 
100*a7e14dcfSSatish Balay   MatStructure matflag;
101*a7e14dcfSSatish Balay 
102*a7e14dcfSSatish Balay   PetscInt stepType;
103*a7e14dcfSSatish Balay   PetscInt iter = 0;
104*a7e14dcfSSatish Balay   PetscInt bfgsUpdates = 0;
105*a7e14dcfSSatish Balay   PetscInt n,N,kspits;
106*a7e14dcfSSatish Balay   PetscInt needH;
107*a7e14dcfSSatish Balay 
108*a7e14dcfSSatish Balay   PetscInt i_max = 5;
109*a7e14dcfSSatish Balay   PetscInt j_max = 1;
110*a7e14dcfSSatish Balay   PetscInt i, j;
111*a7e14dcfSSatish Balay 
112*a7e14dcfSSatish Balay   PetscFunctionBegin;
113*a7e14dcfSSatish Balay 
114*a7e14dcfSSatish Balay   if (tao->XL || tao->XU || tao->ops->computebounds) {
115*a7e14dcfSSatish Balay     ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by nls algorithm\n"); CHKERRQ(ierr);
116*a7e14dcfSSatish Balay   }
117*a7e14dcfSSatish Balay 
118*a7e14dcfSSatish Balay   /* Initialized variables */
119*a7e14dcfSSatish Balay   pert = nlsP->sval;
120*a7e14dcfSSatish Balay 
121*a7e14dcfSSatish Balay   nlsP->ksp_atol = 0;
122*a7e14dcfSSatish Balay   nlsP->ksp_rtol = 0;
123*a7e14dcfSSatish Balay   nlsP->ksp_dtol = 0;
124*a7e14dcfSSatish Balay   nlsP->ksp_ctol = 0;
125*a7e14dcfSSatish Balay   nlsP->ksp_negc = 0;
126*a7e14dcfSSatish Balay   nlsP->ksp_iter = 0;
127*a7e14dcfSSatish Balay   nlsP->ksp_othr = 0;
128*a7e14dcfSSatish Balay 
129*a7e14dcfSSatish Balay 
130*a7e14dcfSSatish Balay 
131*a7e14dcfSSatish Balay   /* Modify the linear solver to a trust region method if desired */
132*a7e14dcfSSatish Balay 
133*a7e14dcfSSatish Balay   switch(nlsP->ksp_type) {
134*a7e14dcfSSatish Balay   case NLS_KSP_CG:
135*a7e14dcfSSatish Balay     ierr = KSPSetType(tao->ksp, KSPCG); CHKERRQ(ierr);
136*a7e14dcfSSatish Balay     if (tao->ksp->ops->setfromoptions) {
137*a7e14dcfSSatish Balay 	(*tao->ksp->ops->setfromoptions)(tao->ksp);
138*a7e14dcfSSatish Balay     }
139*a7e14dcfSSatish Balay     break;
140*a7e14dcfSSatish Balay 
141*a7e14dcfSSatish Balay   case NLS_KSP_NASH:
142*a7e14dcfSSatish Balay     ierr = KSPSetType(tao->ksp, KSPNASH); CHKERRQ(ierr);
143*a7e14dcfSSatish Balay     if (tao->ksp->ops->setfromoptions) {
144*a7e14dcfSSatish Balay       (*tao->ksp->ops->setfromoptions)(tao->ksp);
145*a7e14dcfSSatish Balay     }
146*a7e14dcfSSatish Balay     break;
147*a7e14dcfSSatish Balay 
148*a7e14dcfSSatish Balay   case NLS_KSP_STCG:
149*a7e14dcfSSatish Balay     ierr = KSPSetType(tao->ksp, KSPSTCG); CHKERRQ(ierr);
150*a7e14dcfSSatish Balay     if (tao->ksp->ops->setfromoptions) {
151*a7e14dcfSSatish Balay       (*tao->ksp->ops->setfromoptions)(tao->ksp);
152*a7e14dcfSSatish Balay     }
153*a7e14dcfSSatish Balay     break;
154*a7e14dcfSSatish Balay 
155*a7e14dcfSSatish Balay   case NLS_KSP_GLTR:
156*a7e14dcfSSatish Balay     ierr = KSPSetType(tao->ksp, KSPGLTR); CHKERRQ(ierr);
157*a7e14dcfSSatish Balay     if (tao->ksp->ops->setfromoptions) {
158*a7e14dcfSSatish Balay       (*tao->ksp->ops->setfromoptions)(tao->ksp);
159*a7e14dcfSSatish Balay     }
160*a7e14dcfSSatish Balay     break;
161*a7e14dcfSSatish Balay 
162*a7e14dcfSSatish Balay   default:
163*a7e14dcfSSatish Balay     /* Use the method set by the ksp_type */
164*a7e14dcfSSatish Balay     break;
165*a7e14dcfSSatish Balay   }
166*a7e14dcfSSatish Balay 
167*a7e14dcfSSatish Balay   /* Initialize trust-region radius when using nash, stcg, or gltr
168*a7e14dcfSSatish Balay      Will be reset during the first iteration */
169*a7e14dcfSSatish Balay   if (NLS_KSP_NASH == nlsP->ksp_type) {
170*a7e14dcfSSatish Balay       ierr = KSPNASHSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
171*a7e14dcfSSatish Balay   } else if (NLS_KSP_STCG == nlsP->ksp_type) {
172*a7e14dcfSSatish Balay       ierr = KSPSTCGSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
173*a7e14dcfSSatish Balay   } else if (NLS_KSP_GLTR == nlsP->ksp_type) {
174*a7e14dcfSSatish Balay       ierr = KSPGLTRSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
175*a7e14dcfSSatish Balay   }
176*a7e14dcfSSatish Balay 
177*a7e14dcfSSatish Balay 
178*a7e14dcfSSatish Balay   if (NLS_KSP_NASH == nlsP->ksp_type ||
179*a7e14dcfSSatish Balay       NLS_KSP_STCG == nlsP->ksp_type ||
180*a7e14dcfSSatish Balay       NLS_KSP_GLTR == nlsP->ksp_type) {
181*a7e14dcfSSatish Balay     tao->trust = tao->trust0;
182*a7e14dcfSSatish Balay 
183*a7e14dcfSSatish Balay     if (tao->trust < 0.0) {
184*a7e14dcfSSatish Balay       SETERRQ(PETSC_COMM_SELF,1, "Initial radius negative");
185*a7e14dcfSSatish Balay     }
186*a7e14dcfSSatish Balay 
187*a7e14dcfSSatish Balay     /* Modify the radius if it is too large or small */
188*a7e14dcfSSatish Balay     tao->trust = PetscMax(tao->trust, nlsP->min_radius);
189*a7e14dcfSSatish Balay     tao->trust = PetscMin(tao->trust, nlsP->max_radius);
190*a7e14dcfSSatish Balay   }
191*a7e14dcfSSatish Balay 
192*a7e14dcfSSatish Balay   /* Get vectors we will need */
193*a7e14dcfSSatish Balay 
194*a7e14dcfSSatish Balay   if (NLS_PC_BFGS == nlsP->pc_type && !nlsP->M) {
195*a7e14dcfSSatish Balay     ierr = VecGetLocalSize(tao->solution,&n); CHKERRQ(ierr);
196*a7e14dcfSSatish Balay     ierr = VecGetSize(tao->solution,&N); CHKERRQ(ierr);
197*a7e14dcfSSatish Balay     ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&nlsP->M); CHKERRQ(ierr);
198*a7e14dcfSSatish Balay     ierr = MatLMVMAllocateVectors(nlsP->M,tao->solution); CHKERRQ(ierr);
199*a7e14dcfSSatish Balay   }
200*a7e14dcfSSatish Balay 
201*a7e14dcfSSatish Balay   /* Check convergence criteria */
202*a7e14dcfSSatish Balay   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient); CHKERRQ(ierr);
203*a7e14dcfSSatish Balay   ierr = VecNorm(tao->gradient,NORM_2,&gnorm); CHKERRQ(ierr);
204*a7e14dcfSSatish Balay   if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) {
205*a7e14dcfSSatish Balay     SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
206*a7e14dcfSSatish Balay   }
207*a7e14dcfSSatish Balay   needH = 1;
208*a7e14dcfSSatish Balay 
209*a7e14dcfSSatish Balay   ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason); CHKERRQ(ierr);
210*a7e14dcfSSatish Balay   if (reason != TAO_CONTINUE_ITERATING) {
211*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
212*a7e14dcfSSatish Balay   }
213*a7e14dcfSSatish Balay 
214*a7e14dcfSSatish Balay   /* create vectors for the limited memory preconditioner */
215*a7e14dcfSSatish Balay   if ((NLS_PC_BFGS == nlsP->pc_type) &&
216*a7e14dcfSSatish Balay       (BFGS_SCALE_BFGS != nlsP->bfgs_scale_type)) {
217*a7e14dcfSSatish Balay     if (!nlsP->Diag) {
218*a7e14dcfSSatish Balay 	ierr = VecDuplicate(tao->solution,&nlsP->Diag); CHKERRQ(ierr);
219*a7e14dcfSSatish Balay     }
220*a7e14dcfSSatish Balay   }
221*a7e14dcfSSatish Balay 
222*a7e14dcfSSatish Balay 
223*a7e14dcfSSatish Balay   /* Modify the preconditioner to use the bfgs approximation */
224*a7e14dcfSSatish Balay   ierr = KSPGetPC(tao->ksp, &pc); CHKERRQ(ierr);
225*a7e14dcfSSatish Balay   switch(nlsP->pc_type) {
226*a7e14dcfSSatish Balay   case NLS_PC_NONE:
227*a7e14dcfSSatish Balay     ierr = PCSetType(pc, PCNONE); CHKERRQ(ierr);
228*a7e14dcfSSatish Balay     if (pc->ops->setfromoptions) {
229*a7e14dcfSSatish Balay       (*pc->ops->setfromoptions)(pc);
230*a7e14dcfSSatish Balay     }
231*a7e14dcfSSatish Balay     break;
232*a7e14dcfSSatish Balay 
233*a7e14dcfSSatish Balay   case NLS_PC_AHESS:
234*a7e14dcfSSatish Balay     ierr = PCSetType(pc, PCJACOBI); CHKERRQ(ierr);
235*a7e14dcfSSatish Balay     if (pc->ops->setfromoptions) {
236*a7e14dcfSSatish Balay       (*pc->ops->setfromoptions)(pc);
237*a7e14dcfSSatish Balay     }
238*a7e14dcfSSatish Balay     ierr = PCJacobiSetUseAbs(pc); CHKERRQ(ierr);
239*a7e14dcfSSatish Balay     break;
240*a7e14dcfSSatish Balay 
241*a7e14dcfSSatish Balay   case NLS_PC_BFGS:
242*a7e14dcfSSatish Balay     ierr = PCSetType(pc, PCSHELL); CHKERRQ(ierr);
243*a7e14dcfSSatish Balay     if (pc->ops->setfromoptions) {
244*a7e14dcfSSatish Balay       (*pc->ops->setfromoptions)(pc);
245*a7e14dcfSSatish Balay     }
246*a7e14dcfSSatish Balay     ierr = PCShellSetName(pc, "bfgs"); CHKERRQ(ierr);
247*a7e14dcfSSatish Balay     ierr = PCShellSetContext(pc, nlsP->M); CHKERRQ(ierr);
248*a7e14dcfSSatish Balay     ierr = PCShellSetApply(pc, MatLMVMSolveShell); CHKERRQ(ierr);
249*a7e14dcfSSatish Balay     break;
250*a7e14dcfSSatish Balay 
251*a7e14dcfSSatish Balay   default:
252*a7e14dcfSSatish Balay     /* Use the pc method set by pc_type */
253*a7e14dcfSSatish Balay     break;
254*a7e14dcfSSatish Balay   }
255*a7e14dcfSSatish Balay 
256*a7e14dcfSSatish Balay   /* Initialize trust-region radius.  The initialization is only performed
257*a7e14dcfSSatish Balay      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
258*a7e14dcfSSatish Balay   if (NLS_KSP_NASH == nlsP->ksp_type ||
259*a7e14dcfSSatish Balay       NLS_KSP_STCG == nlsP->ksp_type ||
260*a7e14dcfSSatish Balay       NLS_KSP_GLTR == nlsP->ksp_type) {
261*a7e14dcfSSatish Balay     switch(nlsP->init_type) {
262*a7e14dcfSSatish Balay     case NLS_INIT_CONSTANT:
263*a7e14dcfSSatish Balay       /* Use the initial radius specified */
264*a7e14dcfSSatish Balay       break;
265*a7e14dcfSSatish Balay 
266*a7e14dcfSSatish Balay     case NLS_INIT_INTERPOLATION:
267*a7e14dcfSSatish Balay       /* Use the initial radius specified */
268*a7e14dcfSSatish Balay       max_radius = 0.0;
269*a7e14dcfSSatish Balay 
270*a7e14dcfSSatish Balay       for (j = 0; j < j_max; ++j) {
271*a7e14dcfSSatish Balay         fmin = f;
272*a7e14dcfSSatish Balay         sigma = 0.0;
273*a7e14dcfSSatish Balay 
274*a7e14dcfSSatish Balay         if (needH) {
275*a7e14dcfSSatish Balay 	    ierr = TaoComputeHessian(tao, tao->solution, &tao->hessian, &tao->hessian_pre, &matflag); CHKERRQ(ierr);
276*a7e14dcfSSatish Balay 	    needH = 0;
277*a7e14dcfSSatish Balay         }
278*a7e14dcfSSatish Balay 
279*a7e14dcfSSatish Balay         for (i = 0; i < i_max; ++i) {
280*a7e14dcfSSatish Balay           ierr = VecCopy(tao->solution,nlsP->W); CHKERRQ(ierr);
281*a7e14dcfSSatish Balay 	  ierr = VecAXPY(nlsP->W,-tao->trust/gnorm,tao->gradient); CHKERRQ(ierr);
282*a7e14dcfSSatish Balay 	  ierr = TaoComputeObjective(tao, nlsP->W, &ftrial); CHKERRQ(ierr);
283*a7e14dcfSSatish Balay           if (PetscIsInfOrNanReal(ftrial)) {
284*a7e14dcfSSatish Balay             tau = nlsP->gamma1_i;
285*a7e14dcfSSatish Balay           }
286*a7e14dcfSSatish Balay           else {
287*a7e14dcfSSatish Balay             if (ftrial < fmin) {
288*a7e14dcfSSatish Balay               fmin = ftrial;
289*a7e14dcfSSatish Balay               sigma = -tao->trust / gnorm;
290*a7e14dcfSSatish Balay             }
291*a7e14dcfSSatish Balay 
292*a7e14dcfSSatish Balay 	    ierr = MatMult(tao->hessian, tao->gradient, nlsP->D); CHKERRQ(ierr);
293*a7e14dcfSSatish Balay 	    ierr = VecDot(tao->gradient, nlsP->D, &prered); CHKERRQ(ierr);
294*a7e14dcfSSatish Balay 
295*a7e14dcfSSatish Balay             prered = tao->trust * (gnorm - 0.5 * tao->trust * prered / (gnorm * gnorm));
296*a7e14dcfSSatish Balay             actred = f - ftrial;
297*a7e14dcfSSatish Balay             if ((PetscAbsScalar(actred) <= nlsP->epsilon) &&
298*a7e14dcfSSatish Balay                 (PetscAbsScalar(prered) <= nlsP->epsilon)) {
299*a7e14dcfSSatish Balay               kappa = 1.0;
300*a7e14dcfSSatish Balay             }
301*a7e14dcfSSatish Balay             else {
302*a7e14dcfSSatish Balay               kappa = actred / prered;
303*a7e14dcfSSatish Balay             }
304*a7e14dcfSSatish Balay 
305*a7e14dcfSSatish Balay             tau_1 = nlsP->theta_i * gnorm * tao->trust / (nlsP->theta_i * gnorm * tao->trust + (1.0 - nlsP->theta_i) * prered - actred);
306*a7e14dcfSSatish Balay             tau_2 = nlsP->theta_i * gnorm * tao->trust / (nlsP->theta_i * gnorm * tao->trust - (1.0 + nlsP->theta_i) * prered + actred);
307*a7e14dcfSSatish Balay             tau_min = PetscMin(tau_1, tau_2);
308*a7e14dcfSSatish Balay             tau_max = PetscMax(tau_1, tau_2);
309*a7e14dcfSSatish Balay 
310*a7e14dcfSSatish Balay             if (PetscAbsScalar(kappa - 1.0) <= nlsP->mu1_i) {
311*a7e14dcfSSatish Balay               /* Great agreement */
312*a7e14dcfSSatish Balay               max_radius = PetscMax(max_radius, tao->trust);
313*a7e14dcfSSatish Balay 
314*a7e14dcfSSatish Balay               if (tau_max < 1.0) {
315*a7e14dcfSSatish Balay                 tau = nlsP->gamma3_i;
316*a7e14dcfSSatish Balay               }
317*a7e14dcfSSatish Balay               else if (tau_max > nlsP->gamma4_i) {
318*a7e14dcfSSatish Balay                 tau = nlsP->gamma4_i;
319*a7e14dcfSSatish Balay               }
320*a7e14dcfSSatish Balay               else if (tau_1 >= 1.0 && tau_1 <= nlsP->gamma4_i && tau_2 < 1.0) {
321*a7e14dcfSSatish Balay                 tau = tau_1;
322*a7e14dcfSSatish Balay               }
323*a7e14dcfSSatish Balay               else if (tau_2 >= 1.0 && tau_2 <= nlsP->gamma4_i && tau_1 < 1.0) {
324*a7e14dcfSSatish Balay                 tau = tau_2;
325*a7e14dcfSSatish Balay               }
326*a7e14dcfSSatish Balay               else {
327*a7e14dcfSSatish Balay                 tau = tau_max;
328*a7e14dcfSSatish Balay               }
329*a7e14dcfSSatish Balay             }
330*a7e14dcfSSatish Balay             else if (PetscAbsScalar(kappa - 1.0) <= nlsP->mu2_i) {
331*a7e14dcfSSatish Balay               /* Good agreement */
332*a7e14dcfSSatish Balay               max_radius = PetscMax(max_radius, tao->trust);
333*a7e14dcfSSatish Balay 
334*a7e14dcfSSatish Balay               if (tau_max < nlsP->gamma2_i) {
335*a7e14dcfSSatish Balay                 tau = nlsP->gamma2_i;
336*a7e14dcfSSatish Balay               }
337*a7e14dcfSSatish Balay               else if (tau_max > nlsP->gamma3_i) {
338*a7e14dcfSSatish Balay                 tau = nlsP->gamma3_i;
339*a7e14dcfSSatish Balay               }
340*a7e14dcfSSatish Balay               else {
341*a7e14dcfSSatish Balay                 tau = tau_max;
342*a7e14dcfSSatish Balay               }
343*a7e14dcfSSatish Balay             }
344*a7e14dcfSSatish Balay             else {
345*a7e14dcfSSatish Balay               /* Not good agreement */
346*a7e14dcfSSatish Balay               if (tau_min > 1.0) {
347*a7e14dcfSSatish Balay                 tau = nlsP->gamma2_i;
348*a7e14dcfSSatish Balay               }
349*a7e14dcfSSatish Balay               else if (tau_max < nlsP->gamma1_i) {
350*a7e14dcfSSatish Balay                 tau = nlsP->gamma1_i;
351*a7e14dcfSSatish Balay               }
352*a7e14dcfSSatish Balay               else if ((tau_min < nlsP->gamma1_i) && (tau_max >= 1.0)) {
353*a7e14dcfSSatish Balay                 tau = nlsP->gamma1_i;
354*a7e14dcfSSatish Balay               }
355*a7e14dcfSSatish Balay               else if ((tau_1 >= nlsP->gamma1_i) && (tau_1 < 1.0) &&
356*a7e14dcfSSatish Balay                        ((tau_2 < nlsP->gamma1_i) || (tau_2 >= 1.0))) {
357*a7e14dcfSSatish Balay                 tau = tau_1;
358*a7e14dcfSSatish Balay               }
359*a7e14dcfSSatish Balay               else if ((tau_2 >= nlsP->gamma1_i) && (tau_2 < 1.0) &&
360*a7e14dcfSSatish Balay                        ((tau_1 < nlsP->gamma1_i) || (tau_2 >= 1.0))) {
361*a7e14dcfSSatish Balay                 tau = tau_2;
362*a7e14dcfSSatish Balay               }
363*a7e14dcfSSatish Balay               else {
364*a7e14dcfSSatish Balay                 tau = tau_max;
365*a7e14dcfSSatish Balay               }
366*a7e14dcfSSatish Balay             }
367*a7e14dcfSSatish Balay           }
368*a7e14dcfSSatish Balay           tao->trust = tau * tao->trust;
369*a7e14dcfSSatish Balay         }
370*a7e14dcfSSatish Balay 
371*a7e14dcfSSatish Balay         if (fmin < f) {
372*a7e14dcfSSatish Balay           f = fmin;
373*a7e14dcfSSatish Balay 	  ierr = VecAXPY(tao->solution,sigma,tao->gradient); CHKERRQ(ierr);
374*a7e14dcfSSatish Balay 	  ierr = TaoComputeGradient(tao,tao->solution,tao->gradient); CHKERRQ(ierr);
375*a7e14dcfSSatish Balay 
376*a7e14dcfSSatish Balay 	  ierr = VecNorm(tao->gradient,NORM_2,&gnorm); CHKERRQ(ierr);
377*a7e14dcfSSatish Balay           if (PetscIsInfOrNanReal(gnorm)) {
378*a7e14dcfSSatish Balay             SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN");
379*a7e14dcfSSatish Balay           }
380*a7e14dcfSSatish Balay           needH = 1;
381*a7e14dcfSSatish Balay 
382*a7e14dcfSSatish Balay           ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason); CHKERRQ(ierr);
383*a7e14dcfSSatish Balay           if (reason != TAO_CONTINUE_ITERATING) {
384*a7e14dcfSSatish Balay             PetscFunctionReturn(0);
385*a7e14dcfSSatish Balay           }
386*a7e14dcfSSatish Balay         }
387*a7e14dcfSSatish Balay       }
388*a7e14dcfSSatish Balay       tao->trust = PetscMax(tao->trust, max_radius);
389*a7e14dcfSSatish Balay 
390*a7e14dcfSSatish Balay       /* Modify the radius if it is too large or small */
391*a7e14dcfSSatish Balay       tao->trust = PetscMax(tao->trust, nlsP->min_radius);
392*a7e14dcfSSatish Balay       tao->trust = PetscMin(tao->trust, nlsP->max_radius);
393*a7e14dcfSSatish Balay       break;
394*a7e14dcfSSatish Balay 
395*a7e14dcfSSatish Balay     default:
396*a7e14dcfSSatish Balay       /* Norm of the first direction will initialize radius */
397*a7e14dcfSSatish Balay       tao->trust = 0.0;
398*a7e14dcfSSatish Balay       break;
399*a7e14dcfSSatish Balay     }
400*a7e14dcfSSatish Balay   }
401*a7e14dcfSSatish Balay 
402*a7e14dcfSSatish Balay   /* Set initial scaling for the BFGS preconditioner
403*a7e14dcfSSatish Balay      This step is done after computing the initial trust-region radius
404*a7e14dcfSSatish Balay      since the function value may have decreased */
405*a7e14dcfSSatish Balay   if (NLS_PC_BFGS == nlsP->pc_type) {
406*a7e14dcfSSatish Balay     if (f != 0.0) {
407*a7e14dcfSSatish Balay       delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
408*a7e14dcfSSatish Balay     }
409*a7e14dcfSSatish Balay     else {
410*a7e14dcfSSatish Balay       delta = 2.0 / (gnorm*gnorm);
411*a7e14dcfSSatish Balay     }
412*a7e14dcfSSatish Balay     ierr = MatLMVMSetDelta(nlsP->M,delta); CHKERRQ(ierr);
413*a7e14dcfSSatish Balay   }
414*a7e14dcfSSatish Balay 
415*a7e14dcfSSatish Balay   /* Set counter for gradient/reset steps*/
416*a7e14dcfSSatish Balay   nlsP->newt = 0;
417*a7e14dcfSSatish Balay   nlsP->bfgs = 0;
418*a7e14dcfSSatish Balay   nlsP->sgrad = 0;
419*a7e14dcfSSatish Balay   nlsP->grad = 0;
420*a7e14dcfSSatish Balay 
421*a7e14dcfSSatish Balay   /* Have not converged; continue with Newton method */
422*a7e14dcfSSatish Balay   while (reason == TAO_CONTINUE_ITERATING) {
423*a7e14dcfSSatish Balay     ++iter;
424*a7e14dcfSSatish Balay 
425*a7e14dcfSSatish Balay     /* Compute the Hessian */
426*a7e14dcfSSatish Balay     if (needH) {
427*a7e14dcfSSatish Balay 	ierr = TaoComputeHessian(tao, tao->solution, &tao->hessian, &tao->hessian_pre, &matflag); CHKERRQ(ierr);
428*a7e14dcfSSatish Balay       needH = 0;
429*a7e14dcfSSatish Balay     }
430*a7e14dcfSSatish Balay 
431*a7e14dcfSSatish Balay     if ((NLS_PC_BFGS == nlsP->pc_type) &&
432*a7e14dcfSSatish Balay         (BFGS_SCALE_AHESS == nlsP->bfgs_scale_type)) {
433*a7e14dcfSSatish Balay       /* Obtain diagonal for the bfgs preconditioner  */
434*a7e14dcfSSatish Balay       ierr = MatGetDiagonal(tao->hessian, nlsP->Diag); CHKERRQ(ierr);
435*a7e14dcfSSatish Balay       ierr = VecAbs(nlsP->Diag); CHKERRQ(ierr);
436*a7e14dcfSSatish Balay       ierr = VecReciprocal(nlsP->Diag); CHKERRQ(ierr);
437*a7e14dcfSSatish Balay       ierr = MatLMVMSetScale(nlsP->M,nlsP->Diag); CHKERRQ(ierr);
438*a7e14dcfSSatish Balay     }
439*a7e14dcfSSatish Balay 
440*a7e14dcfSSatish Balay     /* Shift the Hessian matrix */
441*a7e14dcfSSatish Balay     if (pert > 0) {
442*a7e14dcfSSatish Balay       ierr = MatShift(tao->hessian, pert);
443*a7e14dcfSSatish Balay       if (tao->hessian != tao->hessian_pre) {
444*a7e14dcfSSatish Balay 	ierr = MatShift(tao->hessian_pre, pert); CHKERRQ(ierr);
445*a7e14dcfSSatish Balay       }
446*a7e14dcfSSatish Balay     }
447*a7e14dcfSSatish Balay 
448*a7e14dcfSSatish Balay 
449*a7e14dcfSSatish Balay     if (NLS_PC_BFGS == nlsP->pc_type) {
450*a7e14dcfSSatish Balay       if (BFGS_SCALE_PHESS == nlsP->bfgs_scale_type) {
451*a7e14dcfSSatish Balay 	/* Obtain diagonal for the bfgs preconditioner  */
452*a7e14dcfSSatish Balay 	  ierr = MatGetDiagonal(tao->hessian, nlsP->Diag); CHKERRQ(ierr);
453*a7e14dcfSSatish Balay 	  ierr = VecAbs(nlsP->Diag); CHKERRQ(ierr);
454*a7e14dcfSSatish Balay 	  ierr = VecReciprocal(nlsP->Diag); CHKERRQ(ierr);
455*a7e14dcfSSatish Balay 	  ierr = MatLMVMSetScale(nlsP->M,nlsP->Diag); CHKERRQ(ierr);
456*a7e14dcfSSatish Balay       }
457*a7e14dcfSSatish Balay       /* Update the limited memory preconditioner */
458*a7e14dcfSSatish Balay       ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
459*a7e14dcfSSatish Balay       ++bfgsUpdates;
460*a7e14dcfSSatish Balay     }
461*a7e14dcfSSatish Balay 
462*a7e14dcfSSatish Balay     /* Solve the Newton system of equations */
463*a7e14dcfSSatish Balay     ierr = KSPSetOperators(tao->ksp,tao->hessian,tao->hessian_pre,matflag); CHKERRQ(ierr);
464*a7e14dcfSSatish Balay     if (NLS_KSP_NASH == nlsP->ksp_type ||
465*a7e14dcfSSatish Balay         NLS_KSP_STCG == nlsP->ksp_type ||
466*a7e14dcfSSatish Balay         NLS_KSP_GLTR == nlsP->ksp_type) {
467*a7e14dcfSSatish Balay 
468*a7e14dcfSSatish Balay       if (NLS_KSP_NASH == nlsP->ksp_type) {
469*a7e14dcfSSatish Balay 	ierr = KSPNASHSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
470*a7e14dcfSSatish Balay       } else if (NLS_KSP_STCG == nlsP->ksp_type) {
471*a7e14dcfSSatish Balay 	 ierr = KSPSTCGSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
472*a7e14dcfSSatish Balay       } else if (NLS_KSP_GLTR == nlsP->ksp_type) {
473*a7e14dcfSSatish Balay 	ierr = KSPGLTRSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
474*a7e14dcfSSatish Balay       }
475*a7e14dcfSSatish Balay 
476*a7e14dcfSSatish Balay       ierr = KSPSolve(tao->ksp, tao->gradient, nlsP->D); CHKERRQ(ierr);
477*a7e14dcfSSatish Balay       ierr = KSPGetIterationNumber(tao->ksp,&kspits); CHKERRQ(ierr);
478*a7e14dcfSSatish Balay       tao->ksp_its+=kspits;
479*a7e14dcfSSatish Balay 
480*a7e14dcfSSatish Balay       if (NLS_KSP_NASH == nlsP->ksp_type) {
481*a7e14dcfSSatish Balay 	ierr = KSPNASHGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr);
482*a7e14dcfSSatish Balay       } else if (NLS_KSP_STCG == nlsP->ksp_type) {
483*a7e14dcfSSatish Balay 	 ierr = KSPSTCGGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr);
484*a7e14dcfSSatish Balay       } else if (NLS_KSP_GLTR == nlsP->ksp_type) {
485*a7e14dcfSSatish Balay 	ierr = KSPGLTRGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr);
486*a7e14dcfSSatish Balay       }
487*a7e14dcfSSatish Balay 
488*a7e14dcfSSatish Balay       if (0.0 == tao->trust) {
489*a7e14dcfSSatish Balay         /* Radius was uninitialized; use the norm of the direction */
490*a7e14dcfSSatish Balay         if (norm_d > 0.0) {
491*a7e14dcfSSatish Balay           tao->trust = norm_d;
492*a7e14dcfSSatish Balay 
493*a7e14dcfSSatish Balay           /* Modify the radius if it is too large or small */
494*a7e14dcfSSatish Balay           tao->trust = PetscMax(tao->trust, nlsP->min_radius);
495*a7e14dcfSSatish Balay           tao->trust = PetscMin(tao->trust, nlsP->max_radius);
496*a7e14dcfSSatish Balay         }
497*a7e14dcfSSatish Balay         else {
498*a7e14dcfSSatish Balay           /* The direction was bad; set radius to default value and re-solve
499*a7e14dcfSSatish Balay 	     the trust-region subproblem to get a direction */
500*a7e14dcfSSatish Balay 	  tao->trust = tao->trust0;
501*a7e14dcfSSatish Balay 
502*a7e14dcfSSatish Balay           /* Modify the radius if it is too large or small */
503*a7e14dcfSSatish Balay           tao->trust = PetscMax(tao->trust, nlsP->min_radius);
504*a7e14dcfSSatish Balay           tao->trust = PetscMin(tao->trust, nlsP->max_radius);
505*a7e14dcfSSatish Balay 
506*a7e14dcfSSatish Balay 	  if (NLS_KSP_NASH == nlsP->ksp_type) {
507*a7e14dcfSSatish Balay 	    ierr = KSPNASHSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
508*a7e14dcfSSatish Balay 	  } else if (NLS_KSP_STCG == nlsP->ksp_type) {
509*a7e14dcfSSatish Balay 	    ierr = KSPSTCGSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
510*a7e14dcfSSatish Balay 	  } else if (NLS_KSP_GLTR == nlsP->ksp_type) {
511*a7e14dcfSSatish Balay 	    ierr = KSPGLTRSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr);
512*a7e14dcfSSatish Balay 	  }
513*a7e14dcfSSatish Balay 
514*a7e14dcfSSatish Balay 	  ierr = KSPSolve(tao->ksp, tao->gradient, nlsP->D); CHKERRQ(ierr);
515*a7e14dcfSSatish Balay 	  ierr = KSPGetIterationNumber(tao->ksp,&kspits); CHKERRQ(ierr);
516*a7e14dcfSSatish Balay 	  tao->ksp_its+=kspits;
517*a7e14dcfSSatish Balay 	  if (NLS_KSP_NASH == nlsP->ksp_type) {
518*a7e14dcfSSatish Balay 	    ierr = KSPNASHGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr);
519*a7e14dcfSSatish Balay 	  } else if (NLS_KSP_STCG == nlsP->ksp_type) {
520*a7e14dcfSSatish Balay 	    ierr = KSPSTCGGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr);
521*a7e14dcfSSatish Balay 	  } else if (NLS_KSP_GLTR == nlsP->ksp_type) {
522*a7e14dcfSSatish Balay 	    ierr = KSPGLTRGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr);
523*a7e14dcfSSatish Balay 	  }
524*a7e14dcfSSatish Balay 
525*a7e14dcfSSatish Balay           if (norm_d == 0.0) {
526*a7e14dcfSSatish Balay             SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
527*a7e14dcfSSatish Balay           }
528*a7e14dcfSSatish Balay         }
529*a7e14dcfSSatish Balay       }
530*a7e14dcfSSatish Balay     }
531*a7e14dcfSSatish Balay     else {
532*a7e14dcfSSatish Balay       ierr = KSPSolve(tao->ksp, tao->gradient, nlsP->D); CHKERRQ(ierr);
533*a7e14dcfSSatish Balay       ierr = KSPGetIterationNumber(tao->ksp, &kspits); CHKERRQ(ierr);
534*a7e14dcfSSatish Balay       tao->ksp_its += kspits;
535*a7e14dcfSSatish Balay     }
536*a7e14dcfSSatish Balay     ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr);
537*a7e14dcfSSatish Balay     ierr = KSPGetConvergedReason(tao->ksp, &ksp_reason); CHKERRQ(ierr);
538*a7e14dcfSSatish Balay     if ((KSP_DIVERGED_INDEFINITE_PC == ksp_reason) &&
539*a7e14dcfSSatish Balay         (NLS_PC_BFGS == nlsP->pc_type) && (bfgsUpdates > 1)) {
540*a7e14dcfSSatish Balay       /* Preconditioner is numerically indefinite; reset the
541*a7e14dcfSSatish Balay 	 approximate if using BFGS preconditioning. */
542*a7e14dcfSSatish Balay 
543*a7e14dcfSSatish Balay       if (f != 0.0) {
544*a7e14dcfSSatish Balay         delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
545*a7e14dcfSSatish Balay       }
546*a7e14dcfSSatish Balay       else {
547*a7e14dcfSSatish Balay         delta = 2.0 / (gnorm*gnorm);
548*a7e14dcfSSatish Balay       }
549*a7e14dcfSSatish Balay       ierr = MatLMVMSetDelta(nlsP->M,delta); CHKERRQ(ierr);
550*a7e14dcfSSatish Balay       ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr);
551*a7e14dcfSSatish Balay       ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
552*a7e14dcfSSatish Balay       bfgsUpdates = 1;
553*a7e14dcfSSatish Balay     }
554*a7e14dcfSSatish Balay 
555*a7e14dcfSSatish Balay     if (KSP_CONVERGED_ATOL == ksp_reason) {
556*a7e14dcfSSatish Balay       ++nlsP->ksp_atol;
557*a7e14dcfSSatish Balay     }
558*a7e14dcfSSatish Balay     else if (KSP_CONVERGED_RTOL == ksp_reason) {
559*a7e14dcfSSatish Balay       ++nlsP->ksp_rtol;
560*a7e14dcfSSatish Balay     }
561*a7e14dcfSSatish Balay     else if (KSP_CONVERGED_CG_CONSTRAINED == ksp_reason) {
562*a7e14dcfSSatish Balay       ++nlsP->ksp_ctol;
563*a7e14dcfSSatish Balay     }
564*a7e14dcfSSatish Balay     else if (KSP_CONVERGED_CG_NEG_CURVE == ksp_reason) {
565*a7e14dcfSSatish Balay       ++nlsP->ksp_negc;
566*a7e14dcfSSatish Balay     }
567*a7e14dcfSSatish Balay     else if (KSP_DIVERGED_DTOL == ksp_reason) {
568*a7e14dcfSSatish Balay       ++nlsP->ksp_dtol;
569*a7e14dcfSSatish Balay     }
570*a7e14dcfSSatish Balay     else if (KSP_DIVERGED_ITS == ksp_reason) {
571*a7e14dcfSSatish Balay       ++nlsP->ksp_iter;
572*a7e14dcfSSatish Balay     }
573*a7e14dcfSSatish Balay     else {
574*a7e14dcfSSatish Balay       ++nlsP->ksp_othr;
575*a7e14dcfSSatish Balay     }
576*a7e14dcfSSatish Balay 
577*a7e14dcfSSatish Balay     /* Check for success (descent direction) */
578*a7e14dcfSSatish Balay     ierr = VecDot(nlsP->D, tao->gradient, &gdx); CHKERRQ(ierr);
579*a7e14dcfSSatish Balay     if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
580*a7e14dcfSSatish Balay       /* Newton step is not descent or direction produced Inf or NaN
581*a7e14dcfSSatish Balay 	 Update the perturbation for next time */
582*a7e14dcfSSatish Balay       if (pert <= 0.0) {
583*a7e14dcfSSatish Balay 	/* Initialize the perturbation */
584*a7e14dcfSSatish Balay 	pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm));
585*a7e14dcfSSatish Balay         if (NLS_KSP_GLTR == nlsP->ksp_type) {
586*a7e14dcfSSatish Balay 	  ierr = KSPGLTRGetMinEig(tao->ksp,&e_min); CHKERRQ(ierr);
587*a7e14dcfSSatish Balay 	  pert = PetscMax(pert, -e_min);
588*a7e14dcfSSatish Balay         }
589*a7e14dcfSSatish Balay       }
590*a7e14dcfSSatish Balay       else {
591*a7e14dcfSSatish Balay 	/* Increase the perturbation */
592*a7e14dcfSSatish Balay 	pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm));
593*a7e14dcfSSatish Balay       }
594*a7e14dcfSSatish Balay 
595*a7e14dcfSSatish Balay       if (NLS_PC_BFGS != nlsP->pc_type) {
596*a7e14dcfSSatish Balay 	/* We don't have the bfgs matrix around and updated
597*a7e14dcfSSatish Balay 	   Must use gradient direction in this case */
598*a7e14dcfSSatish Balay 	ierr = VecCopy(tao->gradient, nlsP->D); CHKERRQ(ierr);
599*a7e14dcfSSatish Balay 	ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr);
600*a7e14dcfSSatish Balay 	++nlsP->grad;
601*a7e14dcfSSatish Balay         stepType = NLS_GRADIENT;
602*a7e14dcfSSatish Balay       }
603*a7e14dcfSSatish Balay       else {
604*a7e14dcfSSatish Balay         /* Attempt to use the BFGS direction */
605*a7e14dcfSSatish Balay 	ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr);
606*a7e14dcfSSatish Balay 	ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr);
607*a7e14dcfSSatish Balay 
608*a7e14dcfSSatish Balay         /* Check for success (descent direction) */
609*a7e14dcfSSatish Balay 	ierr = VecDot(tao->gradient, nlsP->D, &gdx); CHKERRQ(ierr);
610*a7e14dcfSSatish Balay         if ((gdx >= 0) || PetscIsInfOrNanReal(gdx)) {
611*a7e14dcfSSatish Balay           /* BFGS direction is not descent or direction produced not a number
612*a7e14dcfSSatish Balay 	     We can assert bfgsUpdates > 1 in this case because
613*a7e14dcfSSatish Balay 	     the first solve produces the scaled gradient direction,
614*a7e14dcfSSatish Balay 	     which is guaranteed to be descent */
615*a7e14dcfSSatish Balay 
616*a7e14dcfSSatish Balay           /* Use steepest descent direction (scaled) */
617*a7e14dcfSSatish Balay 
618*a7e14dcfSSatish Balay           if (f != 0.0) {
619*a7e14dcfSSatish Balay             delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
620*a7e14dcfSSatish Balay           }
621*a7e14dcfSSatish Balay           else {
622*a7e14dcfSSatish Balay             delta = 2.0 / (gnorm*gnorm);
623*a7e14dcfSSatish Balay           }
624*a7e14dcfSSatish Balay 	  ierr = MatLMVMSetDelta(nlsP->M, delta); CHKERRQ(ierr);
625*a7e14dcfSSatish Balay 	  ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr);
626*a7e14dcfSSatish Balay 	  ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
627*a7e14dcfSSatish Balay 	  ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr);
628*a7e14dcfSSatish Balay 	  ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr);
629*a7e14dcfSSatish Balay 
630*a7e14dcfSSatish Balay           bfgsUpdates = 1;
631*a7e14dcfSSatish Balay           ++nlsP->sgrad;
632*a7e14dcfSSatish Balay           stepType = NLS_SCALED_GRADIENT;
633*a7e14dcfSSatish Balay         }
634*a7e14dcfSSatish Balay         else {
635*a7e14dcfSSatish Balay           if (1 == bfgsUpdates) {
636*a7e14dcfSSatish Balay 	    /* The first BFGS direction is always the scaled gradient */
637*a7e14dcfSSatish Balay             ++nlsP->sgrad;
638*a7e14dcfSSatish Balay             stepType = NLS_SCALED_GRADIENT;
639*a7e14dcfSSatish Balay           }
640*a7e14dcfSSatish Balay           else {
641*a7e14dcfSSatish Balay             ++nlsP->bfgs;
642*a7e14dcfSSatish Balay             stepType = NLS_BFGS;
643*a7e14dcfSSatish Balay           }
644*a7e14dcfSSatish Balay         }
645*a7e14dcfSSatish Balay       }
646*a7e14dcfSSatish Balay     }
647*a7e14dcfSSatish Balay     else {
648*a7e14dcfSSatish Balay       /* Computed Newton step is descent */
649*a7e14dcfSSatish Balay       switch (ksp_reason) {
650*a7e14dcfSSatish Balay       case KSP_DIVERGED_NANORINF:
651*a7e14dcfSSatish Balay       case KSP_DIVERGED_BREAKDOWN:
652*a7e14dcfSSatish Balay       case KSP_DIVERGED_INDEFINITE_MAT:
653*a7e14dcfSSatish Balay       case KSP_DIVERGED_INDEFINITE_PC:
654*a7e14dcfSSatish Balay       case KSP_CONVERGED_CG_NEG_CURVE:
655*a7e14dcfSSatish Balay         /* Matrix or preconditioner is indefinite; increase perturbation */
656*a7e14dcfSSatish Balay         if (pert <= 0.0) {
657*a7e14dcfSSatish Balay 	  /* Initialize the perturbation */
658*a7e14dcfSSatish Balay           pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm));
659*a7e14dcfSSatish Balay           if (NLS_KSP_GLTR == nlsP->ksp_type) {
660*a7e14dcfSSatish Balay 	    ierr = KSPGLTRGetMinEig(tao->ksp, &e_min); CHKERRQ(ierr);
661*a7e14dcfSSatish Balay 	    pert = PetscMax(pert, -e_min);
662*a7e14dcfSSatish Balay           }
663*a7e14dcfSSatish Balay         }
664*a7e14dcfSSatish Balay         else {
665*a7e14dcfSSatish Balay 	  /* Increase the perturbation */
666*a7e14dcfSSatish Balay 	  pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm));
667*a7e14dcfSSatish Balay         }
668*a7e14dcfSSatish Balay         break;
669*a7e14dcfSSatish Balay 
670*a7e14dcfSSatish Balay       default:
671*a7e14dcfSSatish Balay         /* Newton step computation is good; decrease perturbation */
672*a7e14dcfSSatish Balay         pert = PetscMin(nlsP->psfac * pert, nlsP->pmsfac * gnorm);
673*a7e14dcfSSatish Balay         if (pert < nlsP->pmin) {
674*a7e14dcfSSatish Balay 	  pert = 0.0;
675*a7e14dcfSSatish Balay         }
676*a7e14dcfSSatish Balay         break;
677*a7e14dcfSSatish Balay       }
678*a7e14dcfSSatish Balay 
679*a7e14dcfSSatish Balay       ++nlsP->newt;
680*a7e14dcfSSatish Balay       stepType = NLS_NEWTON;
681*a7e14dcfSSatish Balay     }
682*a7e14dcfSSatish Balay 
683*a7e14dcfSSatish Balay     /* Perform the linesearch */
684*a7e14dcfSSatish Balay     fold = f;
685*a7e14dcfSSatish Balay     ierr = VecCopy(tao->solution, nlsP->Xold); CHKERRQ(ierr);
686*a7e14dcfSSatish Balay     ierr = VecCopy(tao->gradient, nlsP->Gold); CHKERRQ(ierr);
687*a7e14dcfSSatish Balay 
688*a7e14dcfSSatish Balay     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, nlsP->D, &step, &ls_reason); CHKERRQ(ierr);
689*a7e14dcfSSatish Balay     ierr = TaoAddLineSearchCounts(tao); CHKERRQ(ierr);
690*a7e14dcfSSatish Balay 
691*a7e14dcfSSatish Balay     while (ls_reason != TAOLINESEARCH_SUCCESS &&
692*a7e14dcfSSatish Balay 	   ls_reason != TAOLINESEARCH_SUCCESS_USER &&
693*a7e14dcfSSatish Balay 	   stepType != NLS_GRADIENT) {      /* Linesearch failed */
694*a7e14dcfSSatish Balay       f = fold;
695*a7e14dcfSSatish Balay       ierr = VecCopy(nlsP->Xold, tao->solution); CHKERRQ(ierr);
696*a7e14dcfSSatish Balay       ierr = VecCopy(nlsP->Gold, tao->gradient); CHKERRQ(ierr);
697*a7e14dcfSSatish Balay 
698*a7e14dcfSSatish Balay       switch(stepType) {
699*a7e14dcfSSatish Balay       case NLS_NEWTON:
700*a7e14dcfSSatish Balay         /* Failed to obtain acceptable iterate with Newton 1step
701*a7e14dcfSSatish Balay 	   Update the perturbation for next time */
702*a7e14dcfSSatish Balay         if (pert <= 0.0) {
703*a7e14dcfSSatish Balay           /* Initialize the perturbation */
704*a7e14dcfSSatish Balay           pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm));
705*a7e14dcfSSatish Balay           if (NLS_KSP_GLTR == nlsP->ksp_type) {
706*a7e14dcfSSatish Balay 	    ierr = KSPGLTRGetMinEig(tao->ksp,&e_min); CHKERRQ(ierr);
707*a7e14dcfSSatish Balay 	    pert = PetscMax(pert, -e_min);
708*a7e14dcfSSatish Balay           }
709*a7e14dcfSSatish Balay         }
710*a7e14dcfSSatish Balay         else {
711*a7e14dcfSSatish Balay           /* Increase the perturbation */
712*a7e14dcfSSatish Balay           pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm));
713*a7e14dcfSSatish Balay         }
714*a7e14dcfSSatish Balay 
715*a7e14dcfSSatish Balay         if (NLS_PC_BFGS != nlsP->pc_type) {
716*a7e14dcfSSatish Balay 	  /* We don't have the bfgs matrix around and being updated
717*a7e14dcfSSatish Balay 	     Must use gradient direction in this case */
718*a7e14dcfSSatish Balay 	  ierr = VecCopy(tao->gradient, nlsP->D); CHKERRQ(ierr);
719*a7e14dcfSSatish Balay 	  ++nlsP->grad;
720*a7e14dcfSSatish Balay           stepType = NLS_GRADIENT;
721*a7e14dcfSSatish Balay         }
722*a7e14dcfSSatish Balay         else {
723*a7e14dcfSSatish Balay           /* Attempt to use the BFGS direction */
724*a7e14dcfSSatish Balay 	  ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr);
725*a7e14dcfSSatish Balay           /* Check for success (descent direction) */
726*a7e14dcfSSatish Balay 	  ierr = VecDot(tao->solution, nlsP->D, &gdx); CHKERRQ(ierr);
727*a7e14dcfSSatish Balay           if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
728*a7e14dcfSSatish Balay             /* BFGS direction is not descent or direction produced not a number
729*a7e14dcfSSatish Balay 	       We can assert bfgsUpdates > 1 in this case
730*a7e14dcfSSatish Balay 	       Use steepest descent direction (scaled) */
731*a7e14dcfSSatish Balay 
732*a7e14dcfSSatish Balay             if (f != 0.0) {
733*a7e14dcfSSatish Balay               delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
734*a7e14dcfSSatish Balay             }
735*a7e14dcfSSatish Balay             else {
736*a7e14dcfSSatish Balay               delta = 2.0 / (gnorm*gnorm);
737*a7e14dcfSSatish Balay             }
738*a7e14dcfSSatish Balay 	    ierr = MatLMVMSetDelta(nlsP->M, delta); CHKERRQ(ierr);
739*a7e14dcfSSatish Balay 	    ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr);
740*a7e14dcfSSatish Balay 	    ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
741*a7e14dcfSSatish Balay 	    ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr);
742*a7e14dcfSSatish Balay 
743*a7e14dcfSSatish Balay             bfgsUpdates = 1;
744*a7e14dcfSSatish Balay             ++nlsP->sgrad;
745*a7e14dcfSSatish Balay             stepType = NLS_SCALED_GRADIENT;
746*a7e14dcfSSatish Balay           }
747*a7e14dcfSSatish Balay           else {
748*a7e14dcfSSatish Balay             if (1 == bfgsUpdates) {
749*a7e14dcfSSatish Balay 	      /* The first BFGS direction is always the scaled gradient */
750*a7e14dcfSSatish Balay               ++nlsP->sgrad;
751*a7e14dcfSSatish Balay               stepType = NLS_SCALED_GRADIENT;
752*a7e14dcfSSatish Balay             }
753*a7e14dcfSSatish Balay             else {
754*a7e14dcfSSatish Balay               ++nlsP->bfgs;
755*a7e14dcfSSatish Balay               stepType = NLS_BFGS;
756*a7e14dcfSSatish Balay             }
757*a7e14dcfSSatish Balay           }
758*a7e14dcfSSatish Balay         }
759*a7e14dcfSSatish Balay 	break;
760*a7e14dcfSSatish Balay 
761*a7e14dcfSSatish Balay       case NLS_BFGS:
762*a7e14dcfSSatish Balay         /* Can only enter if pc_type == NLS_PC_BFGS
763*a7e14dcfSSatish Balay 	   Failed to obtain acceptable iterate with BFGS step
764*a7e14dcfSSatish Balay 	   Attempt to use the scaled gradient direction */
765*a7e14dcfSSatish Balay 
766*a7e14dcfSSatish Balay         if (f != 0.0) {
767*a7e14dcfSSatish Balay           delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
768*a7e14dcfSSatish Balay         }
769*a7e14dcfSSatish Balay         else {
770*a7e14dcfSSatish Balay           delta = 2.0 / (gnorm*gnorm);
771*a7e14dcfSSatish Balay         }
772*a7e14dcfSSatish Balay 	ierr = MatLMVMSetDelta(nlsP->M, delta); CHKERRQ(ierr);
773*a7e14dcfSSatish Balay 	ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr);
774*a7e14dcfSSatish Balay 	ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
775*a7e14dcfSSatish Balay 	ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr);
776*a7e14dcfSSatish Balay 
777*a7e14dcfSSatish Balay         bfgsUpdates = 1;
778*a7e14dcfSSatish Balay         ++nlsP->sgrad;
779*a7e14dcfSSatish Balay         stepType = NLS_SCALED_GRADIENT;
780*a7e14dcfSSatish Balay         break;
781*a7e14dcfSSatish Balay 
782*a7e14dcfSSatish Balay       case NLS_SCALED_GRADIENT:
783*a7e14dcfSSatish Balay         /* Can only enter if pc_type == NLS_PC_BFGS
784*a7e14dcfSSatish Balay 	   The scaled gradient step did not produce a new iterate;
785*a7e14dcfSSatish Balay 	   attemp to use the gradient direction.
786*a7e14dcfSSatish Balay 	   Need to make sure we are not using a different diagonal scaling */
787*a7e14dcfSSatish Balay 
788*a7e14dcfSSatish Balay 	ierr = MatLMVMSetScale(nlsP->M,0); CHKERRQ(ierr);
789*a7e14dcfSSatish Balay 	ierr = MatLMVMSetDelta(nlsP->M,1.0); CHKERRQ(ierr);
790*a7e14dcfSSatish Balay 	ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr);
791*a7e14dcfSSatish Balay 	ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
792*a7e14dcfSSatish Balay 	ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr);
793*a7e14dcfSSatish Balay 
794*a7e14dcfSSatish Balay         bfgsUpdates = 1;
795*a7e14dcfSSatish Balay 	++nlsP->grad;
796*a7e14dcfSSatish Balay         stepType = NLS_GRADIENT;
797*a7e14dcfSSatish Balay         break;
798*a7e14dcfSSatish Balay       }
799*a7e14dcfSSatish Balay       ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr);
800*a7e14dcfSSatish Balay 
801*a7e14dcfSSatish Balay       ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, nlsP->D, &step, &ls_reason); CHKERRQ(ierr);
802*a7e14dcfSSatish Balay       ierr = TaoLineSearchGetFullStepObjective(tao->linesearch, &f_full); CHKERRQ(ierr);
803*a7e14dcfSSatish Balay       ierr = TaoAddLineSearchCounts(tao); CHKERRQ(ierr);
804*a7e14dcfSSatish Balay     }
805*a7e14dcfSSatish Balay 
806*a7e14dcfSSatish Balay     if (ls_reason != TAOLINESEARCH_SUCCESS &&
807*a7e14dcfSSatish Balay 	ls_reason != TAOLINESEARCH_SUCCESS_USER) {
808*a7e14dcfSSatish Balay       /* Failed to find an improving point */
809*a7e14dcfSSatish Balay       f = fold;
810*a7e14dcfSSatish Balay       ierr = VecCopy(nlsP->Xold, tao->solution); CHKERRQ(ierr);
811*a7e14dcfSSatish Balay       ierr = VecCopy(nlsP->Gold, tao->gradient); CHKERRQ(ierr);
812*a7e14dcfSSatish Balay       step = 0.0;
813*a7e14dcfSSatish Balay       reason = TAO_DIVERGED_LS_FAILURE;
814*a7e14dcfSSatish Balay       tao->reason = TAO_DIVERGED_LS_FAILURE;
815*a7e14dcfSSatish Balay       break;
816*a7e14dcfSSatish Balay     }
817*a7e14dcfSSatish Balay 
818*a7e14dcfSSatish Balay     /* Update trust region radius */
819*a7e14dcfSSatish Balay     if (NLS_KSP_NASH == nlsP->ksp_type ||
820*a7e14dcfSSatish Balay         NLS_KSP_STCG == nlsP->ksp_type ||
821*a7e14dcfSSatish Balay         NLS_KSP_GLTR == nlsP->ksp_type) {
822*a7e14dcfSSatish Balay       switch(nlsP->update_type) {
823*a7e14dcfSSatish Balay       case NLS_UPDATE_STEP:
824*a7e14dcfSSatish Balay         if (stepType == NLS_NEWTON) {
825*a7e14dcfSSatish Balay           if (step < nlsP->nu1) {
826*a7e14dcfSSatish Balay             /* Very bad step taken; reduce radius */
827*a7e14dcfSSatish Balay             tao->trust = nlsP->omega1 * PetscMin(norm_d, tao->trust);
828*a7e14dcfSSatish Balay           }
829*a7e14dcfSSatish Balay           else if (step < nlsP->nu2) {
830*a7e14dcfSSatish Balay             /* Reasonably bad step taken; reduce radius */
831*a7e14dcfSSatish Balay             tao->trust = nlsP->omega2 * PetscMin(norm_d, tao->trust);
832*a7e14dcfSSatish Balay           }
833*a7e14dcfSSatish Balay           else if (step < nlsP->nu3) {
834*a7e14dcfSSatish Balay             /*  Reasonable step was taken; leave radius alone */
835*a7e14dcfSSatish Balay             if (nlsP->omega3 < 1.0) {
836*a7e14dcfSSatish Balay               tao->trust = nlsP->omega3 * PetscMin(norm_d, tao->trust);
837*a7e14dcfSSatish Balay             }
838*a7e14dcfSSatish Balay             else if (nlsP->omega3 > 1.0) {
839*a7e14dcfSSatish Balay               tao->trust = PetscMax(nlsP->omega3 * norm_d, tao->trust);
840*a7e14dcfSSatish Balay             }
841*a7e14dcfSSatish Balay           }
842*a7e14dcfSSatish Balay           else if (step < nlsP->nu4) {
843*a7e14dcfSSatish Balay             /*  Full step taken; increase the radius */
844*a7e14dcfSSatish Balay             tao->trust = PetscMax(nlsP->omega4 * norm_d, tao->trust);
845*a7e14dcfSSatish Balay           }
846*a7e14dcfSSatish Balay           else {
847*a7e14dcfSSatish Balay             /*  More than full step taken; increase the radius */
848*a7e14dcfSSatish Balay             tao->trust = PetscMax(nlsP->omega5 * norm_d, tao->trust);
849*a7e14dcfSSatish Balay           }
850*a7e14dcfSSatish Balay         }
851*a7e14dcfSSatish Balay         else {
852*a7e14dcfSSatish Balay           /*  Newton step was not good; reduce the radius */
853*a7e14dcfSSatish Balay           tao->trust = nlsP->omega1 * PetscMin(norm_d, tao->trust);
854*a7e14dcfSSatish Balay         }
855*a7e14dcfSSatish Balay         break;
856*a7e14dcfSSatish Balay 
857*a7e14dcfSSatish Balay       case NLS_UPDATE_REDUCTION:
858*a7e14dcfSSatish Balay         if (stepType == NLS_NEWTON) {
859*a7e14dcfSSatish Balay 	  /*  Get predicted reduction */
860*a7e14dcfSSatish Balay 
861*a7e14dcfSSatish Balay 	  if (NLS_KSP_STCG == nlsP->ksp_type) {
862*a7e14dcfSSatish Balay 	      ierr = KSPSTCGGetObjFcn(tao->ksp,&prered);
863*a7e14dcfSSatish Balay 	  } else if (NLS_KSP_NASH == nlsP->ksp_type)  {
864*a7e14dcfSSatish Balay 	      ierr = KSPNASHGetObjFcn(tao->ksp,&prered);
865*a7e14dcfSSatish Balay 	  } else {
866*a7e14dcfSSatish Balay 	      ierr = KSPGLTRGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr);
867*a7e14dcfSSatish Balay 	  }
868*a7e14dcfSSatish Balay 
869*a7e14dcfSSatish Balay 
870*a7e14dcfSSatish Balay 
871*a7e14dcfSSatish Balay 
872*a7e14dcfSSatish Balay           if (prered >= 0.0) {
873*a7e14dcfSSatish Balay             /*  The predicted reduction has the wrong sign.  This cannot */
874*a7e14dcfSSatish Balay             /*  happen in infinite precision arithmetic.  Step should */
875*a7e14dcfSSatish Balay             /*  be rejected! */
876*a7e14dcfSSatish Balay             tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d);
877*a7e14dcfSSatish Balay           }
878*a7e14dcfSSatish Balay           else {
879*a7e14dcfSSatish Balay             if (PetscIsInfOrNanReal(f_full)) {
880*a7e14dcfSSatish Balay               tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d);
881*a7e14dcfSSatish Balay             }
882*a7e14dcfSSatish Balay             else {
883*a7e14dcfSSatish Balay               /*  Compute and actual reduction */
884*a7e14dcfSSatish Balay               actred = fold - f_full;
885*a7e14dcfSSatish Balay               prered = -prered;
886*a7e14dcfSSatish Balay               if ((PetscAbsScalar(actred) <= nlsP->epsilon) &&
887*a7e14dcfSSatish Balay                   (PetscAbsScalar(prered) <= nlsP->epsilon)) {
888*a7e14dcfSSatish Balay                 kappa = 1.0;
889*a7e14dcfSSatish Balay               }
890*a7e14dcfSSatish Balay               else {
891*a7e14dcfSSatish Balay                 kappa = actred / prered;
892*a7e14dcfSSatish Balay               }
893*a7e14dcfSSatish Balay 
894*a7e14dcfSSatish Balay               /*  Accept of reject the step and update radius */
895*a7e14dcfSSatish Balay               if (kappa < nlsP->eta1) {
896*a7e14dcfSSatish Balay                 /*  Very bad step */
897*a7e14dcfSSatish Balay                 tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d);
898*a7e14dcfSSatish Balay               }
899*a7e14dcfSSatish Balay               else if (kappa < nlsP->eta2) {
900*a7e14dcfSSatish Balay                 /*  Marginal bad step */
901*a7e14dcfSSatish Balay                 tao->trust = nlsP->alpha2 * PetscMin(tao->trust, norm_d);
902*a7e14dcfSSatish Balay               }
903*a7e14dcfSSatish Balay               else if (kappa < nlsP->eta3) {
904*a7e14dcfSSatish Balay                 /*  Reasonable step */
905*a7e14dcfSSatish Balay                 if (nlsP->alpha3 < 1.0) {
906*a7e14dcfSSatish Balay                   tao->trust = nlsP->alpha3 * PetscMin(norm_d, tao->trust);
907*a7e14dcfSSatish Balay                 }
908*a7e14dcfSSatish Balay                 else if (nlsP->alpha3 > 1.0) {
909*a7e14dcfSSatish Balay                   tao->trust = PetscMax(nlsP->alpha3 * norm_d, tao->trust);
910*a7e14dcfSSatish Balay                 }
911*a7e14dcfSSatish Balay               }
912*a7e14dcfSSatish Balay               else if (kappa < nlsP->eta4) {
913*a7e14dcfSSatish Balay                 /*  Good step */
914*a7e14dcfSSatish Balay                 tao->trust = PetscMax(nlsP->alpha4 * norm_d, tao->trust);
915*a7e14dcfSSatish Balay               }
916*a7e14dcfSSatish Balay               else {
917*a7e14dcfSSatish Balay                 /*  Very good step */
918*a7e14dcfSSatish Balay                 tao->trust = PetscMax(nlsP->alpha5 * norm_d, tao->trust);
919*a7e14dcfSSatish Balay               }
920*a7e14dcfSSatish Balay             }
921*a7e14dcfSSatish Balay           }
922*a7e14dcfSSatish Balay         }
923*a7e14dcfSSatish Balay         else {
924*a7e14dcfSSatish Balay           /*  Newton step was not good; reduce the radius */
925*a7e14dcfSSatish Balay           tao->trust = nlsP->alpha1 * PetscMin(norm_d, tao->trust);
926*a7e14dcfSSatish Balay         }
927*a7e14dcfSSatish Balay         break;
928*a7e14dcfSSatish Balay 
929*a7e14dcfSSatish Balay       default:
930*a7e14dcfSSatish Balay         if (stepType == NLS_NEWTON) {
931*a7e14dcfSSatish Balay 
932*a7e14dcfSSatish Balay 	  if (NLS_KSP_STCG == nlsP->ksp_type) {
933*a7e14dcfSSatish Balay 	      ierr = KSPSTCGGetObjFcn(tao->ksp,&prered);
934*a7e14dcfSSatish Balay 	  } else if (NLS_KSP_NASH == nlsP->ksp_type)  {
935*a7e14dcfSSatish Balay 	      ierr = KSPNASHGetObjFcn(tao->ksp,&prered);
936*a7e14dcfSSatish Balay 	  } else {
937*a7e14dcfSSatish Balay 	      ierr = KSPGLTRGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr);
938*a7e14dcfSSatish Balay 	  }
939*a7e14dcfSSatish Balay           if (prered >= 0.0) {
940*a7e14dcfSSatish Balay             /*  The predicted reduction has the wrong sign.  This cannot */
941*a7e14dcfSSatish Balay             /*  happen in infinite precision arithmetic.  Step should */
942*a7e14dcfSSatish Balay             /*  be rejected! */
943*a7e14dcfSSatish Balay             tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
944*a7e14dcfSSatish Balay           }
945*a7e14dcfSSatish Balay           else {
946*a7e14dcfSSatish Balay             if (PetscIsInfOrNanReal(f_full)) {
947*a7e14dcfSSatish Balay               tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
948*a7e14dcfSSatish Balay             }
949*a7e14dcfSSatish Balay             else {
950*a7e14dcfSSatish Balay               actred = fold - f_full;
951*a7e14dcfSSatish Balay               prered = -prered;
952*a7e14dcfSSatish Balay               if ((PetscAbsScalar(actred) <= nlsP->epsilon) &&
953*a7e14dcfSSatish Balay                   (PetscAbsScalar(prered) <= nlsP->epsilon)) {
954*a7e14dcfSSatish Balay                 kappa = 1.0;
955*a7e14dcfSSatish Balay               }
956*a7e14dcfSSatish Balay               else {
957*a7e14dcfSSatish Balay                 kappa = actred / prered;
958*a7e14dcfSSatish Balay               }
959*a7e14dcfSSatish Balay 
960*a7e14dcfSSatish Balay               tau_1 = nlsP->theta * gdx / (nlsP->theta * gdx - (1.0 - nlsP->theta) * prered + actred);
961*a7e14dcfSSatish Balay               tau_2 = nlsP->theta * gdx / (nlsP->theta * gdx + (1.0 + nlsP->theta) * prered - actred);
962*a7e14dcfSSatish Balay               tau_min = PetscMin(tau_1, tau_2);
963*a7e14dcfSSatish Balay               tau_max = PetscMax(tau_1, tau_2);
964*a7e14dcfSSatish Balay 
965*a7e14dcfSSatish Balay               if (kappa >= 1.0 - nlsP->mu1) {
966*a7e14dcfSSatish Balay                 /*  Great agreement */
967*a7e14dcfSSatish Balay                 if (tau_max < 1.0) {
968*a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, nlsP->gamma3 * norm_d);
969*a7e14dcfSSatish Balay                 }
970*a7e14dcfSSatish Balay                 else if (tau_max > nlsP->gamma4) {
971*a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, nlsP->gamma4 * norm_d);
972*a7e14dcfSSatish Balay                 }
973*a7e14dcfSSatish Balay                 else {
974*a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, tau_max * norm_d);
975*a7e14dcfSSatish Balay                 }
976*a7e14dcfSSatish Balay               }
977*a7e14dcfSSatish Balay               else if (kappa >= 1.0 - nlsP->mu2) {
978*a7e14dcfSSatish Balay                 /*  Good agreement */
979*a7e14dcfSSatish Balay 
980*a7e14dcfSSatish Balay                 if (tau_max < nlsP->gamma2) {
981*a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma2 * PetscMin(tao->trust, norm_d);
982*a7e14dcfSSatish Balay                 }
983*a7e14dcfSSatish Balay                 else if (tau_max > nlsP->gamma3) {
984*a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, nlsP->gamma3 * norm_d);
985*a7e14dcfSSatish Balay                 }
986*a7e14dcfSSatish Balay                 else if (tau_max < 1.0) {
987*a7e14dcfSSatish Balay                   tao->trust = tau_max * PetscMin(tao->trust, norm_d);
988*a7e14dcfSSatish Balay                 }
989*a7e14dcfSSatish Balay                 else {
990*a7e14dcfSSatish Balay                   tao->trust = PetscMax(tao->trust, tau_max * norm_d);
991*a7e14dcfSSatish Balay                 }
992*a7e14dcfSSatish Balay               }
993*a7e14dcfSSatish Balay               else {
994*a7e14dcfSSatish Balay                 /*  Not good agreement */
995*a7e14dcfSSatish Balay                 if (tau_min > 1.0) {
996*a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma2 * PetscMin(tao->trust, norm_d);
997*a7e14dcfSSatish Balay                 }
998*a7e14dcfSSatish Balay                 else if (tau_max < nlsP->gamma1) {
999*a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
1000*a7e14dcfSSatish Balay                 }
1001*a7e14dcfSSatish Balay                 else if ((tau_min < nlsP->gamma1) && (tau_max >= 1.0)) {
1002*a7e14dcfSSatish Balay                   tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d);
1003*a7e14dcfSSatish Balay                 }
1004*a7e14dcfSSatish Balay                 else if ((tau_1 >= nlsP->gamma1) && (tau_1 < 1.0) &&
1005*a7e14dcfSSatish Balay                          ((tau_2 < nlsP->gamma1) || (tau_2 >= 1.0))) {
1006*a7e14dcfSSatish Balay                   tao->trust = tau_1 * PetscMin(tao->trust, norm_d);
1007*a7e14dcfSSatish Balay                 }
1008*a7e14dcfSSatish Balay                 else if ((tau_2 >= nlsP->gamma1) && (tau_2 < 1.0) &&
1009*a7e14dcfSSatish Balay                          ((tau_1 < nlsP->gamma1) || (tau_2 >= 1.0))) {
1010*a7e14dcfSSatish Balay                   tao->trust = tau_2 * PetscMin(tao->trust, norm_d);
1011*a7e14dcfSSatish Balay                 }
1012*a7e14dcfSSatish Balay                 else {
1013*a7e14dcfSSatish Balay                   tao->trust = tau_max * PetscMin(tao->trust, norm_d);
1014*a7e14dcfSSatish Balay                 }
1015*a7e14dcfSSatish Balay               }
1016*a7e14dcfSSatish Balay             }
1017*a7e14dcfSSatish Balay           }
1018*a7e14dcfSSatish Balay         }
1019*a7e14dcfSSatish Balay         else {
1020*a7e14dcfSSatish Balay           /*  Newton step was not good; reduce the radius */
1021*a7e14dcfSSatish Balay           tao->trust = nlsP->gamma1 * PetscMin(norm_d, tao->trust);
1022*a7e14dcfSSatish Balay         }
1023*a7e14dcfSSatish Balay         break;
1024*a7e14dcfSSatish Balay       }
1025*a7e14dcfSSatish Balay 
1026*a7e14dcfSSatish Balay       /*  The radius may have been increased; modify if it is too large */
1027*a7e14dcfSSatish Balay       tao->trust = PetscMin(tao->trust, nlsP->max_radius);
1028*a7e14dcfSSatish Balay     }
1029*a7e14dcfSSatish Balay 
1030*a7e14dcfSSatish Balay     /*  Check for termination */
1031*a7e14dcfSSatish Balay     ierr = VecNorm(tao->gradient, NORM_2, &gnorm); CHKERRQ(ierr);
1032*a7e14dcfSSatish Balay     if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) {
1033*a7e14dcfSSatish Balay       SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number");
1034*a7e14dcfSSatish Balay     }
1035*a7e14dcfSSatish Balay     needH = 1;
1036*a7e14dcfSSatish Balay 
1037*a7e14dcfSSatish Balay     ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, step, &reason); CHKERRQ(ierr);
1038*a7e14dcfSSatish Balay   }
1039*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1040*a7e14dcfSSatish Balay }
1041*a7e14dcfSSatish Balay 
1042*a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
1043*a7e14dcfSSatish Balay #undef __FUNCT__
1044*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetUp_NLS"
1045*a7e14dcfSSatish Balay static PetscErrorCode TaoSetUp_NLS(TaoSolver tao)
1046*a7e14dcfSSatish Balay {
1047*a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
1048*a7e14dcfSSatish Balay   PetscErrorCode ierr;
1049*a7e14dcfSSatish Balay 
1050*a7e14dcfSSatish Balay   PetscFunctionBegin;
1051*a7e14dcfSSatish Balay 
1052*a7e14dcfSSatish Balay   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient); CHKERRQ(ierr);  }
1053*a7e14dcfSSatish Balay   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection); CHKERRQ(ierr);  }
1054*a7e14dcfSSatish Balay   if (!nlsP->W) {ierr = VecDuplicate(tao->solution,&nlsP->W); CHKERRQ(ierr);  }
1055*a7e14dcfSSatish Balay   if (!nlsP->D) {ierr = VecDuplicate(tao->solution,&nlsP->D); CHKERRQ(ierr);  }
1056*a7e14dcfSSatish Balay   if (!nlsP->Xold) {ierr = VecDuplicate(tao->solution,&nlsP->Xold); CHKERRQ(ierr);  }
1057*a7e14dcfSSatish Balay   if (!nlsP->Gold) {ierr = VecDuplicate(tao->solution,&nlsP->Gold); CHKERRQ(ierr);  }
1058*a7e14dcfSSatish Balay 
1059*a7e14dcfSSatish Balay   nlsP->Diag = 0;
1060*a7e14dcfSSatish Balay   nlsP->M = 0;
1061*a7e14dcfSSatish Balay 
1062*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1063*a7e14dcfSSatish Balay }
1064*a7e14dcfSSatish Balay 
1065*a7e14dcfSSatish Balay /*------------------------------------------------------------*/
1066*a7e14dcfSSatish Balay #undef __FUNCT__
1067*a7e14dcfSSatish Balay #define __FUNCT__ "TaoDestroy_NLS"
1068*a7e14dcfSSatish Balay static PetscErrorCode TaoDestroy_NLS(TaoSolver tao)
1069*a7e14dcfSSatish Balay {
1070*a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
1071*a7e14dcfSSatish Balay   PetscErrorCode ierr;
1072*a7e14dcfSSatish Balay 
1073*a7e14dcfSSatish Balay   PetscFunctionBegin;
1074*a7e14dcfSSatish Balay   if (tao->setupcalled) {
1075*a7e14dcfSSatish Balay     ierr = VecDestroy(&nlsP->D); CHKERRQ(ierr);
1076*a7e14dcfSSatish Balay     ierr = VecDestroy(&nlsP->W); CHKERRQ(ierr);
1077*a7e14dcfSSatish Balay     ierr = VecDestroy(&nlsP->Xold); CHKERRQ(ierr);
1078*a7e14dcfSSatish Balay     ierr = VecDestroy(&nlsP->Gold); CHKERRQ(ierr);
1079*a7e14dcfSSatish Balay   }
1080*a7e14dcfSSatish Balay   if (nlsP->Diag) {
1081*a7e14dcfSSatish Balay     ierr = VecDestroy(&nlsP->Diag); CHKERRQ(ierr);
1082*a7e14dcfSSatish Balay   }
1083*a7e14dcfSSatish Balay   if (nlsP->M) {
1084*a7e14dcfSSatish Balay     ierr = MatDestroy(&nlsP->M); CHKERRQ(ierr);
1085*a7e14dcfSSatish Balay   }
1086*a7e14dcfSSatish Balay 
1087*a7e14dcfSSatish Balay   ierr = PetscFree(tao->data); CHKERRQ(ierr);
1088*a7e14dcfSSatish Balay   tao->data = PETSC_NULL;
1089*a7e14dcfSSatish Balay 
1090*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1091*a7e14dcfSSatish Balay }
1092*a7e14dcfSSatish Balay 
1093*a7e14dcfSSatish Balay /*------------------------------------------------------------*/
1094*a7e14dcfSSatish Balay #undef __FUNCT__
1095*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetFromOptions_NLS"
1096*a7e14dcfSSatish Balay static PetscErrorCode TaoSetFromOptions_NLS(TaoSolver tao)
1097*a7e14dcfSSatish Balay {
1098*a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
1099*a7e14dcfSSatish Balay   PetscErrorCode ierr;
1100*a7e14dcfSSatish Balay 
1101*a7e14dcfSSatish Balay   PetscFunctionBegin;
1102*a7e14dcfSSatish Balay   ierr = PetscOptionsHead("Newton line search method for unconstrained optimization"); CHKERRQ(ierr);
1103*a7e14dcfSSatish Balay   ierr = PetscOptionsEList("-tao_nls_ksp_type", "ksp type", "", NLS_KSP, NLS_KSP_TYPES, NLS_KSP[nlsP->ksp_type], &nlsP->ksp_type, 0); CHKERRQ(ierr);
1104*a7e14dcfSSatish Balay   ierr = PetscOptionsEList("-tao_nls_pc_type", "pc type", "", NLS_PC, NLS_PC_TYPES, NLS_PC[nlsP->pc_type], &nlsP->pc_type, 0); CHKERRQ(ierr);
1105*a7e14dcfSSatish Balay   ierr = PetscOptionsEList("-tao_nls_bfgs_scale_type", "bfgs scale type", "", BFGS_SCALE, BFGS_SCALE_TYPES, BFGS_SCALE[nlsP->bfgs_scale_type], &nlsP->bfgs_scale_type, 0); CHKERRQ(ierr);
1106*a7e14dcfSSatish Balay   ierr = PetscOptionsEList("-tao_nls_init_type", "radius initialization type", "", NLS_INIT, NLS_INIT_TYPES, NLS_INIT[nlsP->init_type], &nlsP->init_type, 0); CHKERRQ(ierr);
1107*a7e14dcfSSatish Balay   ierr = PetscOptionsEList("-tao_nls_update_type", "radius update type", "", NLS_UPDATE, NLS_UPDATE_TYPES, NLS_UPDATE[nlsP->update_type], &nlsP->update_type, 0); CHKERRQ(ierr);
1108*a7e14dcfSSatish Balay  ierr = PetscOptionsReal("-tao_nls_sval", "perturbation starting value", "", nlsP->sval, &nlsP->sval, 0); CHKERRQ(ierr);
1109*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_imin", "minimum initial perturbation", "", nlsP->imin, &nlsP->imin, 0); CHKERRQ(ierr);
1110*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_imax", "maximum initial perturbation", "", nlsP->imax, &nlsP->imax, 0); CHKERRQ(ierr);
1111*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_imfac", "initial merit factor", "", nlsP->imfac, &nlsP->imfac, 0); CHKERRQ(ierr);
1112*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_pmin", "minimum perturbation", "", nlsP->pmin, &nlsP->pmin, 0); CHKERRQ(ierr);
1113*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_pmax", "maximum perturbation", "", nlsP->pmax, &nlsP->pmax, 0); CHKERRQ(ierr);
1114*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_pgfac", "growth factor", "", nlsP->pgfac, &nlsP->pgfac, 0); CHKERRQ(ierr);
1115*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_psfac", "shrink factor", "", nlsP->psfac, &nlsP->psfac, 0); CHKERRQ(ierr);
1116*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_pmgfac", "merit growth factor", "", nlsP->pmgfac, &nlsP->pmgfac, 0); CHKERRQ(ierr);
1117*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_pmsfac", "merit shrink factor", "", nlsP->pmsfac, &nlsP->pmsfac, 0); CHKERRQ(ierr);
1118*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_eta1", "poor steplength; reduce radius", "", nlsP->eta1, &nlsP->eta1, 0); CHKERRQ(ierr);
1119*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_eta2", "reasonable steplength; leave radius alone", "", nlsP->eta2, &nlsP->eta2, 0); CHKERRQ(ierr);
1120*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_eta3", "good steplength; increase radius", "", nlsP->eta3, &nlsP->eta3, 0); CHKERRQ(ierr);
1121*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_eta4", "excellent steplength; greatly increase radius", "", nlsP->eta4, &nlsP->eta4, 0); CHKERRQ(ierr);
1122*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_alpha1", "", "", nlsP->alpha1, &nlsP->alpha1, 0); CHKERRQ(ierr);
1123*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_alpha2", "", "", nlsP->alpha2, &nlsP->alpha2, 0); CHKERRQ(ierr);
1124*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_alpha3", "", "", nlsP->alpha3, &nlsP->alpha3, 0); CHKERRQ(ierr);
1125*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_alpha4", "", "", nlsP->alpha4, &nlsP->alpha4, 0); CHKERRQ(ierr);
1126*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_alpha5", "", "", nlsP->alpha5, &nlsP->alpha5, 0); CHKERRQ(ierr);
1127*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_nu1", "poor steplength; reduce radius", "", nlsP->nu1, &nlsP->nu1, 0); CHKERRQ(ierr);
1128*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_nu2", "reasonable steplength; leave radius alone", "", nlsP->nu2, &nlsP->nu2, 0); CHKERRQ(ierr);
1129*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_nu3", "good steplength; increase radius", "", nlsP->nu3, &nlsP->nu3, 0); CHKERRQ(ierr);
1130*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_nu4", "excellent steplength; greatly increase radius", "", nlsP->nu4, &nlsP->nu4, 0); CHKERRQ(ierr);
1131*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_omega1", "", "", nlsP->omega1, &nlsP->omega1, 0); CHKERRQ(ierr);
1132*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_omega2", "", "", nlsP->omega2, &nlsP->omega2, 0); CHKERRQ(ierr);
1133*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_omega3", "", "", nlsP->omega3, &nlsP->omega3, 0); CHKERRQ(ierr);
1134*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_omega4", "", "", nlsP->omega4, &nlsP->omega4, 0); CHKERRQ(ierr);
1135*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_omega5", "", "", nlsP->omega5, &nlsP->omega5, 0); CHKERRQ(ierr);
1136*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_mu1_i", "", "", nlsP->mu1_i, &nlsP->mu1_i, 0); CHKERRQ(ierr);
1137*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_mu2_i", "", "", nlsP->mu2_i, &nlsP->mu2_i, 0); CHKERRQ(ierr);
1138*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma1_i", "", "", nlsP->gamma1_i, &nlsP->gamma1_i, 0); CHKERRQ(ierr);
1139*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma2_i", "", "", nlsP->gamma2_i, &nlsP->gamma2_i, 0); CHKERRQ(ierr);
1140*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma3_i", "", "", nlsP->gamma3_i, &nlsP->gamma3_i, 0); CHKERRQ(ierr);
1141*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma4_i", "", "", nlsP->gamma4_i, &nlsP->gamma4_i, 0); CHKERRQ(ierr);
1142*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_theta_i", "", "", nlsP->theta_i, &nlsP->theta_i, 0); CHKERRQ(ierr);
1143*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_mu1", "", "", nlsP->mu1, &nlsP->mu1, 0); CHKERRQ(ierr);
1144*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_mu2", "", "", nlsP->mu2, &nlsP->mu2, 0); CHKERRQ(ierr);
1145*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma1", "", "", nlsP->gamma1, &nlsP->gamma1, 0); CHKERRQ(ierr);
1146*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma2", "", "", nlsP->gamma2, &nlsP->gamma2, 0); CHKERRQ(ierr);
1147*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma3", "", "", nlsP->gamma3, &nlsP->gamma3, 0); CHKERRQ(ierr);
1148*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_gamma4", "", "", nlsP->gamma4, &nlsP->gamma4, 0); CHKERRQ(ierr);
1149*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_theta", "", "", nlsP->theta, &nlsP->theta, 0); CHKERRQ(ierr);
1150*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_min_radius", "lower bound on initial radius", "", nlsP->min_radius, &nlsP->min_radius, 0); CHKERRQ(ierr);
1151*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_max_radius", "upper bound on radius", "", nlsP->max_radius, &nlsP->max_radius, 0); CHKERRQ(ierr);
1152*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_nls_epsilon", "tolerance used when computing actual and predicted reduction", "", nlsP->epsilon, &nlsP->epsilon, 0); CHKERRQ(ierr);
1153*a7e14dcfSSatish Balay   ierr = PetscOptionsTail(); CHKERRQ(ierr);
1154*a7e14dcfSSatish Balay   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1155*a7e14dcfSSatish Balay   ierr = KSPSetFromOptions(tao->ksp); CHKERRQ(ierr);
1156*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1157*a7e14dcfSSatish Balay }
1158*a7e14dcfSSatish Balay 
1159*a7e14dcfSSatish Balay 
1160*a7e14dcfSSatish Balay /*------------------------------------------------------------*/
1161*a7e14dcfSSatish Balay #undef __FUNCT__
1162*a7e14dcfSSatish Balay #define __FUNCT__ "TaoView_NLS"
1163*a7e14dcfSSatish Balay static PetscErrorCode TaoView_NLS(TaoSolver tao, PetscViewer viewer)
1164*a7e14dcfSSatish Balay {
1165*a7e14dcfSSatish Balay   TAO_NLS *nlsP = (TAO_NLS *)tao->data;
1166*a7e14dcfSSatish Balay   PetscInt nrejects;
1167*a7e14dcfSSatish Balay   PetscBool isascii;
1168*a7e14dcfSSatish Balay   PetscErrorCode ierr;
1169*a7e14dcfSSatish Balay 
1170*a7e14dcfSSatish Balay   PetscFunctionBegin;
1171*a7e14dcfSSatish Balay 
1172*a7e14dcfSSatish Balay   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1173*a7e14dcfSSatish Balay   if (isascii) {
1174*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPushTab(viewer); CHKERRQ(ierr);
1175*a7e14dcfSSatish Balay     if (NLS_PC_BFGS == nlsP->pc_type && nlsP->M) {
1176*a7e14dcfSSatish Balay       ierr = MatLMVMGetRejects(nlsP->M,&nrejects); CHKERRQ(ierr);
1177*a7e14dcfSSatish Balay       ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects); CHKERRQ(ierr);
1178*a7e14dcfSSatish Balay     }
1179*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", nlsP->newt); CHKERRQ(ierr);
1180*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", nlsP->bfgs); CHKERRQ(ierr);
1181*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", nlsP->sgrad); CHKERRQ(ierr);
1182*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", nlsP->grad); CHKERRQ(ierr);
1183*a7e14dcfSSatish Balay 
1184*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "nls ksp atol: %D\n", nlsP->ksp_atol); CHKERRQ(ierr);
1185*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "nls ksp rtol: %D\n", nlsP->ksp_rtol); CHKERRQ(ierr);
1186*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "nls ksp ctol: %D\n", nlsP->ksp_ctol); CHKERRQ(ierr);
1187*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "nls ksp negc: %D\n", nlsP->ksp_negc); CHKERRQ(ierr);
1188*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "nls ksp dtol: %D\n", nlsP->ksp_dtol); CHKERRQ(ierr);
1189*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "nls ksp iter: %D\n", nlsP->ksp_iter); CHKERRQ(ierr);
1190*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer, "nls ksp othr: %D\n", nlsP->ksp_othr); CHKERRQ(ierr);
1191*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPopTab(viewer); CHKERRQ(ierr);
1192*a7e14dcfSSatish Balay   } else {
1193*a7e14dcfSSatish Balay     SETERRQ1(((PetscObject)tao)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for TAO NLS",((PetscObject)viewer)->type_name);
1194*a7e14dcfSSatish Balay   }
1195*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1196*a7e14dcfSSatish Balay }
1197*a7e14dcfSSatish Balay 
1198*a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
1199*a7e14dcfSSatish Balay EXTERN_C_BEGIN
1200*a7e14dcfSSatish Balay #undef __FUNCT__
1201*a7e14dcfSSatish Balay #define __FUNCT__ "TaoCreate_NLS"
1202*a7e14dcfSSatish Balay PetscErrorCode TaoCreate_NLS(TaoSolver tao)
1203*a7e14dcfSSatish Balay {
1204*a7e14dcfSSatish Balay   TAO_NLS *nlsP;
1205*a7e14dcfSSatish Balay   const char *morethuente_type = TAOLINESEARCH_MT;
1206*a7e14dcfSSatish Balay   PetscErrorCode ierr;
1207*a7e14dcfSSatish Balay 
1208*a7e14dcfSSatish Balay   PetscFunctionBegin;
1209*a7e14dcfSSatish Balay   ierr = PetscNewLog(tao,TAO_NLS,&nlsP); CHKERRQ(ierr);
1210*a7e14dcfSSatish Balay 
1211*a7e14dcfSSatish Balay   tao->ops->setup = TaoSetUp_NLS;
1212*a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_NLS;
1213*a7e14dcfSSatish Balay   tao->ops->view = TaoView_NLS;
1214*a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_NLS;
1215*a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_NLS;
1216*a7e14dcfSSatish Balay 
1217*a7e14dcfSSatish Balay   tao->max_it = 50;
1218*a7e14dcfSSatish Balay   tao->fatol = 1e-10;
1219*a7e14dcfSSatish Balay   tao->frtol = 1e-10;
1220*a7e14dcfSSatish Balay   tao->data = (void*)nlsP;
1221*a7e14dcfSSatish Balay   tao->trust0 = 100.0;
1222*a7e14dcfSSatish Balay 
1223*a7e14dcfSSatish Balay   nlsP->sval   = 0.0;
1224*a7e14dcfSSatish Balay   nlsP->imin   = 1.0e-4;
1225*a7e14dcfSSatish Balay   nlsP->imax   = 1.0e+2;
1226*a7e14dcfSSatish Balay   nlsP->imfac  = 1.0e-1;
1227*a7e14dcfSSatish Balay 
1228*a7e14dcfSSatish Balay   nlsP->pmin   = 1.0e-12;
1229*a7e14dcfSSatish Balay   nlsP->pmax   = 1.0e+2;
1230*a7e14dcfSSatish Balay   nlsP->pgfac  = 1.0e+1;
1231*a7e14dcfSSatish Balay   nlsP->psfac  = 4.0e-1;
1232*a7e14dcfSSatish Balay   nlsP->pmgfac = 1.0e-1;
1233*a7e14dcfSSatish Balay   nlsP->pmsfac = 1.0e-1;
1234*a7e14dcfSSatish Balay 
1235*a7e14dcfSSatish Balay   /*  Default values for trust-region radius update based on steplength */
1236*a7e14dcfSSatish Balay   nlsP->nu1 = 0.25;
1237*a7e14dcfSSatish Balay   nlsP->nu2 = 0.50;
1238*a7e14dcfSSatish Balay   nlsP->nu3 = 1.00;
1239*a7e14dcfSSatish Balay   nlsP->nu4 = 1.25;
1240*a7e14dcfSSatish Balay 
1241*a7e14dcfSSatish Balay   nlsP->omega1 = 0.25;
1242*a7e14dcfSSatish Balay   nlsP->omega2 = 0.50;
1243*a7e14dcfSSatish Balay   nlsP->omega3 = 1.00;
1244*a7e14dcfSSatish Balay   nlsP->omega4 = 2.00;
1245*a7e14dcfSSatish Balay   nlsP->omega5 = 4.00;
1246*a7e14dcfSSatish Balay 
1247*a7e14dcfSSatish Balay   /*  Default values for trust-region radius update based on reduction */
1248*a7e14dcfSSatish Balay   nlsP->eta1 = 1.0e-4;
1249*a7e14dcfSSatish Balay   nlsP->eta2 = 0.25;
1250*a7e14dcfSSatish Balay   nlsP->eta3 = 0.50;
1251*a7e14dcfSSatish Balay   nlsP->eta4 = 0.90;
1252*a7e14dcfSSatish Balay 
1253*a7e14dcfSSatish Balay   nlsP->alpha1 = 0.25;
1254*a7e14dcfSSatish Balay   nlsP->alpha2 = 0.50;
1255*a7e14dcfSSatish Balay   nlsP->alpha3 = 1.00;
1256*a7e14dcfSSatish Balay   nlsP->alpha4 = 2.00;
1257*a7e14dcfSSatish Balay   nlsP->alpha5 = 4.00;
1258*a7e14dcfSSatish Balay 
1259*a7e14dcfSSatish Balay   /*  Default values for trust-region radius update based on interpolation */
1260*a7e14dcfSSatish Balay   nlsP->mu1 = 0.10;
1261*a7e14dcfSSatish Balay   nlsP->mu2 = 0.50;
1262*a7e14dcfSSatish Balay 
1263*a7e14dcfSSatish Balay   nlsP->gamma1 = 0.25;
1264*a7e14dcfSSatish Balay   nlsP->gamma2 = 0.50;
1265*a7e14dcfSSatish Balay   nlsP->gamma3 = 2.00;
1266*a7e14dcfSSatish Balay   nlsP->gamma4 = 4.00;
1267*a7e14dcfSSatish Balay 
1268*a7e14dcfSSatish Balay   nlsP->theta = 0.05;
1269*a7e14dcfSSatish Balay 
1270*a7e14dcfSSatish Balay   /*  Default values for trust region initialization based on interpolation */
1271*a7e14dcfSSatish Balay   nlsP->mu1_i = 0.35;
1272*a7e14dcfSSatish Balay   nlsP->mu2_i = 0.50;
1273*a7e14dcfSSatish Balay 
1274*a7e14dcfSSatish Balay   nlsP->gamma1_i = 0.0625;
1275*a7e14dcfSSatish Balay   nlsP->gamma2_i = 0.5;
1276*a7e14dcfSSatish Balay   nlsP->gamma3_i = 2.0;
1277*a7e14dcfSSatish Balay   nlsP->gamma4_i = 5.0;
1278*a7e14dcfSSatish Balay 
1279*a7e14dcfSSatish Balay   nlsP->theta_i = 0.25;
1280*a7e14dcfSSatish Balay 
1281*a7e14dcfSSatish Balay   /*  Remaining parameters */
1282*a7e14dcfSSatish Balay   nlsP->min_radius = 1.0e-10;
1283*a7e14dcfSSatish Balay   nlsP->max_radius = 1.0e10;
1284*a7e14dcfSSatish Balay   nlsP->epsilon = 1.0e-6;
1285*a7e14dcfSSatish Balay 
1286*a7e14dcfSSatish Balay   nlsP->ksp_type        = NLS_KSP_STCG;
1287*a7e14dcfSSatish Balay   nlsP->pc_type         = NLS_PC_BFGS;
1288*a7e14dcfSSatish Balay   nlsP->bfgs_scale_type = BFGS_SCALE_PHESS;
1289*a7e14dcfSSatish Balay   nlsP->init_type       = NLS_INIT_INTERPOLATION;
1290*a7e14dcfSSatish Balay   nlsP->update_type     = NLS_UPDATE_STEP;
1291*a7e14dcfSSatish Balay 
1292*a7e14dcfSSatish Balay   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch); CHKERRQ(ierr);
1293*a7e14dcfSSatish Balay   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type); CHKERRQ(ierr);
1294*a7e14dcfSSatish Balay   ierr = TaoLineSearchUseTaoSolverRoutines(tao->linesearch,tao); CHKERRQ(ierr);
1295*a7e14dcfSSatish Balay 
1296*a7e14dcfSSatish Balay   /*  Set linear solver to default for symmetric matrices */
1297*a7e14dcfSSatish Balay   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp); CHKERRQ(ierr);
1298*a7e14dcfSSatish Balay 
1299*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1300*a7e14dcfSSatish Balay }
1301*a7e14dcfSSatish Balay 
1302*a7e14dcfSSatish Balay EXTERN_C_END
1303*a7e14dcfSSatish Balay 
1304*a7e14dcfSSatish Balay 
1305*a7e14dcfSSatish Balay 
1306*a7e14dcfSSatish Balay 
1307*a7e14dcfSSatish Balay #undef __FUNCT__
1308*a7e14dcfSSatish Balay #define __FUNCT__ "MatLMVMSolveShell"
1309*a7e14dcfSSatish Balay static PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x)
1310*a7e14dcfSSatish Balay {
1311*a7e14dcfSSatish Balay     PetscErrorCode ierr;
1312*a7e14dcfSSatish Balay     Mat M;
1313*a7e14dcfSSatish Balay     PetscFunctionBegin;
1314*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1315*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(b,VEC_CLASSID,2);
1316*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(x,VEC_CLASSID,3);
1317*a7e14dcfSSatish Balay     ierr = PCShellGetContext(pc,(void**)&M); CHKERRQ(ierr);
1318*a7e14dcfSSatish Balay     ierr = MatLMVMSolve(M, b, x); CHKERRQ(ierr);
1319*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
1320*a7e14dcfSSatish Balay }
1321