xref: /petsc/src/tao/linesearch/impls/morethuente/morethuente.c (revision a7e14dcfba0d07adf6226a919460249440ec94c7)
1*a7e14dcfSSatish Balay #include "petscvec.h"
2*a7e14dcfSSatish Balay #include "taosolver.h"
3*a7e14dcfSSatish Balay #include "tao-private/taolinesearch_impl.h"
4*a7e14dcfSSatish Balay #include "morethuente.h"
5*a7e14dcfSSatish Balay 
6*a7e14dcfSSatish Balay /*
7*a7e14dcfSSatish Balay    This algorithm is taken from More' and Thuente, "Line search algorithms
8*a7e14dcfSSatish Balay    with guaranteed sufficient decrease", Argonne National Laboratory,
9*a7e14dcfSSatish Balay    Technical Report MCS-P330-1092.
10*a7e14dcfSSatish Balay */
11*a7e14dcfSSatish Balay 
12*a7e14dcfSSatish Balay static PetscErrorCode Tao_mcstep(TaoLineSearch ls,
13*a7e14dcfSSatish Balay 				 PetscReal *stx, PetscReal *fx, PetscReal *dx,
14*a7e14dcfSSatish Balay 				 PetscReal *sty, PetscReal *fy, PetscReal *dy,
15*a7e14dcfSSatish Balay 				 PetscReal *stp, PetscReal *fp, PetscReal *dp);
16*a7e14dcfSSatish Balay 
17*a7e14dcfSSatish Balay #undef __FUNCT__
18*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchDestroy_MT"
19*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchDestroy_MT(TaoLineSearch ls)
20*a7e14dcfSSatish Balay {
21*a7e14dcfSSatish Balay   PetscErrorCode ierr;
22*a7e14dcfSSatish Balay   TAOLINESEARCH_MT_CTX *mt;
23*a7e14dcfSSatish Balay   PetscFunctionBegin;
24*a7e14dcfSSatish Balay   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
25*a7e14dcfSSatish Balay   mt = (TAOLINESEARCH_MT_CTX*)(ls->data);
26*a7e14dcfSSatish Balay   if (mt->x) {
27*a7e14dcfSSatish Balay     ierr = PetscObjectDereference((PetscObject)mt->x); CHKERRQ(ierr);
28*a7e14dcfSSatish Balay   }
29*a7e14dcfSSatish Balay   if (mt->work) {
30*a7e14dcfSSatish Balay     ierr = VecDestroy(&mt->work); CHKERRQ(ierr);
31*a7e14dcfSSatish Balay   }
32*a7e14dcfSSatish Balay   ierr = PetscFree(ls->data);
33*a7e14dcfSSatish Balay   ls->data = PETSC_NULL;
34*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
35*a7e14dcfSSatish Balay }
36*a7e14dcfSSatish Balay 
37*a7e14dcfSSatish Balay #undef __FUNCT__
38*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchSetFromOptions_MT"
39*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchSetFromOptions_MT(TaoLineSearch ls)
40*a7e14dcfSSatish Balay {
41*a7e14dcfSSatish Balay   PetscFunctionBegin;
42*a7e14dcfSSatish Balay 
43*a7e14dcfSSatish Balay   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
44*a7e14dcfSSatish Balay 
45*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
46*a7e14dcfSSatish Balay }
47*a7e14dcfSSatish Balay 
48*a7e14dcfSSatish Balay 
49*a7e14dcfSSatish Balay #undef __FUNCT__
50*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchView_MT"
51*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchView_MT(TaoLineSearch ls, PetscViewer pv)
52*a7e14dcfSSatish Balay {
53*a7e14dcfSSatish Balay     PetscErrorCode ierr;
54*a7e14dcfSSatish Balay     PetscBool isascii;
55*a7e14dcfSSatish Balay     PetscFunctionBegin;
56*a7e14dcfSSatish Balay     ierr = PetscObjectTypeCompare((PetscObject)pv, PETSCVIEWERASCII, &isascii); CHKERRQ(ierr);
57*a7e14dcfSSatish Balay     if (isascii) {
58*a7e14dcfSSatish Balay 	ierr = PetscViewerASCIIPrintf(pv,"  maxf=%D, ftol=%G, gtol=%G\n",ls->max_funcs, ls->rtol, ls->ftol); CHKERRQ(ierr);
59*a7e14dcfSSatish Balay     } else {
60*a7e14dcfSSatish Balay       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for MoreThuente TaoLineSearch",((PetscObject)pv)->type_name);
61*a7e14dcfSSatish Balay     }
62*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
63*a7e14dcfSSatish Balay }
64*a7e14dcfSSatish Balay 
65*a7e14dcfSSatish Balay #undef __FUNCT__
66*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchApply_MT"
67*a7e14dcfSSatish Balay /* @ TaoApply_LineSearch - This routine takes step length of 1.0.
68*a7e14dcfSSatish Balay 
69*a7e14dcfSSatish Balay    Input Parameters:
70*a7e14dcfSSatish Balay +  tao - TaoSolver context
71*a7e14dcfSSatish Balay .  X - current iterate (on output X contains new iterate, X + step*S)
72*a7e14dcfSSatish Balay .  f - objective function evaluated at X
73*a7e14dcfSSatish Balay .  G - gradient evaluated at X
74*a7e14dcfSSatish Balay -  D - search direction
75*a7e14dcfSSatish Balay 
76*a7e14dcfSSatish Balay 
77*a7e14dcfSSatish Balay    Info is set to 0.
78*a7e14dcfSSatish Balay 
79*a7e14dcfSSatish Balay @ */
80*a7e14dcfSSatish Balay 
81*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchApply_MT(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s)
82*a7e14dcfSSatish Balay {
83*a7e14dcfSSatish Balay     PetscErrorCode ierr;
84*a7e14dcfSSatish Balay     TAOLINESEARCH_MT_CTX *mt;
85*a7e14dcfSSatish Balay 
86*a7e14dcfSSatish Balay     PetscReal    xtrapf = 4.0;
87*a7e14dcfSSatish Balay     PetscReal   finit, width, width1, dginit, fm, fxm, fym, dgm, dgxm, dgym;
88*a7e14dcfSSatish Balay     PetscReal    dgx, dgy, dg, dg2, fx, fy, stx, sty, dgtest;
89*a7e14dcfSSatish Balay     PetscReal ftest1=0.0, ftest2=0.0;
90*a7e14dcfSSatish Balay     PetscInt  i, stage1,n1,n2,nn1,nn2;
91*a7e14dcfSSatish Balay     PetscReal bstepmin1, bstepmin2, bstepmax;
92*a7e14dcfSSatish Balay     PetscBool g_computed=PETSC_FALSE;; /* to prevent extra gradient computation */
93*a7e14dcfSSatish Balay 
94*a7e14dcfSSatish Balay     PetscFunctionBegin;
95*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
96*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(x,VEC_CLASSID,2);
97*a7e14dcfSSatish Balay     PetscValidScalarPointer(f,3);
98*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(g,VEC_CLASSID,4);
99*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(s,VEC_CLASSID,5);
100*a7e14dcfSSatish Balay 
101*a7e14dcfSSatish Balay     /* comm,type,size checks are done in interface TaoLineSearchApply */
102*a7e14dcfSSatish Balay     mt = (TAOLINESEARCH_MT_CTX*)(ls->data);
103*a7e14dcfSSatish Balay 
104*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_CONTINUE_ITERATING;
105*a7e14dcfSSatish Balay 
106*a7e14dcfSSatish Balay     /* Check work vector */
107*a7e14dcfSSatish Balay     if (!mt->work) {
108*a7e14dcfSSatish Balay       ierr = VecDuplicate(x,&mt->work); CHKERRQ(ierr);
109*a7e14dcfSSatish Balay       mt->x = x;
110*a7e14dcfSSatish Balay       ierr = PetscObjectReference((PetscObject)mt->x); CHKERRQ(ierr);
111*a7e14dcfSSatish Balay     }
112*a7e14dcfSSatish Balay     /* If x has changed, then recreate work */
113*a7e14dcfSSatish Balay     else if (x != mt->x) {
114*a7e14dcfSSatish Balay       ierr = VecDestroy(&mt->work); CHKERRQ(ierr);
115*a7e14dcfSSatish Balay       ierr = VecDuplicate(x,&mt->work); CHKERRQ(ierr);
116*a7e14dcfSSatish Balay       ierr = PetscObjectDereference((PetscObject)mt->x); CHKERRQ(ierr);
117*a7e14dcfSSatish Balay       mt->x = x;
118*a7e14dcfSSatish Balay       ierr = PetscObjectReference((PetscObject)mt->x); CHKERRQ(ierr);
119*a7e14dcfSSatish Balay     }
120*a7e14dcfSSatish Balay 
121*a7e14dcfSSatish Balay 
122*a7e14dcfSSatish Balay     if (ls->bounded) {
123*a7e14dcfSSatish Balay 	/* Compute step length needed to make all variables equal a bound */
124*a7e14dcfSSatish Balay 	/* Compute the smallest steplength that will make one nonbinding variable
125*a7e14dcfSSatish Balay 	   equal the bound */
126*a7e14dcfSSatish Balay 	ierr = VecGetLocalSize(ls->upper,&n1); CHKERRQ(ierr);
127*a7e14dcfSSatish Balay 	ierr = VecGetLocalSize(mt->x, &n2); CHKERRQ(ierr);
128*a7e14dcfSSatish Balay 	ierr = VecGetSize(ls->upper,&nn1); CHKERRQ(ierr);
129*a7e14dcfSSatish Balay 	ierr = VecGetSize(mt->x,&nn2); CHKERRQ(ierr);
130*a7e14dcfSSatish Balay 	if (n1 != n2 || nn1 != nn2) {
131*a7e14dcfSSatish Balay 	    SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Variable vector not compatible with bounds vector");
132*a7e14dcfSSatish Balay 	}
133*a7e14dcfSSatish Balay 	ierr = VecScale(s,-1.0); CHKERRQ(ierr);
134*a7e14dcfSSatish Balay 	ierr = VecBoundGradientProjection(s,x,ls->lower,ls->upper,s); CHKERRQ(ierr);
135*a7e14dcfSSatish Balay 	ierr = VecScale(s,-1.0); CHKERRQ(ierr);
136*a7e14dcfSSatish Balay 	ierr = VecStepBoundInfo(x,ls->lower,ls->upper,s,&bstepmin1,&bstepmin2,&bstepmax);
137*a7e14dcfSSatish Balay 	CHKERRQ(ierr);
138*a7e14dcfSSatish Balay 	ls->stepmax = PetscMin(bstepmax,1.0e15);
139*a7e14dcfSSatish Balay     }
140*a7e14dcfSSatish Balay 
141*a7e14dcfSSatish Balay     ierr = VecDot(g,s,&dginit);
142*a7e14dcfSSatish Balay 
143*a7e14dcfSSatish Balay     if (PetscIsInfOrNanReal(dginit)) {
144*a7e14dcfSSatish Balay       ierr = PetscInfo1(ls,"Initial Line Search step * g is Inf or Nan (%G)\n",dginit); CHKERRQ(ierr);
145*a7e14dcfSSatish Balay       ls->reason=TAOLINESEARCH_FAILED_INFORNAN;
146*a7e14dcfSSatish Balay       PetscFunctionReturn(0);
147*a7e14dcfSSatish Balay     }
148*a7e14dcfSSatish Balay     if (dginit >= 0.0) {
149*a7e14dcfSSatish Balay       ierr = PetscInfo1(ls,"Initial Line Search step * g is not descent direction (%G)\n",dginit); CHKERRQ(ierr);
150*a7e14dcfSSatish Balay       ls->reason = TAOLINESEARCH_FAILED_ASCENT;
151*a7e14dcfSSatish Balay       PetscFunctionReturn(0);
152*a7e14dcfSSatish Balay     }
153*a7e14dcfSSatish Balay 
154*a7e14dcfSSatish Balay 
155*a7e14dcfSSatish Balay     /* Initialization */
156*a7e14dcfSSatish Balay     mt->bracket = 0;
157*a7e14dcfSSatish Balay     stage1 = 1;
158*a7e14dcfSSatish Balay     finit = *f;
159*a7e14dcfSSatish Balay     dgtest = ls->ftol * dginit;
160*a7e14dcfSSatish Balay     width = ls->stepmax - ls->stepmin;
161*a7e14dcfSSatish Balay     width1 = width * 2.0;
162*a7e14dcfSSatish Balay     ierr = VecCopy(x,mt->work);CHKERRQ(ierr);
163*a7e14dcfSSatish Balay     /* Variable dictionary:
164*a7e14dcfSSatish Balay      stx, fx, dgx - the step, function, and derivative at the best step
165*a7e14dcfSSatish Balay      sty, fy, dgy - the step, function, and derivative at the other endpoint
166*a7e14dcfSSatish Balay                    of the interval of uncertainty
167*a7e14dcfSSatish Balay      step, f, dg - the step, function, and derivative at the current step */
168*a7e14dcfSSatish Balay 
169*a7e14dcfSSatish Balay     stx = 0.0;
170*a7e14dcfSSatish Balay     fx  = finit;
171*a7e14dcfSSatish Balay     dgx = dginit;
172*a7e14dcfSSatish Balay     sty = 0.0;
173*a7e14dcfSSatish Balay     fy  = finit;
174*a7e14dcfSSatish Balay     dgy = dginit;
175*a7e14dcfSSatish Balay 
176*a7e14dcfSSatish Balay     ls->step=ls->initstep;
177*a7e14dcfSSatish Balay     for (i=0; i< ls->max_funcs; i++) {
178*a7e14dcfSSatish Balay     /* Set min and max steps to correspond to the interval of uncertainty */
179*a7e14dcfSSatish Balay       if (mt->bracket) {
180*a7e14dcfSSatish Balay 	ls->stepmin = PetscMin(stx,sty);
181*a7e14dcfSSatish Balay 	ls->stepmax = PetscMax(stx,sty);
182*a7e14dcfSSatish Balay       }
183*a7e14dcfSSatish Balay       else {
184*a7e14dcfSSatish Balay 	ls->stepmin = stx;
185*a7e14dcfSSatish Balay 	ls->stepmax = ls->step + xtrapf * (ls->step - stx);
186*a7e14dcfSSatish Balay       }
187*a7e14dcfSSatish Balay 
188*a7e14dcfSSatish Balay       /* Force the step to be within the bounds */
189*a7e14dcfSSatish Balay       ls->step = PetscMax(ls->step,ls->stepmin);
190*a7e14dcfSSatish Balay       ls->step = PetscMin(ls->step,ls->stepmax);
191*a7e14dcfSSatish Balay 
192*a7e14dcfSSatish Balay       /* If an unusual termination is to occur, then let step be the lowest
193*a7e14dcfSSatish Balay 	 point obtained thus far */
194*a7e14dcfSSatish Balay       if ((stx!=0) && (((mt->bracket) && (ls->step <= ls->stepmin || ls->step >= ls->stepmax)) ||
195*a7e14dcfSSatish Balay         ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol * ls->stepmax)) ||
196*a7e14dcfSSatish Balay 		       ((ls->nfeval+ls->nfgeval) >= ls->max_funcs - 1) || (mt->infoc == 0))) {
197*a7e14dcfSSatish Balay 	ls->step = stx;
198*a7e14dcfSSatish Balay       }
199*a7e14dcfSSatish Balay 
200*a7e14dcfSSatish Balay       ierr = VecCopy(x,mt->work); CHKERRQ(ierr);
201*a7e14dcfSSatish Balay       ierr = VecAXPY(mt->work,ls->step,s); CHKERRQ(ierr);   /* W = X + step*S */
202*a7e14dcfSSatish Balay 
203*a7e14dcfSSatish Balay       if (ls->bounded) {
204*a7e14dcfSSatish Balay 	  ierr = VecMedian(ls->lower, mt->work, ls->upper, mt->work);CHKERRQ(ierr);
205*a7e14dcfSSatish Balay       }
206*a7e14dcfSSatish Balay       if (ls->usegts) {
207*a7e14dcfSSatish Balay 	ierr = TaoLineSearchComputeObjectiveAndGTS(ls,mt->work,f,&dg); CHKERRQ(ierr);
208*a7e14dcfSSatish Balay 	g_computed=PETSC_FALSE;
209*a7e14dcfSSatish Balay       } else {
210*a7e14dcfSSatish Balay 	ierr = TaoLineSearchComputeObjectiveAndGradient(ls,mt->work,f,g); CHKERRQ(ierr);
211*a7e14dcfSSatish Balay 	g_computed=PETSC_TRUE;
212*a7e14dcfSSatish Balay 	if (ls->bounded) {
213*a7e14dcfSSatish Balay 	  ierr = VecDot(g,x,&dg); CHKERRQ(ierr);
214*a7e14dcfSSatish Balay 	  ierr = VecDot(g,mt->work,&dg2); CHKERRQ(ierr);
215*a7e14dcfSSatish Balay 	  dg = (dg2 - dg)/ls->step;
216*a7e14dcfSSatish Balay 	} else {
217*a7e14dcfSSatish Balay 	  ierr = VecDot(g,s,&dg); CHKERRQ(ierr);
218*a7e14dcfSSatish Balay 	}
219*a7e14dcfSSatish Balay       }
220*a7e14dcfSSatish Balay 
221*a7e14dcfSSatish Balay       if (0 == i) {
222*a7e14dcfSSatish Balay 	ls->f_fullstep=*f;
223*a7e14dcfSSatish Balay       }
224*a7e14dcfSSatish Balay 
225*a7e14dcfSSatish Balay 
226*a7e14dcfSSatish Balay 
227*a7e14dcfSSatish Balay       if (PetscIsInfOrNanReal(*f) || PetscIsInfOrNanReal(dg)) {
228*a7e14dcfSSatish Balay 	/* User provided compute function generated Not-a-Number, assume
229*a7e14dcfSSatish Balay 	 domain violation and set function value and directional
230*a7e14dcfSSatish Balay 	 derivative to infinity. */
231*a7e14dcfSSatish Balay 	*f = TAO_INFINITY;
232*a7e14dcfSSatish Balay 	dg = TAO_INFINITY;
233*a7e14dcfSSatish Balay       }
234*a7e14dcfSSatish Balay 
235*a7e14dcfSSatish Balay       ftest1 = finit + ls->step * dgtest;
236*a7e14dcfSSatish Balay       if (ls->bounded) {
237*a7e14dcfSSatish Balay 	  ftest2 = finit + ls->step * dgtest * ls->ftol;
238*a7e14dcfSSatish Balay       }
239*a7e14dcfSSatish Balay       /* Convergence testing */
240*a7e14dcfSSatish Balay       if (((*f - ftest1 <= 1.0e-10 * PetscAbsReal(finit)) &&
241*a7e14dcfSSatish Balay 	   (PetscAbsReal(dg) + ls->gtol*dginit <= 0.0))) {
242*a7e14dcfSSatish Balay 	ierr = PetscInfo(ls, "Line search success: Sufficient decrease and directional deriv conditions hold\n"); CHKERRQ(ierr);
243*a7e14dcfSSatish Balay 	ls->reason = TAOLINESEARCH_SUCCESS;
244*a7e14dcfSSatish Balay 	break;
245*a7e14dcfSSatish Balay       }
246*a7e14dcfSSatish Balay 
247*a7e14dcfSSatish Balay       /* Check Armijo if beyond the first breakpoint */
248*a7e14dcfSSatish Balay       if (ls->bounded && (*f <= ftest2) && (ls->step >= bstepmin2)) {
249*a7e14dcfSSatish Balay 	  ierr = PetscInfo(ls,"Line search success: Sufficient decrease.\n"); CHKERRQ(ierr);
250*a7e14dcfSSatish Balay 	  break;
251*a7e14dcfSSatish Balay       }
252*a7e14dcfSSatish Balay 
253*a7e14dcfSSatish Balay       /* Checks for bad cases */
254*a7e14dcfSSatish Balay       if (((mt->bracket) && (ls->step <= ls->stepmin||ls->step >= ls->stepmax)) || (!mt->infoc)) {
255*a7e14dcfSSatish Balay 	ierr = PetscInfo(ls,"Rounding errors may prevent further progress.  May not be a step satisfying\n"); CHKERRQ(ierr);
256*a7e14dcfSSatish Balay 	ierr = PetscInfo(ls,"sufficient decrease and curvature conditions. Tolerances may be too small.\n"); CHKERRQ(ierr);
257*a7e14dcfSSatish Balay 	ls->reason = TAOLINESEARCH_HALTED_OTHER;
258*a7e14dcfSSatish Balay 	break;
259*a7e14dcfSSatish Balay       }
260*a7e14dcfSSatish Balay       if ((ls->step == ls->stepmax) && (*f <= ftest1) && (dg <= dgtest)) {
261*a7e14dcfSSatish Balay 	ierr = PetscInfo1(ls,"Step is at the upper bound, stepmax (%G)\n",ls->stepmax); CHKERRQ(ierr);
262*a7e14dcfSSatish Balay 	ls->reason = TAOLINESEARCH_HALTED_UPPERBOUND;
263*a7e14dcfSSatish Balay 	break;
264*a7e14dcfSSatish Balay       }
265*a7e14dcfSSatish Balay       if ((ls->step == ls->stepmin) && (*f >= ftest1) && (dg >= dgtest)) {
266*a7e14dcfSSatish Balay 	ierr = PetscInfo1(ls,"Step is at the lower bound, stepmin (%G)\n",ls->stepmin); CHKERRQ(ierr);
267*a7e14dcfSSatish Balay 	ls->reason = TAOLINESEARCH_HALTED_LOWERBOUND;
268*a7e14dcfSSatish Balay 	break;
269*a7e14dcfSSatish Balay       }
270*a7e14dcfSSatish Balay       if ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol*ls->stepmax)){
271*a7e14dcfSSatish Balay 	ierr = PetscInfo1(ls,"Relative width of interval of uncertainty is at most rtol (%G)\n",ls->rtol); CHKERRQ(ierr);
272*a7e14dcfSSatish Balay 	ls->reason = TAOLINESEARCH_HALTED_RTOL;
273*a7e14dcfSSatish Balay 	break;
274*a7e14dcfSSatish Balay       }
275*a7e14dcfSSatish Balay 
276*a7e14dcfSSatish Balay       /* In the first stage, we seek a step for which the modified function
277*a7e14dcfSSatish Balay 	 has a nonpositive value and nonnegative derivative */
278*a7e14dcfSSatish Balay       if ((stage1) && (*f <= ftest1) && (dg >= dginit * PetscMin(ls->ftol, ls->gtol))) {
279*a7e14dcfSSatish Balay 	stage1 = 0;
280*a7e14dcfSSatish Balay       }
281*a7e14dcfSSatish Balay 
282*a7e14dcfSSatish Balay       /* A modified function is used to predict the step only if we
283*a7e14dcfSSatish Balay 	 have not obtained a step for which the modified function has a
284*a7e14dcfSSatish Balay 	 nonpositive function value and nonnegative derivative, and if a
285*a7e14dcfSSatish Balay 	 lower function value has been obtained but the decrease is not
286*a7e14dcfSSatish Balay 	 sufficient */
287*a7e14dcfSSatish Balay 
288*a7e14dcfSSatish Balay       if ((stage1) && (*f <= fx) && (*f > ftest1)) {
289*a7e14dcfSSatish Balay 	fm   = *f - ls->step * dgtest;	/* Define modified function */
290*a7e14dcfSSatish Balay 	fxm  = fx - stx * dgtest;	        /* and derivatives */
291*a7e14dcfSSatish Balay 	fym  = fy - sty * dgtest;
292*a7e14dcfSSatish Balay 	dgm  = dg - dgtest;
293*a7e14dcfSSatish Balay 	dgxm = dgx - dgtest;
294*a7e14dcfSSatish Balay 	dgym = dgy - dgtest;
295*a7e14dcfSSatish Balay 
296*a7e14dcfSSatish Balay 	/* if (dgxm * (ls->step - stx) >= 0.0) */
297*a7e14dcfSSatish Balay 	/* Update the interval of uncertainty and compute the new step */
298*a7e14dcfSSatish Balay 	ierr = Tao_mcstep(ls,&stx,&fxm,&dgxm,&sty,&fym,&dgym,&ls->step,&fm,&dgm);CHKERRQ(ierr);
299*a7e14dcfSSatish Balay 
300*a7e14dcfSSatish Balay 	fx  = fxm + stx * dgtest;	/* Reset the function and */
301*a7e14dcfSSatish Balay 	fy  = fym + sty * dgtest;	/* gradient values */
302*a7e14dcfSSatish Balay 	dgx = dgxm + dgtest;
303*a7e14dcfSSatish Balay 	dgy = dgym + dgtest;
304*a7e14dcfSSatish Balay       }
305*a7e14dcfSSatish Balay       else {
306*a7e14dcfSSatish Balay 	/* Update the interval of uncertainty and compute the new step */
307*a7e14dcfSSatish Balay 	ierr = Tao_mcstep(ls,&stx,&fx,&dgx,&sty,&fy,&dgy,&ls->step,f,&dg);CHKERRQ(ierr);
308*a7e14dcfSSatish Balay       }
309*a7e14dcfSSatish Balay 
310*a7e14dcfSSatish Balay       /* Force a sufficient decrease in the interval of uncertainty */
311*a7e14dcfSSatish Balay       if (mt->bracket) {
312*a7e14dcfSSatish Balay 	if (PetscAbsReal(sty - stx) >= 0.66 * width1) ls->step = stx + 0.5*(sty - stx);
313*a7e14dcfSSatish Balay 	width1 = width;
314*a7e14dcfSSatish Balay 	width = PetscAbsReal(sty - stx);
315*a7e14dcfSSatish Balay       }
316*a7e14dcfSSatish Balay     }
317*a7e14dcfSSatish Balay     if ((ls->nfeval+ls->nfgeval) > ls->max_funcs) {
318*a7e14dcfSSatish Balay       ierr = PetscInfo2(ls,"Number of line search function evals (%D) > maximum (%D)\n",(ls->nfeval+ls->nfgeval),ls->max_funcs); CHKERRQ(ierr);
319*a7e14dcfSSatish Balay       ls->reason = TAOLINESEARCH_HALTED_MAXFCN;
320*a7e14dcfSSatish Balay     }
321*a7e14dcfSSatish Balay 
322*a7e14dcfSSatish Balay     /* Finish computations */
323*a7e14dcfSSatish Balay     ierr = PetscInfo2(ls,"%D function evals in line search, step = %G\n",(ls->nfeval+ls->nfgeval),ls->step); CHKERRQ(ierr);
324*a7e14dcfSSatish Balay 
325*a7e14dcfSSatish Balay     /* Set new solution vector and compute gradient if needed */
326*a7e14dcfSSatish Balay     ierr = VecCopy(mt->work,x); CHKERRQ(ierr);
327*a7e14dcfSSatish Balay     if (!g_computed) {
328*a7e14dcfSSatish Balay       ierr = TaoLineSearchComputeGradient(ls,mt->work,g); CHKERRQ(ierr);
329*a7e14dcfSSatish Balay     }
330*a7e14dcfSSatish Balay 
331*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
332*a7e14dcfSSatish Balay }
333*a7e14dcfSSatish Balay 
334*a7e14dcfSSatish Balay EXTERN_C_BEGIN
335*a7e14dcfSSatish Balay #undef __FUNCT__
336*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchCreate_MT"
337*a7e14dcfSSatish Balay PetscErrorCode TaoLineSearchCreate_MT(TaoLineSearch ls)
338*a7e14dcfSSatish Balay {
339*a7e14dcfSSatish Balay     PetscErrorCode ierr;
340*a7e14dcfSSatish Balay     TAOLINESEARCH_MT_CTX *ctx;
341*a7e14dcfSSatish Balay     PetscFunctionBegin;
342*a7e14dcfSSatish Balay     PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
343*a7e14dcfSSatish Balay     ierr = PetscNewLog(ls,TAOLINESEARCH_MT_CTX,&ctx); CHKERRQ(ierr);
344*a7e14dcfSSatish Balay     ctx->bracket=0;
345*a7e14dcfSSatish Balay     ctx->infoc=1;
346*a7e14dcfSSatish Balay     ls->data = (void*)ctx;
347*a7e14dcfSSatish Balay     ls->initstep = 1.0;
348*a7e14dcfSSatish Balay     ls->ops->setup=0;
349*a7e14dcfSSatish Balay     ls->ops->apply=TaoLineSearchApply_MT;
350*a7e14dcfSSatish Balay     ls->ops->view =TaoLineSearchView_MT;
351*a7e14dcfSSatish Balay     ls->ops->destroy=TaoLineSearchDestroy_MT;
352*a7e14dcfSSatish Balay     ls->ops->setfromoptions=TaoLineSearchSetFromOptions_MT;
353*a7e14dcfSSatish Balay 
354*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
355*a7e14dcfSSatish Balay }
356*a7e14dcfSSatish Balay EXTERN_C_END
357*a7e14dcfSSatish Balay 
358*a7e14dcfSSatish Balay 
359*a7e14dcfSSatish Balay 
360*a7e14dcfSSatish Balay /*
361*a7e14dcfSSatish Balay      The subroutine mcstep is taken from the work of Jorge Nocedal.
362*a7e14dcfSSatish Balay      this is a variant of More' and Thuente's routine.
363*a7e14dcfSSatish Balay 
364*a7e14dcfSSatish Balay      subroutine mcstep
365*a7e14dcfSSatish Balay 
366*a7e14dcfSSatish Balay      the purpose of mcstep is to compute a safeguarded step for
367*a7e14dcfSSatish Balay      a linesearch and to update an interval of uncertainty for
368*a7e14dcfSSatish Balay      a minimizer of the function.
369*a7e14dcfSSatish Balay 
370*a7e14dcfSSatish Balay      the parameter stx contains the step with the least function
371*a7e14dcfSSatish Balay      value. the parameter stp contains the current step. it is
372*a7e14dcfSSatish Balay      assumed that the derivative at stx is negative in the
373*a7e14dcfSSatish Balay      direction of the step. if bracket is set true then a
374*a7e14dcfSSatish Balay      minimizer has been bracketed in an interval of uncertainty
375*a7e14dcfSSatish Balay      with endpoints stx and sty.
376*a7e14dcfSSatish Balay 
377*a7e14dcfSSatish Balay      the subroutine statement is
378*a7e14dcfSSatish Balay 
379*a7e14dcfSSatish Balay      subroutine mcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,bracket,
380*a7e14dcfSSatish Balay                        stpmin,stpmax,info)
381*a7e14dcfSSatish Balay 
382*a7e14dcfSSatish Balay      where
383*a7e14dcfSSatish Balay 
384*a7e14dcfSSatish Balay        stx, fx, and dx are variables which specify the step,
385*a7e14dcfSSatish Balay          the function, and the derivative at the best step obtained
386*a7e14dcfSSatish Balay          so far. The derivative must be negative in the direction
387*a7e14dcfSSatish Balay          of the step, that is, dx and stp-stx must have opposite
388*a7e14dcfSSatish Balay          signs. On output these parameters are updated appropriately.
389*a7e14dcfSSatish Balay 
390*a7e14dcfSSatish Balay        sty, fy, and dy are variables which specify the step,
391*a7e14dcfSSatish Balay          the function, and the derivative at the other endpoint of
392*a7e14dcfSSatish Balay          the interval of uncertainty. On output these parameters are
393*a7e14dcfSSatish Balay          updated appropriately.
394*a7e14dcfSSatish Balay 
395*a7e14dcfSSatish Balay        stp, fp, and dp are variables which specify the step,
396*a7e14dcfSSatish Balay          the function, and the derivative at the current step.
397*a7e14dcfSSatish Balay          If bracket is set true then on input stp must be
398*a7e14dcfSSatish Balay          between stx and sty. On output stp is set to the new step.
399*a7e14dcfSSatish Balay 
400*a7e14dcfSSatish Balay        bracket is a logical variable which specifies if a minimizer
401*a7e14dcfSSatish Balay          has been bracketed.  If the minimizer has not been bracketed
402*a7e14dcfSSatish Balay          then on input bracket must be set false.  If the minimizer
403*a7e14dcfSSatish Balay          is bracketed then on output bracket is set true.
404*a7e14dcfSSatish Balay 
405*a7e14dcfSSatish Balay        stpmin and stpmax are input variables which specify lower
406*a7e14dcfSSatish Balay          and upper bounds for the step.
407*a7e14dcfSSatish Balay 
408*a7e14dcfSSatish Balay        info is an integer output variable set as follows:
409*a7e14dcfSSatish Balay          if info = 1,2,3,4,5, then the step has been computed
410*a7e14dcfSSatish Balay          according to one of the five cases below. otherwise
411*a7e14dcfSSatish Balay          info = 0, and this indicates improper input parameters.
412*a7e14dcfSSatish Balay 
413*a7e14dcfSSatish Balay      subprograms called
414*a7e14dcfSSatish Balay 
415*a7e14dcfSSatish Balay        fortran-supplied ... abs,max,min,sqrt
416*a7e14dcfSSatish Balay 
417*a7e14dcfSSatish Balay      argonne national laboratory. minpack project. june 1983
418*a7e14dcfSSatish Balay      jorge j. more', david j. thuente
419*a7e14dcfSSatish Balay 
420*a7e14dcfSSatish Balay */
421*a7e14dcfSSatish Balay 
422*a7e14dcfSSatish Balay #undef __FUNCT__
423*a7e14dcfSSatish Balay #define __FUNCT__ "Tao_mcstep"
424*a7e14dcfSSatish Balay static PetscErrorCode Tao_mcstep(TaoLineSearch ls,
425*a7e14dcfSSatish Balay                               PetscReal *stx, PetscReal *fx, PetscReal *dx,
426*a7e14dcfSSatish Balay 		              PetscReal *sty, PetscReal *fy, PetscReal *dy,
427*a7e14dcfSSatish Balay 			      PetscReal *stp, PetscReal *fp, PetscReal *dp)
428*a7e14dcfSSatish Balay {
429*a7e14dcfSSatish Balay   TAOLINESEARCH_MT_CTX *mtP = (TAOLINESEARCH_MT_CTX *) ls->data;
430*a7e14dcfSSatish Balay   PetscReal gamma1, p, q, r, s, sgnd, stpc, stpf, stpq, theta;
431*a7e14dcfSSatish Balay   PetscInt bound;
432*a7e14dcfSSatish Balay 
433*a7e14dcfSSatish Balay   PetscFunctionBegin;
434*a7e14dcfSSatish Balay 
435*a7e14dcfSSatish Balay   /* Check the input parameters for errors */
436*a7e14dcfSSatish Balay   mtP->infoc = 0;
437*a7e14dcfSSatish Balay   if (mtP->bracket && (*stp <= PetscMin(*stx,*sty) || (*stp >= PetscMax(*stx,*sty)))) SETERRQ(PETSC_COMM_SELF,1,"bad stp in bracket");
438*a7e14dcfSSatish Balay   if (*dx * (*stp-*stx) >= 0.0) SETERRQ(PETSC_COMM_SELF,1,"dx * (stp-stx) >= 0.0");
439*a7e14dcfSSatish Balay   if (ls->stepmax < ls->stepmin) SETERRQ(PETSC_COMM_SELF,1,"stepmax > stepmin");
440*a7e14dcfSSatish Balay 
441*a7e14dcfSSatish Balay   /* Determine if the derivatives have opposite sign */
442*a7e14dcfSSatish Balay   sgnd = *dp * (*dx / PetscAbsReal(*dx));
443*a7e14dcfSSatish Balay 
444*a7e14dcfSSatish Balay   if (*fp > *fx) {
445*a7e14dcfSSatish Balay     /* Case 1: a higher function value.
446*a7e14dcfSSatish Balay      The minimum is bracketed. If the cubic step is closer
447*a7e14dcfSSatish Balay      to stx than the quadratic step, the cubic step is taken,
448*a7e14dcfSSatish Balay      else the average of the cubic and quadratic steps is taken. */
449*a7e14dcfSSatish Balay 
450*a7e14dcfSSatish Balay     mtP->infoc = 1;
451*a7e14dcfSSatish Balay     bound = 1;
452*a7e14dcfSSatish Balay     theta = 3 * (*fx - *fp) / (*stp - *stx) + *dx + *dp;
453*a7e14dcfSSatish Balay     s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx));
454*a7e14dcfSSatish Balay     s = PetscMax(s,PetscAbsReal(*dp));
455*a7e14dcfSSatish Balay     gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s));
456*a7e14dcfSSatish Balay     if (*stp < *stx) gamma1 = -gamma1;
457*a7e14dcfSSatish Balay     /* Can p be 0?  Check */
458*a7e14dcfSSatish Balay     p = (gamma1 - *dx) + theta;
459*a7e14dcfSSatish Balay     q = ((gamma1 - *dx) + gamma1) + *dp;
460*a7e14dcfSSatish Balay     r = p/q;
461*a7e14dcfSSatish Balay     stpc = *stx + r*(*stp - *stx);
462*a7e14dcfSSatish Balay     stpq = *stx + ((*dx/((*fx-*fp)/(*stp-*stx)+*dx))*0.5) * (*stp - *stx);
463*a7e14dcfSSatish Balay 
464*a7e14dcfSSatish Balay     if (PetscAbsReal(stpc-*stx) < PetscAbsReal(stpq-*stx)) {
465*a7e14dcfSSatish Balay       stpf = stpc;
466*a7e14dcfSSatish Balay     }
467*a7e14dcfSSatish Balay     else {
468*a7e14dcfSSatish Balay       stpf = stpc + 0.5*(stpq - stpc);
469*a7e14dcfSSatish Balay     }
470*a7e14dcfSSatish Balay     mtP->bracket = 1;
471*a7e14dcfSSatish Balay   }
472*a7e14dcfSSatish Balay   else if (sgnd < 0.0) {
473*a7e14dcfSSatish Balay     /* Case 2: A lower function value and derivatives of
474*a7e14dcfSSatish Balay      opposite sign. The minimum is bracketed. If the cubic
475*a7e14dcfSSatish Balay      step is closer to stx than the quadratic (secant) step,
476*a7e14dcfSSatish Balay      the cubic step is taken, else the quadratic step is taken. */
477*a7e14dcfSSatish Balay 
478*a7e14dcfSSatish Balay     mtP->infoc = 2;
479*a7e14dcfSSatish Balay     bound = 0;
480*a7e14dcfSSatish Balay     theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp;
481*a7e14dcfSSatish Balay     s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx));
482*a7e14dcfSSatish Balay     s = PetscMax(s,PetscAbsReal(*dp));
483*a7e14dcfSSatish Balay     gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s));
484*a7e14dcfSSatish Balay     if (*stp > *stx) gamma1 = -gamma1;
485*a7e14dcfSSatish Balay     p = (gamma1 - *dp) + theta;
486*a7e14dcfSSatish Balay     q = ((gamma1 - *dp) + gamma1) + *dx;
487*a7e14dcfSSatish Balay     r = p/q;
488*a7e14dcfSSatish Balay     stpc = *stp + r*(*stx - *stp);
489*a7e14dcfSSatish Balay     stpq = *stp + (*dp/(*dp-*dx))*(*stx - *stp);
490*a7e14dcfSSatish Balay 
491*a7e14dcfSSatish Balay     if (PetscAbsReal(stpc-*stp) > PetscAbsReal(stpq-*stp)) {
492*a7e14dcfSSatish Balay       stpf = stpc;
493*a7e14dcfSSatish Balay     }
494*a7e14dcfSSatish Balay     else {
495*a7e14dcfSSatish Balay       stpf = stpq;
496*a7e14dcfSSatish Balay     }
497*a7e14dcfSSatish Balay     mtP->bracket = 1;
498*a7e14dcfSSatish Balay   }
499*a7e14dcfSSatish Balay   else if (PetscAbsReal(*dp) < PetscAbsReal(*dx)) {
500*a7e14dcfSSatish Balay     /* Case 3: A lower function value, derivatives of the
501*a7e14dcfSSatish Balay      same sign, and the magnitude of the derivative decreases.
502*a7e14dcfSSatish Balay      The cubic step is only used if the cubic tends to infinity
503*a7e14dcfSSatish Balay      in the direction of the step or if the minimum of the cubic
504*a7e14dcfSSatish Balay      is beyond stp. Otherwise the cubic step is defined to be
505*a7e14dcfSSatish Balay      either stepmin or stepmax. The quadratic (secant) step is also
506*a7e14dcfSSatish Balay      computed and if the minimum is bracketed then the the step
507*a7e14dcfSSatish Balay      closest to stx is taken, else the step farthest away is taken. */
508*a7e14dcfSSatish Balay 
509*a7e14dcfSSatish Balay     mtP->infoc = 3;
510*a7e14dcfSSatish Balay     bound = 1;
511*a7e14dcfSSatish Balay     theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp;
512*a7e14dcfSSatish Balay     s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx));
513*a7e14dcfSSatish Balay     s = PetscMax(s,PetscAbsReal(*dp));
514*a7e14dcfSSatish Balay 
515*a7e14dcfSSatish Balay     /* The case gamma1 = 0 only arises if the cubic does not tend
516*a7e14dcfSSatish Balay        to infinity in the direction of the step. */
517*a7e14dcfSSatish Balay     gamma1 = s*PetscSqrtScalar(PetscMax(0.0,PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s)));
518*a7e14dcfSSatish Balay     if (*stp > *stx) gamma1 = -gamma1;
519*a7e14dcfSSatish Balay     p = (gamma1 - *dp) + theta;
520*a7e14dcfSSatish Balay     q = (gamma1 + (*dx - *dp)) + gamma1;
521*a7e14dcfSSatish Balay     r = p/q;
522*a7e14dcfSSatish Balay     if (r < 0.0 && gamma1 != 0.0) stpc = *stp + r*(*stx - *stp);
523*a7e14dcfSSatish Balay     else if (*stp > *stx)        stpc = ls->stepmax;
524*a7e14dcfSSatish Balay     else                         stpc = ls->stepmin;
525*a7e14dcfSSatish Balay     stpq = *stp + (*dp/(*dp-*dx)) * (*stx - *stp);
526*a7e14dcfSSatish Balay 
527*a7e14dcfSSatish Balay     if (mtP->bracket) {
528*a7e14dcfSSatish Balay       if (PetscAbsReal(*stp-stpc) < PetscAbsReal(*stp-stpq)) {
529*a7e14dcfSSatish Balay 	stpf = stpc;
530*a7e14dcfSSatish Balay       }
531*a7e14dcfSSatish Balay       else {
532*a7e14dcfSSatish Balay 	stpf = stpq;
533*a7e14dcfSSatish Balay       }
534*a7e14dcfSSatish Balay     }
535*a7e14dcfSSatish Balay     else {
536*a7e14dcfSSatish Balay       if (PetscAbsReal(*stp-stpc) > PetscAbsReal(*stp-stpq)) {
537*a7e14dcfSSatish Balay 	stpf = stpc;
538*a7e14dcfSSatish Balay       }
539*a7e14dcfSSatish Balay       else {
540*a7e14dcfSSatish Balay 	stpf = stpq;
541*a7e14dcfSSatish Balay       }
542*a7e14dcfSSatish Balay     }
543*a7e14dcfSSatish Balay   }
544*a7e14dcfSSatish Balay   else {
545*a7e14dcfSSatish Balay     /* Case 4: A lower function value, derivatives of the
546*a7e14dcfSSatish Balay        same sign, and the magnitude of the derivative does
547*a7e14dcfSSatish Balay        not decrease. If the minimum is not bracketed, the step
548*a7e14dcfSSatish Balay        is either stpmin or stpmax, else the cubic step is taken. */
549*a7e14dcfSSatish Balay 
550*a7e14dcfSSatish Balay     mtP->infoc = 4;
551*a7e14dcfSSatish Balay     bound = 0;
552*a7e14dcfSSatish Balay     if (mtP->bracket) {
553*a7e14dcfSSatish Balay       theta = 3*(*fp - *fy)/(*sty - *stp) + *dy + *dp;
554*a7e14dcfSSatish Balay       s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dy));
555*a7e14dcfSSatish Balay       s = PetscMax(s,PetscAbsReal(*dp));
556*a7e14dcfSSatish Balay       gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dy/s)*(*dp/s));
557*a7e14dcfSSatish Balay       if (*stp > *sty) gamma1 = -gamma1;
558*a7e14dcfSSatish Balay       p = (gamma1 - *dp) + theta;
559*a7e14dcfSSatish Balay       q = ((gamma1 - *dp) + gamma1) + *dy;
560*a7e14dcfSSatish Balay       r = p/q;
561*a7e14dcfSSatish Balay       stpc = *stp + r*(*sty - *stp);
562*a7e14dcfSSatish Balay       stpq = *stp + (*dp/(*dp-*dx)) * (*stx - *stp);
563*a7e14dcfSSatish Balay 
564*a7e14dcfSSatish Balay       stpf = stpc;
565*a7e14dcfSSatish Balay     }
566*a7e14dcfSSatish Balay     else if (*stp > *stx) {
567*a7e14dcfSSatish Balay       stpf = ls->stepmax;
568*a7e14dcfSSatish Balay     }
569*a7e14dcfSSatish Balay     else {
570*a7e14dcfSSatish Balay       stpf = ls->stepmin;
571*a7e14dcfSSatish Balay     }
572*a7e14dcfSSatish Balay   }
573*a7e14dcfSSatish Balay 
574*a7e14dcfSSatish Balay   /* Update the interval of uncertainty.  This update does not
575*a7e14dcfSSatish Balay      depend on the new step or the case analysis above. */
576*a7e14dcfSSatish Balay 
577*a7e14dcfSSatish Balay   if (*fp > *fx) {
578*a7e14dcfSSatish Balay     *sty = *stp;
579*a7e14dcfSSatish Balay     *fy = *fp;
580*a7e14dcfSSatish Balay     *dy = *dp;
581*a7e14dcfSSatish Balay   }
582*a7e14dcfSSatish Balay   else {
583*a7e14dcfSSatish Balay     if (sgnd < 0.0) {
584*a7e14dcfSSatish Balay       *sty = *stx;
585*a7e14dcfSSatish Balay       *fy = *fx;
586*a7e14dcfSSatish Balay       *dy = *dx;
587*a7e14dcfSSatish Balay     }
588*a7e14dcfSSatish Balay     *stx = *stp;
589*a7e14dcfSSatish Balay     *fx = *fp;
590*a7e14dcfSSatish Balay     *dx = *dp;
591*a7e14dcfSSatish Balay   }
592*a7e14dcfSSatish Balay 
593*a7e14dcfSSatish Balay   /* Compute the new step and safeguard it. */
594*a7e14dcfSSatish Balay   stpf = PetscMin(ls->stepmax,stpf);
595*a7e14dcfSSatish Balay   stpf = PetscMax(ls->stepmin,stpf);
596*a7e14dcfSSatish Balay   *stp = stpf;
597*a7e14dcfSSatish Balay   if (mtP->bracket && bound) {
598*a7e14dcfSSatish Balay     if (*sty > *stx) {
599*a7e14dcfSSatish Balay       *stp = PetscMin(*stx+0.66*(*sty-*stx),*stp);
600*a7e14dcfSSatish Balay     }
601*a7e14dcfSSatish Balay     else {
602*a7e14dcfSSatish Balay       *stp = PetscMax(*stx+0.66*(*sty-*stx),*stp);
603*a7e14dcfSSatish Balay     }
604*a7e14dcfSSatish Balay   }
605*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
606*a7e14dcfSSatish Balay }
607