xref: /petsc/src/tao/linesearch/impls/owarmijo/owarmijo.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 "owarmijo.h"
5*a7e14dcfSSatish Balay 
6*a7e14dcfSSatish Balay #define REPLACE_FIFO 1
7*a7e14dcfSSatish Balay #define REPLACE_MRU  2
8*a7e14dcfSSatish Balay 
9*a7e14dcfSSatish Balay #define REFERENCE_MAX  1
10*a7e14dcfSSatish Balay #define REFERENCE_AVE  2
11*a7e14dcfSSatish Balay #define REFERENCE_MEAN 3
12*a7e14dcfSSatish Balay 
13*a7e14dcfSSatish Balay 
14*a7e14dcfSSatish Balay 
15*a7e14dcfSSatish Balay static PetscErrorCode ProjWork_OWLQN(Vec w,Vec x,Vec gv,PetscReal *gdx)
16*a7e14dcfSSatish Balay {
17*a7e14dcfSSatish Balay   PetscReal *xptr,*wptr,*gptr;
18*a7e14dcfSSatish Balay   PetscErrorCode ierr;
19*a7e14dcfSSatish Balay   PetscInt low,high,low1,high1,low2,high2,i;
20*a7e14dcfSSatish Balay 
21*a7e14dcfSSatish Balay   PetscFunctionBegin;
22*a7e14dcfSSatish Balay 
23*a7e14dcfSSatish Balay   ierr=VecGetOwnershipRange(w,&low,&high);CHKERRQ(ierr);
24*a7e14dcfSSatish Balay   ierr=VecGetOwnershipRange(x,&low1,&high1);CHKERRQ(ierr);
25*a7e14dcfSSatish Balay   ierr=VecGetOwnershipRange(gv,&low2,&high2);CHKERRQ(ierr);
26*a7e14dcfSSatish Balay 
27*a7e14dcfSSatish Balay   *gdx=0.0;
28*a7e14dcfSSatish Balay   ierr = VecGetArray(x,&xptr);CHKERRQ(ierr);
29*a7e14dcfSSatish Balay   ierr = VecGetArray(w,&wptr);CHKERRQ(ierr);
30*a7e14dcfSSatish Balay   ierr = VecGetArray(gv,&gptr);CHKERRQ(ierr);
31*a7e14dcfSSatish Balay 
32*a7e14dcfSSatish Balay   for (i=0;i<high-low;i++)
33*a7e14dcfSSatish Balay     {
34*a7e14dcfSSatish Balay       if (xptr[i]*wptr[i]<0.0)
35*a7e14dcfSSatish Balay 	wptr[i]=0.0;
36*a7e14dcfSSatish Balay 
37*a7e14dcfSSatish Balay       *gdx = *gdx + gptr[i]*(wptr[i]-xptr[i]);
38*a7e14dcfSSatish Balay     }
39*a7e14dcfSSatish Balay   ierr = VecRestoreArray(w,&wptr);CHKERRQ(ierr);
40*a7e14dcfSSatish Balay   ierr = VecRestoreArray(x,&xptr);CHKERRQ(ierr);
41*a7e14dcfSSatish Balay   ierr = VecRestoreArray(gv,&gptr);CHKERRQ(ierr);
42*a7e14dcfSSatish Balay 
43*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
44*a7e14dcfSSatish Balay }
45*a7e14dcfSSatish Balay 
46*a7e14dcfSSatish Balay #undef __FUNCT__
47*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchDestroy_OWArmijo"
48*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchDestroy_OWArmijo(TaoLineSearch ls)
49*a7e14dcfSSatish Balay {
50*a7e14dcfSSatish Balay   TAOLINESEARCH_OWARMIJO_CTX *armP = (TAOLINESEARCH_OWARMIJO_CTX *)ls->data;
51*a7e14dcfSSatish Balay   PetscErrorCode ierr;
52*a7e14dcfSSatish Balay 
53*a7e14dcfSSatish Balay   PetscFunctionBegin;
54*a7e14dcfSSatish Balay 
55*a7e14dcfSSatish Balay   if (armP->memory != PETSC_NULL) {
56*a7e14dcfSSatish Balay     ierr = PetscFree(armP->memory); CHKERRQ(ierr);
57*a7e14dcfSSatish Balay     armP->memory = PETSC_NULL;
58*a7e14dcfSSatish Balay   }
59*a7e14dcfSSatish Balay   if (armP->x) {
60*a7e14dcfSSatish Balay     ierr = PetscObjectDereference((PetscObject)armP->x); CHKERRQ(ierr);
61*a7e14dcfSSatish Balay   }
62*a7e14dcfSSatish Balay   ierr = VecDestroy(&armP->work); CHKERRQ(ierr);
63*a7e14dcfSSatish Balay   ierr = PetscFree(ls->data); CHKERRQ(ierr);
64*a7e14dcfSSatish Balay   ls->data = PETSC_NULL;
65*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
66*a7e14dcfSSatish Balay }
67*a7e14dcfSSatish Balay 
68*a7e14dcfSSatish Balay #undef __FUNCT__
69*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchSetFromOptions_OWArmijo"
70*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchSetFromOptions_OWArmijo(TaoLineSearch ls)
71*a7e14dcfSSatish Balay {
72*a7e14dcfSSatish Balay   TAOLINESEARCH_OWARMIJO_CTX *armP = (TAOLINESEARCH_OWARMIJO_CTX *)ls->data;
73*a7e14dcfSSatish Balay   PetscErrorCode ierr;
74*a7e14dcfSSatish Balay 
75*a7e14dcfSSatish Balay   PetscFunctionBegin;
76*a7e14dcfSSatish Balay   ierr = PetscOptionsHead("OWArmijo linesearch options");CHKERRQ(ierr);
77*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_OWArmijo_alpha", "initial reference constant", "", armP->alpha, &armP->alpha, 0); CHKERRQ(ierr);
78*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_OWArmijo_beta_inf", "decrease constant one", "", armP->beta_inf, &armP->beta_inf, 0); CHKERRQ(ierr);
79*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_OWArmijo_beta", "decrease constant", "", armP->beta, &armP->beta, 0); CHKERRQ(ierr);
80*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_OWArmijo_sigma", "acceptance constant", "", armP->sigma, &armP->sigma, 0); CHKERRQ(ierr);
81*a7e14dcfSSatish Balay   ierr = PetscOptionsInt("-tao_ls_OWArmijo_memory_size", "number of historical elements", "", armP->memorySize, &armP->memorySize, 0); CHKERRQ(ierr);
82*a7e14dcfSSatish Balay   ierr = PetscOptionsInt("-tao_ls_OWArmijo_reference_policy", "policy for updating reference value", "", armP->referencePolicy, &armP->referencePolicy, 0); CHKERRQ(ierr);
83*a7e14dcfSSatish Balay   ierr = PetscOptionsInt("-tao_ls_OWArmijo_replacement_policy", "policy for updating memory", "", armP->replacementPolicy, &armP->replacementPolicy, 0); CHKERRQ(ierr);
84*a7e14dcfSSatish Balay   ierr = PetscOptionsBool("-tao_ls_OWArmijo_nondescending","Use nondescending OWArmijo algorithm","",armP->nondescending,&armP->nondescending, 0); CHKERRQ(ierr);
85*a7e14dcfSSatish Balay   ierr = PetscOptionsTail();CHKERRQ(ierr);
86*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
87*a7e14dcfSSatish Balay }
88*a7e14dcfSSatish Balay 
89*a7e14dcfSSatish Balay #undef __FUNCT__
90*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchView_OWArmijo"
91*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchView_OWArmijo(TaoLineSearch ls, PetscViewer pv)
92*a7e14dcfSSatish Balay {
93*a7e14dcfSSatish Balay   TAOLINESEARCH_OWARMIJO_CTX *armP = (TAOLINESEARCH_OWARMIJO_CTX *)ls->data;
94*a7e14dcfSSatish Balay   PetscBool isascii;
95*a7e14dcfSSatish Balay   PetscErrorCode ierr;
96*a7e14dcfSSatish Balay 
97*a7e14dcfSSatish Balay   PetscFunctionBegin;
98*a7e14dcfSSatish Balay   ierr = PetscObjectTypeCompare((PetscObject)pv, PETSCVIEWERASCII, &isascii); CHKERRQ(ierr);
99*a7e14dcfSSatish Balay   if (isascii) {
100*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(pv,"  maxf=%d, ftol=%g, gtol=%g\n",ls->max_funcs, ls->rtol, ls->ftol); CHKERRQ(ierr);
101*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,"  OWArmijo linesearch",armP->alpha);CHKERRQ(ierr);
102*a7e14dcfSSatish Balay     if (armP->nondescending) {
103*a7e14dcfSSatish Balay       ierr = PetscViewerASCIIPrintf(pv, " (nondescending)"); CHKERRQ(ierr);
104*a7e14dcfSSatish Balay     }
105*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,": alpha=%g beta=%g ",armP->alpha,armP->beta);CHKERRQ(ierr);
106*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,"sigma=%g ",armP->sigma);CHKERRQ(ierr);
107*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,"memsize=%d\n",armP->memorySize);CHKERRQ(ierr);
108*a7e14dcfSSatish Balay   } else {
109*a7e14dcfSSatish Balay     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for OWArmijo TaoLineSearch",((PetscObject)pv)->type_name);
110*a7e14dcfSSatish Balay   }
111*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
112*a7e14dcfSSatish Balay }
113*a7e14dcfSSatish Balay 
114*a7e14dcfSSatish Balay #undef __FUNCT__
115*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchApply_OWArmijo"
116*a7e14dcfSSatish Balay /* @ TaoApply_OWArmijo - This routine performs a linesearch. It
117*a7e14dcfSSatish Balay    backtracks until the (nonmonotone) OWArmijo conditions are satisfied.
118*a7e14dcfSSatish Balay 
119*a7e14dcfSSatish Balay    Input Parameters:
120*a7e14dcfSSatish Balay +  tao - TAO_SOLVER context
121*a7e14dcfSSatish Balay .  X - current iterate (on output X contains new iterate, X + step*S)
122*a7e14dcfSSatish Balay .  S - search direction
123*a7e14dcfSSatish Balay .  f - merit function evaluated at X
124*a7e14dcfSSatish Balay .  G - gradient of merit function evaluated at X
125*a7e14dcfSSatish Balay .  W - work vector
126*a7e14dcfSSatish Balay -  step - initial estimate of step length
127*a7e14dcfSSatish Balay 
128*a7e14dcfSSatish Balay    Output parameters:
129*a7e14dcfSSatish Balay +  f - merit function evaluated at new iterate, X + step*S
130*a7e14dcfSSatish Balay .  G - gradient of merit function evaluated at new iterate, X + step*S
131*a7e14dcfSSatish Balay .  X - new iterate
132*a7e14dcfSSatish Balay -  step - final step length
133*a7e14dcfSSatish Balay 
134*a7e14dcfSSatish Balay    Info is set to one of:
135*a7e14dcfSSatish Balay .   0 - the line search succeeds; the sufficient decrease
136*a7e14dcfSSatish Balay    condition and the directional derivative condition hold
137*a7e14dcfSSatish Balay 
138*a7e14dcfSSatish Balay    negative number if an input parameter is invalid
139*a7e14dcfSSatish Balay -   -1 -  step < 0
140*a7e14dcfSSatish Balay 
141*a7e14dcfSSatish Balay    positive number > 1 if the line search otherwise terminates
142*a7e14dcfSSatish Balay +    1 -  Step is at the lower bound, stepmin.
143*a7e14dcfSSatish Balay @ */
144*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchApply_OWArmijo(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s)
145*a7e14dcfSSatish Balay {
146*a7e14dcfSSatish Balay   TAOLINESEARCH_OWARMIJO_CTX *armP = (TAOLINESEARCH_OWARMIJO_CTX *)ls->data;
147*a7e14dcfSSatish Balay   PetscErrorCode ierr;
148*a7e14dcfSSatish Balay   PetscInt i;
149*a7e14dcfSSatish Balay   PetscReal fact, ref, gdx;
150*a7e14dcfSSatish Balay   PetscInt idx;
151*a7e14dcfSSatish Balay   PetscBool g_computed=PETSC_FALSE; /* to prevent extra gradient computation */
152*a7e14dcfSSatish Balay 
153*a7e14dcfSSatish Balay   Vec g_old;
154*a7e14dcfSSatish Balay   PetscReal owlqn_minstep=0.005;
155*a7e14dcfSSatish Balay   PetscReal partgdx;
156*a7e14dcfSSatish Balay 
157*a7e14dcfSSatish Balay   PetscFunctionBegin;
158*a7e14dcfSSatish Balay 
159*a7e14dcfSSatish Balay   fact = 0.0;
160*a7e14dcfSSatish Balay   ls->nfeval=0;
161*a7e14dcfSSatish Balay   ls->reason = TAOLINESEARCH_CONTINUE_ITERATING;
162*a7e14dcfSSatish Balay   if (!armP->work) {
163*a7e14dcfSSatish Balay     ierr = VecDuplicate(x,&armP->work); CHKERRQ(ierr);
164*a7e14dcfSSatish Balay     armP->x = x;
165*a7e14dcfSSatish Balay     ierr = PetscObjectReference((PetscObject)armP->x); CHKERRQ(ierr);
166*a7e14dcfSSatish Balay   }
167*a7e14dcfSSatish Balay   /* If x has changed, then recreate work */
168*a7e14dcfSSatish Balay   else if (x != armP->x) {
169*a7e14dcfSSatish Balay     ierr = VecDestroy(&armP->work); CHKERRQ(ierr);
170*a7e14dcfSSatish Balay     ierr = VecDuplicate(x,&armP->work); CHKERRQ(ierr);
171*a7e14dcfSSatish Balay     ierr = PetscObjectDereference((PetscObject)armP->x); CHKERRQ(ierr);
172*a7e14dcfSSatish Balay     armP->x = x;
173*a7e14dcfSSatish Balay     ierr = PetscObjectReference((PetscObject)armP->x); CHKERRQ(ierr);
174*a7e14dcfSSatish Balay   }
175*a7e14dcfSSatish Balay 
176*a7e14dcfSSatish Balay   /* Check linesearch parameters */
177*a7e14dcfSSatish Balay   if (armP->alpha < 1) {
178*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"OWArmijo line search error: alpha (%g) < 1\n", armP->alpha); CHKERRQ(ierr);
179*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
180*a7e14dcfSSatish Balay   }
181*a7e14dcfSSatish Balay 
182*a7e14dcfSSatish Balay   else if ((armP->beta <= 0) || (armP->beta >= 1)) {
183*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"OWArmijo line search error: beta (%g) invalid\n", armP->beta); CHKERRQ(ierr);
184*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
185*a7e14dcfSSatish Balay 
186*a7e14dcfSSatish Balay   }
187*a7e14dcfSSatish Balay 
188*a7e14dcfSSatish Balay   else if ((armP->beta_inf <= 0) || (armP->beta_inf >= 1)) {
189*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"OWArmijo line search error: beta_inf (%g) invalid\n", armP->beta_inf); CHKERRQ(ierr);
190*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
191*a7e14dcfSSatish Balay   }
192*a7e14dcfSSatish Balay 
193*a7e14dcfSSatish Balay   else if ((armP->sigma <= 0) || (armP->sigma >= 0.5)) {
194*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"OWArmijo line search error: sigma (%g) invalid\n", armP->sigma); CHKERRQ(ierr);
195*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
196*a7e14dcfSSatish Balay   }
197*a7e14dcfSSatish Balay 
198*a7e14dcfSSatish Balay   else if (armP->memorySize < 1) {
199*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"OWArmijo line search error: memory_size (%d) < 1\n", armP->memorySize); CHKERRQ(ierr);
200*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
201*a7e14dcfSSatish Balay   }
202*a7e14dcfSSatish Balay 
203*a7e14dcfSSatish Balay   else if ((armP->referencePolicy != REFERENCE_MAX) &&
204*a7e14dcfSSatish Balay       (armP->referencePolicy != REFERENCE_AVE) &&
205*a7e14dcfSSatish Balay       (armP->referencePolicy != REFERENCE_MEAN)) {
206*a7e14dcfSSatish Balay     ierr = PetscInfo(ls,"OWArmijo line search error: reference_policy invalid\n"); CHKERRQ(ierr);
207*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
208*a7e14dcfSSatish Balay 
209*a7e14dcfSSatish Balay   }
210*a7e14dcfSSatish Balay 
211*a7e14dcfSSatish Balay   else if ((armP->replacementPolicy != REPLACE_FIFO) &&
212*a7e14dcfSSatish Balay       (armP->replacementPolicy != REPLACE_MRU)) {
213*a7e14dcfSSatish Balay     ierr = PetscInfo(ls,"OWArmijo line search error: replacement_policy invalid\n"); CHKERRQ(ierr);
214*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
215*a7e14dcfSSatish Balay   }
216*a7e14dcfSSatish Balay 
217*a7e14dcfSSatish Balay   else if (PetscIsInfOrNanReal(*f)) {
218*a7e14dcfSSatish Balay     ierr = PetscInfo(ls,"OWArmijo line search error: initial function inf or nan\n"); CHKERRQ(ierr);
219*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
220*a7e14dcfSSatish Balay   }
221*a7e14dcfSSatish Balay 
222*a7e14dcfSSatish Balay   if (ls->reason != TAOLINESEARCH_CONTINUE_ITERATING) {
223*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
224*a7e14dcfSSatish Balay   }
225*a7e14dcfSSatish Balay 
226*a7e14dcfSSatish Balay   /* Check to see of the memory has been allocated.  If not, allocate
227*a7e14dcfSSatish Balay      the historical array and populate it with the initial function
228*a7e14dcfSSatish Balay      values. */
229*a7e14dcfSSatish Balay   if (armP->memory == PETSC_NULL) {
230*a7e14dcfSSatish Balay     ierr = PetscMalloc(sizeof(PetscReal)*armP->memorySize, &armP->memory ); CHKERRQ(ierr);
231*a7e14dcfSSatish Balay   }
232*a7e14dcfSSatish Balay 
233*a7e14dcfSSatish Balay   if (!armP->memorySetup) {
234*a7e14dcfSSatish Balay     for (i = 0; i < armP->memorySize; i++) {
235*a7e14dcfSSatish Balay       armP->memory[i] = armP->alpha*(*f);
236*a7e14dcfSSatish Balay     }
237*a7e14dcfSSatish Balay 
238*a7e14dcfSSatish Balay     armP->current = 0;
239*a7e14dcfSSatish Balay     armP->lastReference = armP->memory[0];
240*a7e14dcfSSatish Balay     armP->memorySetup=PETSC_TRUE;
241*a7e14dcfSSatish Balay   }
242*a7e14dcfSSatish Balay 
243*a7e14dcfSSatish Balay   /* Calculate reference value (MAX) */
244*a7e14dcfSSatish Balay   ref = armP->memory[0];
245*a7e14dcfSSatish Balay   idx = 0;
246*a7e14dcfSSatish Balay 
247*a7e14dcfSSatish Balay   for (i = 1; i < armP->memorySize; i++) {
248*a7e14dcfSSatish Balay     if (armP->memory[i] > ref) {
249*a7e14dcfSSatish Balay       ref = armP->memory[i];
250*a7e14dcfSSatish Balay       idx = i;
251*a7e14dcfSSatish Balay     }
252*a7e14dcfSSatish Balay   }
253*a7e14dcfSSatish Balay 
254*a7e14dcfSSatish Balay   if (armP->referencePolicy == REFERENCE_AVE) {
255*a7e14dcfSSatish Balay     ref = 0;
256*a7e14dcfSSatish Balay     for (i = 0; i < armP->memorySize; i++) {
257*a7e14dcfSSatish Balay       ref += armP->memory[i];
258*a7e14dcfSSatish Balay     }
259*a7e14dcfSSatish Balay     ref = ref / armP->memorySize;
260*a7e14dcfSSatish Balay     ref = PetscMax(ref, armP->memory[armP->current]);
261*a7e14dcfSSatish Balay   }
262*a7e14dcfSSatish Balay   else if (armP->referencePolicy == REFERENCE_MEAN) {
263*a7e14dcfSSatish Balay     ref = PetscMin(ref, 0.5*(armP->lastReference + armP->memory[armP->current]));
264*a7e14dcfSSatish Balay   }
265*a7e14dcfSSatish Balay 
266*a7e14dcfSSatish Balay 
267*a7e14dcfSSatish Balay   if (armP->nondescending) {
268*a7e14dcfSSatish Balay     fact = armP->sigma;
269*a7e14dcfSSatish Balay   }
270*a7e14dcfSSatish Balay 
271*a7e14dcfSSatish Balay   VecDuplicate(g,&g_old);
272*a7e14dcfSSatish Balay   VecCopy(g,g_old);
273*a7e14dcfSSatish Balay 
274*a7e14dcfSSatish Balay   ls->step = ls->initstep;
275*a7e14dcfSSatish Balay 
276*a7e14dcfSSatish Balay   while (ls->step >= owlqn_minstep && ls->nfeval < ls->max_funcs) {
277*a7e14dcfSSatish Balay     /* Calculate iterate */
278*a7e14dcfSSatish Balay     ierr = VecCopy(x,armP->work); CHKERRQ(ierr);
279*a7e14dcfSSatish Balay     ierr = VecAXPY(armP->work,ls->step,s); CHKERRQ(ierr);
280*a7e14dcfSSatish Balay 
281*a7e14dcfSSatish Balay     partgdx=0.0;
282*a7e14dcfSSatish Balay     ierr = ProjWork_OWLQN(armP->work,x,g_old,&partgdx);
283*a7e14dcfSSatish Balay     ierr = (PetscErrorCode)MPI_Allreduce(&partgdx,&gdx,1,MPI_DOUBLE,MPI_SUM,PETSC_COMM_WORLD); CHKERRQ(ierr);
284*a7e14dcfSSatish Balay 
285*a7e14dcfSSatish Balay     /* Check the condition of gdx */
286*a7e14dcfSSatish Balay     if (PetscIsInfOrNanReal(gdx)) {
287*a7e14dcfSSatish Balay       ierr = PetscInfo1(ls,"Initial Line Search step * g is Inf or Nan (%g)\n",gdx); CHKERRQ(ierr);
288*a7e14dcfSSatish Balay       ls->reason=TAOLINESEARCH_FAILED_INFORNAN;
289*a7e14dcfSSatish Balay       PetscFunctionReturn(0);
290*a7e14dcfSSatish Balay     }
291*a7e14dcfSSatish Balay     if (gdx >= 0.0) {
292*a7e14dcfSSatish Balay       ierr = PetscInfo1(ls,"Initial Line Search step is not descent direction (g's=%g)\n",gdx); CHKERRQ(ierr);
293*a7e14dcfSSatish Balay       ls->reason = TAOLINESEARCH_FAILED_ASCENT;
294*a7e14dcfSSatish Balay       PetscFunctionReturn(0);
295*a7e14dcfSSatish Balay     }
296*a7e14dcfSSatish Balay 
297*a7e14dcfSSatish Balay     /* Calculate function at new iterate */
298*a7e14dcfSSatish Balay     ierr = TaoLineSearchComputeObjectiveAndGradient(ls,armP->work,f,g); CHKERRQ(ierr);
299*a7e14dcfSSatish Balay     g_computed=PETSC_TRUE;
300*a7e14dcfSSatish Balay 
301*a7e14dcfSSatish Balay 
302*a7e14dcfSSatish Balay     if (ls->step == ls->initstep) {
303*a7e14dcfSSatish Balay       ls->f_fullstep = *f;
304*a7e14dcfSSatish Balay     }
305*a7e14dcfSSatish Balay 
306*a7e14dcfSSatish Balay     if (PetscIsInfOrNanReal(*f)) {
307*a7e14dcfSSatish Balay       ls->step *= armP->beta_inf;
308*a7e14dcfSSatish Balay     }
309*a7e14dcfSSatish Balay     else {
310*a7e14dcfSSatish Balay       /* Check descent condition */
311*a7e14dcfSSatish Balay       if (armP->nondescending && *f <= ref - ls->step*fact*ref)
312*a7e14dcfSSatish Balay 	break;
313*a7e14dcfSSatish Balay       if (!armP->nondescending && *f <= ref + armP->sigma * gdx) {
314*a7e14dcfSSatish Balay         break;
315*a7e14dcfSSatish Balay       }
316*a7e14dcfSSatish Balay 
317*a7e14dcfSSatish Balay       ls->step *= armP->beta;
318*a7e14dcfSSatish Balay     }
319*a7e14dcfSSatish Balay   }
320*a7e14dcfSSatish Balay 
321*a7e14dcfSSatish Balay   VecDestroy(&g_old);
322*a7e14dcfSSatish Balay 
323*a7e14dcfSSatish Balay   /* Check termination */
324*a7e14dcfSSatish Balay   if (PetscIsInfOrNanReal(*f)) {
325*a7e14dcfSSatish Balay     ierr = PetscInfo(ls, "Function is inf or nan.\n"); CHKERRQ(ierr);
326*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_FAILED_BADPARAMETER;
327*a7e14dcfSSatish Balay   } else if (ls->step < owlqn_minstep) {
328*a7e14dcfSSatish Balay     ierr = PetscInfo(ls, "Step length is below tolerance.\n"); CHKERRQ(ierr);
329*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_HALTED_RTOL;
330*a7e14dcfSSatish Balay   } else if (ls->nfeval >= ls->max_funcs) {
331*a7e14dcfSSatish Balay     ierr = PetscInfo2(ls, "Number of line search function evals (%d) > maximum allowed (%d)\n",ls->nfeval, ls->max_funcs); CHKERRQ(ierr);
332*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_HALTED_MAXFCN;
333*a7e14dcfSSatish Balay   }
334*a7e14dcfSSatish Balay   if (ls->reason) {
335*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
336*a7e14dcfSSatish Balay   }
337*a7e14dcfSSatish Balay 
338*a7e14dcfSSatish Balay   /* Successful termination, update memory */
339*a7e14dcfSSatish Balay   armP->lastReference = ref;
340*a7e14dcfSSatish Balay   if (armP->replacementPolicy == REPLACE_FIFO) {
341*a7e14dcfSSatish Balay     armP->memory[armP->current++] = *f;
342*a7e14dcfSSatish Balay     if (armP->current >= armP->memorySize) {
343*a7e14dcfSSatish Balay       armP->current = 0;
344*a7e14dcfSSatish Balay     }
345*a7e14dcfSSatish Balay   } else {
346*a7e14dcfSSatish Balay     armP->current = idx;
347*a7e14dcfSSatish Balay     armP->memory[idx] = *f;
348*a7e14dcfSSatish Balay   }
349*a7e14dcfSSatish Balay 
350*a7e14dcfSSatish Balay   /* Update iterate and compute gradient */
351*a7e14dcfSSatish Balay   ierr = VecCopy(armP->work,x); CHKERRQ(ierr);
352*a7e14dcfSSatish Balay   if (!g_computed) {
353*a7e14dcfSSatish Balay     ierr = TaoLineSearchComputeGradient(ls, x, g); CHKERRQ(ierr);
354*a7e14dcfSSatish Balay   }
355*a7e14dcfSSatish Balay 
356*a7e14dcfSSatish Balay   /* Finish computations */
357*a7e14dcfSSatish Balay   ierr = PetscInfo2(ls, "%d function evals in line search, step = %10.4f\n",ls->nfeval, ls->step); CHKERRQ(ierr);
358*a7e14dcfSSatish Balay 
359*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
360*a7e14dcfSSatish Balay }
361*a7e14dcfSSatish Balay 
362*a7e14dcfSSatish Balay EXTERN_C_BEGIN
363*a7e14dcfSSatish Balay #undef __FUNCT__
364*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchCreate_OWArmijo"
365*a7e14dcfSSatish Balay PetscErrorCode TaoLineSearchCreate_OWArmijo(TaoLineSearch ls)
366*a7e14dcfSSatish Balay {
367*a7e14dcfSSatish Balay   TAOLINESEARCH_OWARMIJO_CTX *armP;
368*a7e14dcfSSatish Balay   PetscErrorCode ierr;
369*a7e14dcfSSatish Balay 
370*a7e14dcfSSatish Balay   PetscFunctionBegin;
371*a7e14dcfSSatish Balay   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
372*a7e14dcfSSatish Balay   ierr = PetscNewLog(ls,TAOLINESEARCH_OWARMIJO_CTX, &armP);CHKERRQ(ierr);
373*a7e14dcfSSatish Balay 
374*a7e14dcfSSatish Balay   armP->memory = PETSC_NULL;
375*a7e14dcfSSatish Balay   armP->alpha = 1.0;
376*a7e14dcfSSatish Balay   armP->beta = 0.25;
377*a7e14dcfSSatish Balay   armP->beta_inf = 0.25;
378*a7e14dcfSSatish Balay   armP->sigma = 1e-4;
379*a7e14dcfSSatish Balay   armP->memorySize = 1;
380*a7e14dcfSSatish Balay   armP->referencePolicy = REFERENCE_MAX;
381*a7e14dcfSSatish Balay   armP->replacementPolicy = REPLACE_MRU;
382*a7e14dcfSSatish Balay   armP->nondescending=PETSC_FALSE;
383*a7e14dcfSSatish Balay   ls->data = (void*)armP;
384*a7e14dcfSSatish Balay   ls->initstep=0.1;
385*a7e14dcfSSatish Balay   ls->ops->setup=0;
386*a7e14dcfSSatish Balay   ls->ops->apply=TaoLineSearchApply_OWArmijo;
387*a7e14dcfSSatish Balay   ls->ops->view = TaoLineSearchView_OWArmijo;
388*a7e14dcfSSatish Balay   ls->ops->destroy = TaoLineSearchDestroy_OWArmijo;
389*a7e14dcfSSatish Balay   ls->ops->setfromoptions = TaoLineSearchSetFromOptions_OWArmijo;
390*a7e14dcfSSatish Balay 
391*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
392*a7e14dcfSSatish Balay }
393*a7e14dcfSSatish Balay EXTERN_C_END
394