xref: /petsc/src/tao/unconstrained/impls/owlqn/owlqn.c (revision a7e14dcfba0d07adf6226a919460249440ec94c7)
1*a7e14dcfSSatish Balay #include "taolinesearch.h"
2*a7e14dcfSSatish Balay #include "src/matrix/lmvmmat.h"
3*a7e14dcfSSatish Balay #include "owlqn.h"
4*a7e14dcfSSatish Balay 
5*a7e14dcfSSatish Balay #define OWLQN_BFGS                0
6*a7e14dcfSSatish Balay #define OWLQN_SCALED_GRADIENT     1
7*a7e14dcfSSatish Balay #define OWLQN_GRADIENT            2
8*a7e14dcfSSatish Balay 
9*a7e14dcfSSatish Balay 
10*a7e14dcfSSatish Balay #undef __FUNCT__
11*a7e14dcfSSatish Balay #define __FUNCT__ "ProjDirect_OWLQN"
12*a7e14dcfSSatish Balay static PetscErrorCode ProjDirect_OWLQN(Vec d, Vec g)
13*a7e14dcfSSatish Balay {
14*a7e14dcfSSatish Balay   PetscErrorCode ierr;
15*a7e14dcfSSatish Balay   PetscReal *gptr,*dptr;
16*a7e14dcfSSatish Balay   PetscInt low,high,low1,high1,i;
17*a7e14dcfSSatish Balay 
18*a7e14dcfSSatish Balay   PetscFunctionBegin;
19*a7e14dcfSSatish Balay 
20*a7e14dcfSSatish Balay   ierr=VecGetOwnershipRange(d,&low,&high);CHKERRQ(ierr);
21*a7e14dcfSSatish Balay   ierr=VecGetOwnershipRange(g,&low1,&high1);CHKERRQ(ierr);
22*a7e14dcfSSatish Balay 
23*a7e14dcfSSatish Balay   ierr = VecGetArray(g,&gptr);CHKERRQ(ierr);
24*a7e14dcfSSatish Balay   ierr = VecGetArray(d,&dptr);CHKERRQ(ierr);
25*a7e14dcfSSatish Balay   for (i = 0; i < high-low; i++) {
26*a7e14dcfSSatish Balay     if (dptr[i] * gptr[i] <= 0.0 )
27*a7e14dcfSSatish Balay       {
28*a7e14dcfSSatish Balay 	dptr[i] = 0.0;
29*a7e14dcfSSatish Balay       }
30*a7e14dcfSSatish Balay   }
31*a7e14dcfSSatish Balay   ierr = VecRestoreArray(d,&dptr);CHKERRQ(ierr);
32*a7e14dcfSSatish Balay   ierr = VecRestoreArray(g,&gptr);CHKERRQ(ierr);
33*a7e14dcfSSatish Balay 
34*a7e14dcfSSatish Balay 
35*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
36*a7e14dcfSSatish Balay }
37*a7e14dcfSSatish Balay 
38*a7e14dcfSSatish Balay #undef __FUNCT__
39*a7e14dcfSSatish Balay #define __FUNCT__ "ComputePseudoGrad_OWLQN"
40*a7e14dcfSSatish Balay static PetscErrorCode ComputePseudoGrad_OWLQN(Vec x, Vec gv, PetscReal lambda)
41*a7e14dcfSSatish Balay {
42*a7e14dcfSSatish Balay 
43*a7e14dcfSSatish Balay   PetscErrorCode ierr;
44*a7e14dcfSSatish Balay   PetscReal *xptr,*gptr;
45*a7e14dcfSSatish Balay   PetscInt low,high,low1,high1,i;
46*a7e14dcfSSatish Balay 
47*a7e14dcfSSatish Balay 
48*a7e14dcfSSatish Balay   PetscFunctionBegin;
49*a7e14dcfSSatish Balay 
50*a7e14dcfSSatish Balay   ierr=VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr);
51*a7e14dcfSSatish Balay   ierr=VecGetOwnershipRange(gv,&low1,&high1);CHKERRQ(ierr);
52*a7e14dcfSSatish Balay 
53*a7e14dcfSSatish Balay   ierr = VecGetArray(x,&xptr);CHKERRQ(ierr);
54*a7e14dcfSSatish Balay   ierr = VecGetArray(gv,&gptr);CHKERRQ(ierr);
55*a7e14dcfSSatish Balay   for (i = 0; i < high-low; i++) {
56*a7e14dcfSSatish Balay     if (xptr[i] < 0.0)
57*a7e14dcfSSatish Balay       gptr[i] = gptr[i] - lambda;
58*a7e14dcfSSatish Balay     else if (xptr[i] > 0.0)
59*a7e14dcfSSatish Balay       gptr[i] = gptr[i] + lambda;
60*a7e14dcfSSatish Balay     else if (gptr[i] + lambda < 0.0)
61*a7e14dcfSSatish Balay       gptr[i] = gptr[i] + lambda;
62*a7e14dcfSSatish Balay     else if (gptr[i] - lambda > 0.0)
63*a7e14dcfSSatish Balay       gptr[i] = gptr[i] - lambda;
64*a7e14dcfSSatish Balay     else
65*a7e14dcfSSatish Balay       gptr[i] = 0.0;
66*a7e14dcfSSatish Balay   }
67*a7e14dcfSSatish Balay   ierr = VecRestoreArray(gv,&gptr);CHKERRQ(ierr);
68*a7e14dcfSSatish Balay   ierr = VecRestoreArray(x,&xptr);CHKERRQ(ierr);
69*a7e14dcfSSatish Balay 
70*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
71*a7e14dcfSSatish Balay  }
72*a7e14dcfSSatish Balay 
73*a7e14dcfSSatish Balay 
74*a7e14dcfSSatish Balay 
75*a7e14dcfSSatish Balay 
76*a7e14dcfSSatish Balay #undef __FUNCT__
77*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSolve_OWLQN"
78*a7e14dcfSSatish Balay static PetscErrorCode TaoSolve_OWLQN(TaoSolver tao)
79*a7e14dcfSSatish Balay {
80*a7e14dcfSSatish Balay 
81*a7e14dcfSSatish Balay   TAO_OWLQN *lmP = (TAO_OWLQN *)tao->data;
82*a7e14dcfSSatish Balay 
83*a7e14dcfSSatish Balay   PetscReal f, fold, gdx, gnorm;
84*a7e14dcfSSatish Balay   PetscReal step = 1.0;
85*a7e14dcfSSatish Balay 
86*a7e14dcfSSatish Balay   PetscReal delta;
87*a7e14dcfSSatish Balay 
88*a7e14dcfSSatish Balay   PetscErrorCode ierr;
89*a7e14dcfSSatish Balay   PetscInt stepType;
90*a7e14dcfSSatish Balay   PetscInt iter = 0;
91*a7e14dcfSSatish Balay   TaoSolverTerminationReason reason = TAO_CONTINUE_ITERATING;
92*a7e14dcfSSatish Balay   TaoLineSearchTerminationReason ls_status = TAOLINESEARCH_CONTINUE_ITERATING;
93*a7e14dcfSSatish Balay 
94*a7e14dcfSSatish Balay   PetscFunctionBegin;
95*a7e14dcfSSatish Balay 
96*a7e14dcfSSatish Balay   if (tao->XL || tao->XU || tao->ops->computebounds) {
97*a7e14dcfSSatish Balay     ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by owlqn algorithm\n"); CHKERRQ(ierr);
98*a7e14dcfSSatish Balay   }
99*a7e14dcfSSatish Balay 
100*a7e14dcfSSatish Balay   /* Check convergence criteria */
101*a7e14dcfSSatish Balay   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient); CHKERRQ(ierr);
102*a7e14dcfSSatish Balay 
103*a7e14dcfSSatish Balay   ierr = VecCopy(tao->gradient, lmP->GV); CHKERRQ(ierr);
104*a7e14dcfSSatish Balay 
105*a7e14dcfSSatish Balay   ierr = ComputePseudoGrad_OWLQN(tao->solution,lmP->GV,lmP->lambda);CHKERRQ(ierr);
106*a7e14dcfSSatish Balay 
107*a7e14dcfSSatish Balay   ierr = VecNorm(lmP->GV,NORM_2,&gnorm); CHKERRQ(ierr);
108*a7e14dcfSSatish Balay 
109*a7e14dcfSSatish Balay   if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) {
110*a7e14dcfSSatish Balay     SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
111*a7e14dcfSSatish Balay   }
112*a7e14dcfSSatish Balay 
113*a7e14dcfSSatish Balay   ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, step, &reason); CHKERRQ(ierr);
114*a7e14dcfSSatish Balay   if (reason != TAO_CONTINUE_ITERATING) {
115*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
116*a7e14dcfSSatish Balay   }
117*a7e14dcfSSatish Balay 
118*a7e14dcfSSatish Balay   /* Set initial scaling for the function */
119*a7e14dcfSSatish Balay   if (f != 0.0) {
120*a7e14dcfSSatish Balay     delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
121*a7e14dcfSSatish Balay   }
122*a7e14dcfSSatish Balay   else {
123*a7e14dcfSSatish Balay     delta = 2.0 / (gnorm*gnorm);
124*a7e14dcfSSatish Balay   }
125*a7e14dcfSSatish Balay   ierr = MatLMVMSetDelta(lmP->M,delta); CHKERRQ(ierr);
126*a7e14dcfSSatish Balay 
127*a7e14dcfSSatish Balay   /* Set counter for gradient/reset steps */
128*a7e14dcfSSatish Balay   lmP->bfgs = 0;
129*a7e14dcfSSatish Balay   lmP->sgrad = 0;
130*a7e14dcfSSatish Balay   lmP->grad = 0;
131*a7e14dcfSSatish Balay 
132*a7e14dcfSSatish Balay   /* Have not converged; continue with Newton method */
133*a7e14dcfSSatish Balay   while (reason == TAO_CONTINUE_ITERATING) {
134*a7e14dcfSSatish Balay 
135*a7e14dcfSSatish Balay     /* Compute direction */
136*a7e14dcfSSatish Balay     ierr = MatLMVMUpdate(lmP->M,tao->solution,tao->gradient); CHKERRQ(ierr);
137*a7e14dcfSSatish Balay     ierr = MatLMVMSolve(lmP->M, lmP->GV, lmP->D); CHKERRQ(ierr);
138*a7e14dcfSSatish Balay 
139*a7e14dcfSSatish Balay     ierr = ProjDirect_OWLQN(lmP->D,lmP->GV);CHKERRQ(ierr);
140*a7e14dcfSSatish Balay 
141*a7e14dcfSSatish Balay     ++lmP->bfgs;
142*a7e14dcfSSatish Balay 
143*a7e14dcfSSatish Balay     /* Check for success (descent direction) */
144*a7e14dcfSSatish Balay     ierr = VecDot(lmP->D, lmP->GV , &gdx); CHKERRQ(ierr);
145*a7e14dcfSSatish Balay     if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
146*a7e14dcfSSatish Balay 
147*a7e14dcfSSatish Balay       /* Step is not descent or direction produced not a number
148*a7e14dcfSSatish Balay 	 We can assert bfgsUpdates > 1 in this case because
149*a7e14dcfSSatish Balay 	 the first solve produces the scaled gradient direction,
150*a7e14dcfSSatish Balay 	 which is guaranteed to be descent
151*a7e14dcfSSatish Balay 
152*a7e14dcfSSatish Balay 	 Use steepest descent direction (scaled) */
153*a7e14dcfSSatish Balay       ++lmP->grad;
154*a7e14dcfSSatish Balay 
155*a7e14dcfSSatish Balay       if (f != 0.0) {
156*a7e14dcfSSatish Balay         delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
157*a7e14dcfSSatish Balay       }
158*a7e14dcfSSatish Balay       else {
159*a7e14dcfSSatish Balay         delta = 2.0 / (gnorm*gnorm);
160*a7e14dcfSSatish Balay       }
161*a7e14dcfSSatish Balay       ierr = MatLMVMSetDelta(lmP->M, delta); CHKERRQ(ierr);
162*a7e14dcfSSatish Balay       ierr = MatLMVMReset(lmP->M); CHKERRQ(ierr);
163*a7e14dcfSSatish Balay       ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
164*a7e14dcfSSatish Balay       ierr = MatLMVMSolve(lmP->M,lmP->GV, lmP->D); CHKERRQ(ierr);
165*a7e14dcfSSatish Balay 
166*a7e14dcfSSatish Balay       ierr = ProjDirect_OWLQN(lmP->D,lmP->GV);CHKERRQ(ierr);
167*a7e14dcfSSatish Balay       /* On a reset, the direction cannot be not a number; it is a
168*a7e14dcfSSatish Balay 	 scaled gradient step.  No need to check for this condition.
169*a7e14dcfSSatish Balay 	 info = D->Norm2(&dnorm); CHKERRQ(info);
170*a7e14dcfSSatish Balay 	 if (PetscIsInfOrNanReal(dnorm)) {
171*a7e14dcfSSatish Balay 	 SETERRQ(PETSC_COMM_SELF,1, "Direction generated Not-a-Number");
172*a7e14dcfSSatish Balay        } */
173*a7e14dcfSSatish Balay 
174*a7e14dcfSSatish Balay       lmP->bfgs = 1;
175*a7e14dcfSSatish Balay       ++lmP->sgrad;
176*a7e14dcfSSatish Balay       stepType = OWLQN_SCALED_GRADIENT;
177*a7e14dcfSSatish Balay     }
178*a7e14dcfSSatish Balay     else {
179*a7e14dcfSSatish Balay       if (1 == lmP->bfgs) {
180*a7e14dcfSSatish Balay         /* The first BFGS direction is always the scaled gradient */
181*a7e14dcfSSatish Balay         ++lmP->sgrad;
182*a7e14dcfSSatish Balay         stepType = OWLQN_SCALED_GRADIENT;
183*a7e14dcfSSatish Balay       }
184*a7e14dcfSSatish Balay       else {
185*a7e14dcfSSatish Balay         ++lmP->bfgs;
186*a7e14dcfSSatish Balay         stepType = OWLQN_BFGS;
187*a7e14dcfSSatish Balay       }
188*a7e14dcfSSatish Balay     }
189*a7e14dcfSSatish Balay 
190*a7e14dcfSSatish Balay     ierr = VecScale(lmP->D, -1.0); CHKERRQ(ierr);
191*a7e14dcfSSatish Balay 
192*a7e14dcfSSatish Balay     /* Perform the linesearch */
193*a7e14dcfSSatish Balay     fold = f;
194*a7e14dcfSSatish Balay     ierr = VecCopy(tao->solution, lmP->Xold); CHKERRQ(ierr);
195*a7e14dcfSSatish Balay     ierr = VecCopy(tao->gradient, lmP->Gold); CHKERRQ(ierr);
196*a7e14dcfSSatish Balay 
197*a7e14dcfSSatish Balay     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, lmP->GV, lmP->D, &step,&ls_status); CHKERRQ(ierr);
198*a7e14dcfSSatish Balay     ierr = TaoAddLineSearchCounts(tao); CHKERRQ(ierr);
199*a7e14dcfSSatish Balay 
200*a7e14dcfSSatish Balay     while (((int)ls_status < 0) && (stepType != OWLQN_GRADIENT)) {
201*a7e14dcfSSatish Balay 
202*a7e14dcfSSatish Balay       /* Reset factors and use scaled gradient step */
203*a7e14dcfSSatish Balay       f = fold;
204*a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Xold, tao->solution); CHKERRQ(ierr);
205*a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Gold, tao->gradient); CHKERRQ(ierr);
206*a7e14dcfSSatish Balay       ierr = VecCopy(tao->gradient, lmP->GV); CHKERRQ(ierr);
207*a7e14dcfSSatish Balay 
208*a7e14dcfSSatish Balay       ierr = ComputePseudoGrad_OWLQN(tao->solution,lmP->GV,lmP->lambda);CHKERRQ(ierr);
209*a7e14dcfSSatish Balay 
210*a7e14dcfSSatish Balay       switch(stepType) {
211*a7e14dcfSSatish Balay       case OWLQN_BFGS:
212*a7e14dcfSSatish Balay         /* Failed to obtain acceptable iterate with BFGS step
213*a7e14dcfSSatish Balay 	   Attempt to use the scaled gradient direction */
214*a7e14dcfSSatish Balay 
215*a7e14dcfSSatish Balay         if (f != 0.0) {
216*a7e14dcfSSatish Balay           delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm);
217*a7e14dcfSSatish Balay         }
218*a7e14dcfSSatish Balay         else {
219*a7e14dcfSSatish Balay           delta = 2.0 / (gnorm*gnorm);
220*a7e14dcfSSatish Balay         }
221*a7e14dcfSSatish Balay 	ierr = MatLMVMSetDelta(lmP->M, delta); CHKERRQ(ierr);
222*a7e14dcfSSatish Balay 	ierr = MatLMVMReset(lmP->M); CHKERRQ(ierr);
223*a7e14dcfSSatish Balay 	ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
224*a7e14dcfSSatish Balay 	ierr = MatLMVMSolve(lmP->M, lmP->GV, lmP->D); CHKERRQ(ierr);
225*a7e14dcfSSatish Balay 
226*a7e14dcfSSatish Balay         ierr = ProjDirect_OWLQN(lmP->D,lmP->GV);CHKERRQ(ierr);
227*a7e14dcfSSatish Balay         /* On a reset, the direction cannot be not a number; it is a
228*a7e14dcfSSatish Balay 	   scaled gradient step.  No need to check for this condition.
229*a7e14dcfSSatish Balay 	   info = D->Norm2(&dnorm); CHKERRQ(info);
230*a7e14dcfSSatish Balay 	   if (PetscIsInfOrNanReal(dnorm)) {
231*a7e14dcfSSatish Balay 	   SETERRQ(PETSC_COMM_SELF,1, "Direction generated Not-a-Number");
232*a7e14dcfSSatish Balay 	   }*/
233*a7e14dcfSSatish Balay 
234*a7e14dcfSSatish Balay 	lmP->bfgs = 1;
235*a7e14dcfSSatish Balay 	++lmP->sgrad;
236*a7e14dcfSSatish Balay 	stepType = OWLQN_SCALED_GRADIENT;
237*a7e14dcfSSatish Balay 	break;
238*a7e14dcfSSatish Balay 
239*a7e14dcfSSatish Balay       case OWLQN_SCALED_GRADIENT:
240*a7e14dcfSSatish Balay         /* The scaled gradient step did not produce a new iterate;
241*a7e14dcfSSatish Balay 	   attempt to use the gradient direction.
242*a7e14dcfSSatish Balay 	   Need to make sure we are not using a different diagonal scaling */
243*a7e14dcfSSatish Balay 	ierr = MatLMVMSetDelta(lmP->M, 1.0); CHKERRQ(ierr);
244*a7e14dcfSSatish Balay 	ierr = MatLMVMReset(lmP->M); CHKERRQ(ierr);
245*a7e14dcfSSatish Balay 	ierr = MatLMVMUpdate(lmP->M, tao->solution, tao->gradient); CHKERRQ(ierr);
246*a7e14dcfSSatish Balay 	ierr = MatLMVMSolve(lmP->M, lmP->GV, lmP->D); CHKERRQ(ierr);
247*a7e14dcfSSatish Balay 
248*a7e14dcfSSatish Balay 	ierr = ProjDirect_OWLQN(lmP->D,lmP->GV);CHKERRQ(ierr);
249*a7e14dcfSSatish Balay 
250*a7e14dcfSSatish Balay         lmP->bfgs = 1;
251*a7e14dcfSSatish Balay         ++lmP->grad;
252*a7e14dcfSSatish Balay         stepType = OWLQN_GRADIENT;
253*a7e14dcfSSatish Balay         break;
254*a7e14dcfSSatish Balay       }
255*a7e14dcfSSatish Balay       ierr = VecScale(lmP->D, -1.0); CHKERRQ(ierr);
256*a7e14dcfSSatish Balay 
257*a7e14dcfSSatish Balay 
258*a7e14dcfSSatish Balay       /* Perform the linesearch */
259*a7e14dcfSSatish Balay       ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, lmP->GV, lmP->D, &step, &ls_status); CHKERRQ(ierr);
260*a7e14dcfSSatish Balay       ierr = TaoAddLineSearchCounts(tao); CHKERRQ(ierr);
261*a7e14dcfSSatish Balay     }
262*a7e14dcfSSatish Balay 
263*a7e14dcfSSatish Balay     if ((int)ls_status < 0) {
264*a7e14dcfSSatish Balay       /* Failed to find an improving point*/
265*a7e14dcfSSatish Balay       f = fold;
266*a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Xold, tao->solution); CHKERRQ(ierr);
267*a7e14dcfSSatish Balay       ierr = VecCopy(lmP->Gold, tao->gradient); CHKERRQ(ierr);
268*a7e14dcfSSatish Balay       ierr = VecCopy(tao->gradient, lmP->GV); CHKERRQ(ierr);
269*a7e14dcfSSatish Balay       step = 0.0;
270*a7e14dcfSSatish Balay     }
271*a7e14dcfSSatish Balay     else {
272*a7e14dcfSSatish Balay       /* a little hack here, because that gv is used to store g */
273*a7e14dcfSSatish Balay       ierr = VecCopy(lmP->GV, tao->gradient); CHKERRQ(ierr);
274*a7e14dcfSSatish Balay     }
275*a7e14dcfSSatish Balay 
276*a7e14dcfSSatish Balay     ierr = ComputePseudoGrad_OWLQN(tao->solution,lmP->GV,lmP->lambda);CHKERRQ(ierr);
277*a7e14dcfSSatish Balay 
278*a7e14dcfSSatish Balay     /* Check for termination */
279*a7e14dcfSSatish Balay 
280*a7e14dcfSSatish Balay     ierr = VecNorm(lmP->GV,NORM_2,&gnorm); CHKERRQ(ierr);
281*a7e14dcfSSatish Balay 
282*a7e14dcfSSatish Balay     iter++;
283*a7e14dcfSSatish Balay     ierr = TaoMonitor(tao,iter,f,gnorm,0.0,step,&reason); CHKERRQ(ierr);
284*a7e14dcfSSatish Balay 
285*a7e14dcfSSatish Balay     if ((int)ls_status < 0)
286*a7e14dcfSSatish Balay       break;
287*a7e14dcfSSatish Balay   }
288*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
289*a7e14dcfSSatish Balay }
290*a7e14dcfSSatish Balay 
291*a7e14dcfSSatish Balay 
292*a7e14dcfSSatish Balay #undef __FUNCT__
293*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetUp_OWLQN"
294*a7e14dcfSSatish Balay static PetscErrorCode TaoSetUp_OWLQN(TaoSolver tao)
295*a7e14dcfSSatish Balay {
296*a7e14dcfSSatish Balay   TAO_OWLQN *lmP = (TAO_OWLQN *)tao->data;
297*a7e14dcfSSatish Balay   PetscInt n,N;
298*a7e14dcfSSatish Balay   PetscErrorCode ierr;
299*a7e14dcfSSatish Balay 
300*a7e14dcfSSatish Balay   PetscFunctionBegin;
301*a7e14dcfSSatish Balay   /* Existence of tao->solution checked in TaoSolverSetUp() */
302*a7e14dcfSSatish Balay   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient); CHKERRQ(ierr);  }
303*a7e14dcfSSatish Balay   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection); CHKERRQ(ierr);  }
304*a7e14dcfSSatish Balay   if (!lmP->D) {ierr = VecDuplicate(tao->solution,&lmP->D); CHKERRQ(ierr);  }
305*a7e14dcfSSatish Balay   if (!lmP->GV) {ierr = VecDuplicate(tao->solution,&lmP->GV); CHKERRQ(ierr);  }
306*a7e14dcfSSatish Balay   if (!lmP->Xold) {ierr = VecDuplicate(tao->solution,&lmP->Xold); CHKERRQ(ierr);  }
307*a7e14dcfSSatish Balay   if (!lmP->Gold) {ierr = VecDuplicate(tao->solution,&lmP->Gold); CHKERRQ(ierr);  }
308*a7e14dcfSSatish Balay 
309*a7e14dcfSSatish Balay   /* Create matrix for the limited memory approximation */
310*a7e14dcfSSatish Balay   ierr = VecGetLocalSize(tao->solution,&n); CHKERRQ(ierr);
311*a7e14dcfSSatish Balay   ierr = VecGetSize(tao->solution,&N); CHKERRQ(ierr);
312*a7e14dcfSSatish Balay   ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&lmP->M); CHKERRQ(ierr);
313*a7e14dcfSSatish Balay   ierr = MatLMVMAllocateVectors(lmP->M,tao->solution); CHKERRQ(ierr);
314*a7e14dcfSSatish Balay 
315*a7e14dcfSSatish Balay 
316*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
317*a7e14dcfSSatish Balay }
318*a7e14dcfSSatish Balay 
319*a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
320*a7e14dcfSSatish Balay #undef __FUNCT__
321*a7e14dcfSSatish Balay #define __FUNCT__ "TaoDestroy_OWLQN"
322*a7e14dcfSSatish Balay static PetscErrorCode TaoDestroy_OWLQN(TaoSolver tao)
323*a7e14dcfSSatish Balay {
324*a7e14dcfSSatish Balay 
325*a7e14dcfSSatish Balay   TAO_OWLQN *lmP = (TAO_OWLQN *)tao->data;
326*a7e14dcfSSatish Balay   PetscErrorCode ierr;
327*a7e14dcfSSatish Balay 
328*a7e14dcfSSatish Balay   PetscFunctionBegin;
329*a7e14dcfSSatish Balay   if (tao->setupcalled) {
330*a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Xold); CHKERRQ(ierr);
331*a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->Gold); CHKERRQ(ierr);
332*a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->D); CHKERRQ(ierr);
333*a7e14dcfSSatish Balay     ierr = MatDestroy(&lmP->M); CHKERRQ(ierr);
334*a7e14dcfSSatish Balay     ierr = VecDestroy(&lmP->GV);CHKERRQ(ierr);
335*a7e14dcfSSatish Balay   }
336*a7e14dcfSSatish Balay   ierr = PetscFree(tao->data); CHKERRQ(ierr);
337*a7e14dcfSSatish Balay   tao->data = PETSC_NULL;
338*a7e14dcfSSatish Balay 
339*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
340*a7e14dcfSSatish Balay }
341*a7e14dcfSSatish Balay 
342*a7e14dcfSSatish Balay /*------------------------------------------------------------*/
343*a7e14dcfSSatish Balay #undef __FUNCT__
344*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetFromOptions_OWLQN"
345*a7e14dcfSSatish Balay static PetscErrorCode TaoSetFromOptions_OWLQN(TaoSolver tao)
346*a7e14dcfSSatish Balay {
347*a7e14dcfSSatish Balay 
348*a7e14dcfSSatish Balay   TAO_OWLQN *lmP = (TAO_OWLQN *)tao->data;
349*a7e14dcfSSatish Balay   PetscBool flg;
350*a7e14dcfSSatish Balay   PetscErrorCode ierr;
351*a7e14dcfSSatish Balay 
352*a7e14dcfSSatish Balay   PetscFunctionBegin;
353*a7e14dcfSSatish Balay   ierr = PetscOptionsHead("Orthant-Wise Limited-memory method for Quasi-Newton unconstrained optimization"); CHKERRQ(ierr);
354*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_owlqn_lambda", "regulariser weight","", 100,&lmP->lambda,&flg);  CHKERRQ(ierr);
355*a7e14dcfSSatish Balay   ierr = PetscOptionsTail(); CHKERRQ(ierr);
356*a7e14dcfSSatish Balay   ierr = TaoLineSearchSetFromOptions(tao->linesearch); CHKERRQ(ierr);
357*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
358*a7e14dcfSSatish Balay }
359*a7e14dcfSSatish Balay 
360*a7e14dcfSSatish Balay /*------------------------------------------------------------*/
361*a7e14dcfSSatish Balay #undef __FUNCT__
362*a7e14dcfSSatish Balay #define __FUNCT__ "TaoView_OWLQN"
363*a7e14dcfSSatish Balay static PetscErrorCode TaoView_OWLQN(TaoSolver tao, PetscViewer viewer)
364*a7e14dcfSSatish Balay {
365*a7e14dcfSSatish Balay 
366*a7e14dcfSSatish Balay     TAO_OWLQN *lm = (TAO_OWLQN *)tao->data;
367*a7e14dcfSSatish Balay     PetscBool isascii;
368*a7e14dcfSSatish Balay     PetscErrorCode ierr;
369*a7e14dcfSSatish Balay 
370*a7e14dcfSSatish Balay 
371*a7e14dcfSSatish Balay     PetscFunctionBegin;
372*a7e14dcfSSatish Balay     ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii); CHKERRQ(ierr);
373*a7e14dcfSSatish Balay     if (isascii) {
374*a7e14dcfSSatish Balay 
375*a7e14dcfSSatish Balay         ierr = PetscViewerASCIIPushTab(viewer); CHKERRQ(ierr);
376*a7e14dcfSSatish Balay 	ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %d\n", lm->bfgs); CHKERRQ(ierr);
377*a7e14dcfSSatish Balay 	ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %d\n", lm->sgrad); CHKERRQ(ierr);
378*a7e14dcfSSatish Balay 	ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %d\n", lm->grad); CHKERRQ(ierr);
379*a7e14dcfSSatish Balay         ierr = PetscViewerASCIIPopTab(viewer); CHKERRQ(ierr);
380*a7e14dcfSSatish Balay     } else {
381*a7e14dcfSSatish Balay       SETERRQ1(((PetscObject)tao)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for TAO OWLQN",((PetscObject)viewer)->type_name);
382*a7e14dcfSSatish Balay     }
383*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
384*a7e14dcfSSatish Balay }
385*a7e14dcfSSatish Balay 
386*a7e14dcfSSatish Balay /* ---------------------------------------------------------- */
387*a7e14dcfSSatish Balay 
388*a7e14dcfSSatish Balay EXTERN_C_BEGIN
389*a7e14dcfSSatish Balay #undef __FUNCT__
390*a7e14dcfSSatish Balay #define __FUNCT__ "TaoCreate_OWLQN"
391*a7e14dcfSSatish Balay PetscErrorCode TaoCreate_OWLQN(TaoSolver tao)
392*a7e14dcfSSatish Balay {
393*a7e14dcfSSatish Balay 
394*a7e14dcfSSatish Balay   TAO_OWLQN *lmP;
395*a7e14dcfSSatish Balay   const char *owarmijo_type = TAOLINESEARCH_OWARMIJO;
396*a7e14dcfSSatish Balay   PetscErrorCode ierr;
397*a7e14dcfSSatish Balay 
398*a7e14dcfSSatish Balay   PetscFunctionBegin;
399*a7e14dcfSSatish Balay   tao->ops->setup = TaoSetUp_OWLQN;
400*a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_OWLQN;
401*a7e14dcfSSatish Balay   tao->ops->view = TaoView_OWLQN;
402*a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_OWLQN;
403*a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_OWLQN;
404*a7e14dcfSSatish Balay 
405*a7e14dcfSSatish Balay   ierr = PetscNewLog(tao,TAO_OWLQN, &lmP); CHKERRQ(ierr);
406*a7e14dcfSSatish Balay   lmP->D = 0;
407*a7e14dcfSSatish Balay   lmP->M = 0;
408*a7e14dcfSSatish Balay   lmP->GV = 0;
409*a7e14dcfSSatish Balay   lmP->Xold = 0;
410*a7e14dcfSSatish Balay   lmP->Gold = 0;
411*a7e14dcfSSatish Balay   lmP->lambda = 1.0;
412*a7e14dcfSSatish Balay 
413*a7e14dcfSSatish Balay   tao->data = (void*)lmP;
414*a7e14dcfSSatish Balay   tao->max_it = 2000;
415*a7e14dcfSSatish Balay   tao->max_funcs = 4000;
416*a7e14dcfSSatish Balay   tao->fatol = 1e-4;
417*a7e14dcfSSatish Balay   tao->frtol = 1e-4;
418*a7e14dcfSSatish Balay 
419*a7e14dcfSSatish Balay   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch); CHKERRQ(ierr);
420*a7e14dcfSSatish Balay   ierr = TaoLineSearchSetType(tao->linesearch,owarmijo_type); CHKERRQ(ierr);
421*a7e14dcfSSatish Balay   ierr = TaoLineSearchUseTaoSolverRoutines(tao->linesearch,tao); CHKERRQ(ierr);
422*a7e14dcfSSatish Balay 
423*a7e14dcfSSatish Balay 
424*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
425*a7e14dcfSSatish Balay }
426*a7e14dcfSSatish Balay EXTERN_C_END
427*a7e14dcfSSatish Balay 
428