xref: /petsc/src/tao/bound/impls/bncg/bncg.c (revision ac9112b8da24494b321770155bf80866e3ee4a12)
1*ac9112b8SAlp Dener #include <petsctaolinesearch.h>
2*ac9112b8SAlp Dener #include <../src/tao/bound/impls/bncg/bncg.h>
3*ac9112b8SAlp Dener 
4*ac9112b8SAlp Dener #define CG_FletcherReeves       0
5*ac9112b8SAlp Dener #define CG_PolakRibiere         1
6*ac9112b8SAlp Dener #define CG_PolakRibierePlus     2
7*ac9112b8SAlp Dener #define CG_HestenesStiefel      3
8*ac9112b8SAlp Dener #define CG_DaiYuan              4
9*ac9112b8SAlp Dener #define CG_Types                5
10*ac9112b8SAlp Dener 
11*ac9112b8SAlp Dener static const char *CG_Table[64] = {"fr", "pr", "prp", "hs", "dy"};
12*ac9112b8SAlp Dener 
13*ac9112b8SAlp Dener PetscErrorCode TaoBNCGResetStepForNewInactives(Tao tao, Vec step)
14*ac9112b8SAlp Dener {
15*ac9112b8SAlp Dener   TAO_BNCG                     *cg = (TAO_BNCG*)tao->data;
16*ac9112b8SAlp Dener   PetscErrorCode               ierr;
17*ac9112b8SAlp Dener   const PetscScalar            *xl, *xo, *xn, *xu, *gn, *go;
18*ac9112b8SAlp Dener   PetscInt                     size, i;
19*ac9112b8SAlp Dener   PetscScalar                  *s;
20*ac9112b8SAlp Dener 
21*ac9112b8SAlp Dener   PetscFunctionBegin;
22*ac9112b8SAlp Dener   ierr = VecGetLocalSize(tao->solution, &size);CHKERRQ(ierr);
23*ac9112b8SAlp Dener   ierr = VecGetArrayRead(cg->unprojected_gradient_old, &go);CHKERRQ(ierr);
24*ac9112b8SAlp Dener   ierr = VecGetArrayRead(cg->unprojected_gradient, &gn);CHKERRQ(ierr);
25*ac9112b8SAlp Dener   ierr = VecGetArrayRead(cg->X_old, &xo);CHKERRQ(ierr);
26*ac9112b8SAlp Dener   ierr = VecGetArrayRead(tao->solution, &xn);CHKERRQ(ierr);
27*ac9112b8SAlp Dener   ierr = VecGetArrayRead(tao->XL, &xl);CHKERRQ(ierr);
28*ac9112b8SAlp Dener   ierr = VecGetArrayRead(tao->XU, &xu);CHKERRQ(ierr);
29*ac9112b8SAlp Dener   ierr = VecGetArray(step, &s);CHKERRQ(ierr);
30*ac9112b8SAlp Dener   for (i=0; i<size; i++) {
31*ac9112b8SAlp Dener     if (xl[i] == xu[i]) {
32*ac9112b8SAlp Dener       s[i] = 0.0;
33*ac9112b8SAlp Dener     } else {
34*ac9112b8SAlp Dener       if (xl[i] > PETSC_NINFINITY) {
35*ac9112b8SAlp Dener         if ((xn[i] == xl[i] && gn[i] < 0.0) && (xo[i] == xl[i] && go[i] >= 0.0)) {
36*ac9112b8SAlp Dener           s[i] = -gn[i];
37*ac9112b8SAlp Dener         }
38*ac9112b8SAlp Dener       }
39*ac9112b8SAlp Dener       if (xu[i] < PETSC_NINFINITY) {
40*ac9112b8SAlp Dener         if ((xn[i] == xu[i] && gn[i] > 0.0) && (xo[i] == xu[i] && go[i] <= 0.0)) {
41*ac9112b8SAlp Dener           s[i] = -gn[i];
42*ac9112b8SAlp Dener         }
43*ac9112b8SAlp Dener       }
44*ac9112b8SAlp Dener     }
45*ac9112b8SAlp Dener   }
46*ac9112b8SAlp Dener   ierr = VecRestoreArrayRead(cg->unprojected_gradient_old, &go);CHKERRQ(ierr);
47*ac9112b8SAlp Dener   ierr = VecRestoreArrayRead(cg->unprojected_gradient, &gn);CHKERRQ(ierr);
48*ac9112b8SAlp Dener   ierr = VecRestoreArrayRead(cg->X_old, &xo);CHKERRQ(ierr);
49*ac9112b8SAlp Dener   ierr = VecRestoreArrayRead(tao->solution, &xn);CHKERRQ(ierr);
50*ac9112b8SAlp Dener   ierr = VecRestoreArrayRead(tao->XL, &xl);CHKERRQ(ierr);
51*ac9112b8SAlp Dener   ierr = VecRestoreArrayRead(tao->XU, &xu);CHKERRQ(ierr);
52*ac9112b8SAlp Dener   ierr = VecRestoreArray(step, &s);CHKERRQ(ierr);
53*ac9112b8SAlp Dener   PetscFunctionReturn(0);
54*ac9112b8SAlp Dener }
55*ac9112b8SAlp Dener 
56*ac9112b8SAlp Dener static PetscErrorCode TaoSolve_BNCG(Tao tao)
57*ac9112b8SAlp Dener {
58*ac9112b8SAlp Dener   TAO_BNCG                     *cg = (TAO_BNCG*)tao->data;
59*ac9112b8SAlp Dener   PetscErrorCode               ierr;
60*ac9112b8SAlp Dener   TaoLineSearchConvergedReason ls_status = TAOLINESEARCH_CONTINUE_ITERATING;
61*ac9112b8SAlp Dener   PetscReal                    step=1.0,f,gnorm,gnorm2,delta,gd,ginner,beta,dnorm;
62*ac9112b8SAlp Dener   PetscReal                    gd_old,gnorm2_old,f_old;
63*ac9112b8SAlp Dener   PetscBool                    cg_restart;
64*ac9112b8SAlp Dener 
65*ac9112b8SAlp Dener   PetscFunctionBegin;
66*ac9112b8SAlp Dener   /*   Project the current point onto the feasible set */
67*ac9112b8SAlp Dener   ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr);
68*ac9112b8SAlp Dener   ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr);
69*ac9112b8SAlp Dener 
70*ac9112b8SAlp Dener   /* Project the initial point onto the feasible region */
71*ac9112b8SAlp Dener   ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr);
72*ac9112b8SAlp Dener 
73*ac9112b8SAlp Dener   /*  Compute the objective function and criteria */
74*ac9112b8SAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, cg->unprojected_gradient);CHKERRQ(ierr);
75*ac9112b8SAlp Dener   ierr = VecNorm(cg->unprojected_gradient,NORM_2,&gnorm);CHKERRQ(ierr);
76*ac9112b8SAlp Dener   if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
77*ac9112b8SAlp Dener 
78*ac9112b8SAlp Dener   /* Project the gradient and calculate the norm */
79*ac9112b8SAlp Dener   ierr = VecBoundGradientProjection(cg->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
80*ac9112b8SAlp Dener   ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr);
81*ac9112b8SAlp Dener   gnorm2 = gnorm*gnorm;
82*ac9112b8SAlp Dener 
83*ac9112b8SAlp Dener   /* Convergence check */
84*ac9112b8SAlp Dener   tao->reason = TAO_CONTINUE_ITERATING;
85*ac9112b8SAlp Dener   ierr = TaoLogConvergenceHistory(tao, f, gnorm, 0.0, tao->ksp_its);CHKERRQ(ierr);
86*ac9112b8SAlp Dener   ierr = TaoMonitor(tao, tao->niter, f, gnorm, 0.0, step);CHKERRQ(ierr);
87*ac9112b8SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
88*ac9112b8SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
89*ac9112b8SAlp Dener 
90*ac9112b8SAlp Dener   /* Start optimization iterations */
91*ac9112b8SAlp Dener   f_old = f;
92*ac9112b8SAlp Dener   gnorm2_old = gnorm2;
93*ac9112b8SAlp Dener   ierr = VecCopy(tao->solution, cg->X_old);CHKERRQ(ierr);
94*ac9112b8SAlp Dener   ierr = VecCopy(tao->gradient, cg->G_old);CHKERRQ(ierr);
95*ac9112b8SAlp Dener   ierr = VecCopy(cg->unprojected_gradient, cg->unprojected_gradient_old);CHKERRQ(ierr);
96*ac9112b8SAlp Dener   tao->niter = cg->ls_fails = cg->broken_ortho = cg->descent_error = 0;
97*ac9112b8SAlp Dener   cg->resets = -1;
98*ac9112b8SAlp Dener   while (tao->reason == TAO_CONTINUE_ITERATING) {
99*ac9112b8SAlp Dener     /* Check restart conditions for using steepest descent */
100*ac9112b8SAlp Dener     cg_restart = PETSC_FALSE;
101*ac9112b8SAlp Dener     ierr = VecDot(tao->gradient, cg->G_old, &ginner);CHKERRQ(ierr);
102*ac9112b8SAlp Dener     if (tao->niter == 0) {
103*ac9112b8SAlp Dener       /* 1) First iteration */
104*ac9112b8SAlp Dener       cg_restart = PETSC_TRUE;
105*ac9112b8SAlp Dener     } else if (PetscAbsScalar(ginner) >= cg->eta * gnorm2) {
106*ac9112b8SAlp Dener       /* 2) Gradients are far from orthogonal */
107*ac9112b8SAlp Dener       cg_restart = PETSC_TRUE;
108*ac9112b8SAlp Dener       cg->broken_ortho++;
109*ac9112b8SAlp Dener     }
110*ac9112b8SAlp Dener 
111*ac9112b8SAlp Dener     /* Compute CG step */
112*ac9112b8SAlp Dener     if (cg_restart) {
113*ac9112b8SAlp Dener       beta = 0.0;
114*ac9112b8SAlp Dener       cg->resets++;
115*ac9112b8SAlp Dener     } else {
116*ac9112b8SAlp Dener       switch (cg->cg_type) {
117*ac9112b8SAlp Dener       case CG_FletcherReeves:
118*ac9112b8SAlp Dener         beta = gnorm2 / gnorm2_old;
119*ac9112b8SAlp Dener         break;
120*ac9112b8SAlp Dener 
121*ac9112b8SAlp Dener       case CG_PolakRibiere:
122*ac9112b8SAlp Dener         beta = (gnorm2 - ginner) / gnorm2_old;
123*ac9112b8SAlp Dener         break;
124*ac9112b8SAlp Dener 
125*ac9112b8SAlp Dener       case CG_PolakRibierePlus:
126*ac9112b8SAlp Dener         beta = PetscMax((gnorm2-ginner)/gnorm2_old, 0.0);
127*ac9112b8SAlp Dener         break;
128*ac9112b8SAlp Dener 
129*ac9112b8SAlp Dener       case CG_HestenesStiefel:
130*ac9112b8SAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr);
131*ac9112b8SAlp Dener         ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr);
132*ac9112b8SAlp Dener         beta = (gnorm2 - ginner) / (gd - gd_old);
133*ac9112b8SAlp Dener         break;
134*ac9112b8SAlp Dener 
135*ac9112b8SAlp Dener       case CG_DaiYuan:
136*ac9112b8SAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr);
137*ac9112b8SAlp Dener         ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr);
138*ac9112b8SAlp Dener         beta = gnorm2 / (gd - gd_old);
139*ac9112b8SAlp Dener         break;
140*ac9112b8SAlp Dener 
141*ac9112b8SAlp Dener       default:
142*ac9112b8SAlp Dener         beta = 0.0;
143*ac9112b8SAlp Dener         break;
144*ac9112b8SAlp Dener       }
145*ac9112b8SAlp Dener     }
146*ac9112b8SAlp Dener 
147*ac9112b8SAlp Dener     /*  Compute the direction d=-g + beta*d */
148*ac9112b8SAlp Dener     ierr = VecAXPBY(tao->stepdirection, -1.0, beta, tao->gradient);CHKERRQ(ierr);
149*ac9112b8SAlp Dener     ierr = TaoBNCGResetStepForNewInactives(tao, tao->stepdirection);CHKERRQ(ierr);
150*ac9112b8SAlp Dener 
151*ac9112b8SAlp Dener     /* Verify that this is a descent direction */
152*ac9112b8SAlp Dener     ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr);
153*ac9112b8SAlp Dener     ierr = VecNorm(tao->stepdirection, NORM_2, &dnorm);
154*ac9112b8SAlp Dener     if (gd > -cg->rho*PetscPowReal(dnorm, cg->pow)) {
155*ac9112b8SAlp Dener       /* Not a descent direction, so we reset back to projected gradient descent */
156*ac9112b8SAlp Dener       ierr = VecAXPBY(tao->stepdirection, -1.0, 0.0, tao->gradient);CHKERRQ(ierr);
157*ac9112b8SAlp Dener       cg->resets++;
158*ac9112b8SAlp Dener       cg->descent_error++;
159*ac9112b8SAlp Dener     }
160*ac9112b8SAlp Dener 
161*ac9112b8SAlp Dener     /*  update initial steplength choice */
162*ac9112b8SAlp Dener     delta = 1.0;
163*ac9112b8SAlp Dener     delta = PetscMax(delta, cg->delta_min);
164*ac9112b8SAlp Dener     delta = PetscMin(delta, cg->delta_max);
165*ac9112b8SAlp Dener 
166*ac9112b8SAlp Dener     /* Store solution and gradient info before it changes */
167*ac9112b8SAlp Dener     ierr = VecCopy(tao->solution, cg->X_old);CHKERRQ(ierr);
168*ac9112b8SAlp Dener     ierr = VecCopy(tao->gradient, cg->G_old);CHKERRQ(ierr);
169*ac9112b8SAlp Dener     ierr = VecCopy(cg->unprojected_gradient, cg->unprojected_gradient_old);CHKERRQ(ierr);
170*ac9112b8SAlp Dener     gnorm2_old = gnorm2;
171*ac9112b8SAlp Dener     f_old = f;
172*ac9112b8SAlp Dener 
173*ac9112b8SAlp Dener     /* Perform bounded line search */
174*ac9112b8SAlp Dener     ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,delta);CHKERRQ(ierr);
175*ac9112b8SAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr);
176*ac9112b8SAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
177*ac9112b8SAlp Dener 
178*ac9112b8SAlp Dener     /*  Check linesearch failure */
179*ac9112b8SAlp Dener     if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER) {
180*ac9112b8SAlp Dener       cg->ls_fails++;
181*ac9112b8SAlp Dener       /* Restore previous point */
182*ac9112b8SAlp Dener       gnorm2 = gnorm2_old;
183*ac9112b8SAlp Dener       f = f_old;
184*ac9112b8SAlp Dener       ierr = VecCopy(cg->X_old, tao->solution);CHKERRQ(ierr);
185*ac9112b8SAlp Dener       ierr = VecCopy(cg->G_old, tao->gradient);CHKERRQ(ierr);
186*ac9112b8SAlp Dener       ierr = VecCopy(cg->unprojected_gradient_old, cg->unprojected_gradient);CHKERRQ(ierr);
187*ac9112b8SAlp Dener 
188*ac9112b8SAlp Dener       /* Fall back on the unscaled gradient step */
189*ac9112b8SAlp Dener       delta = 1.0;
190*ac9112b8SAlp Dener       ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr);
191*ac9112b8SAlp Dener       ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
192*ac9112b8SAlp Dener 
193*ac9112b8SAlp Dener       ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,delta);CHKERRQ(ierr);
194*ac9112b8SAlp Dener       ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr);
195*ac9112b8SAlp Dener       ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
196*ac9112b8SAlp Dener 
197*ac9112b8SAlp Dener       if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER){
198*ac9112b8SAlp Dener         cg->ls_fails++;
199*ac9112b8SAlp Dener         /* Restore previous point */
200*ac9112b8SAlp Dener         gnorm2 = gnorm2_old;
201*ac9112b8SAlp Dener         f = f_old;
202*ac9112b8SAlp Dener         ierr = VecCopy(cg->X_old, tao->solution);CHKERRQ(ierr);
203*ac9112b8SAlp Dener         ierr = VecCopy(cg->G_old, tao->gradient);CHKERRQ(ierr);
204*ac9112b8SAlp Dener         ierr = VecCopy(cg->unprojected_gradient_old, cg->unprojected_gradient);CHKERRQ(ierr);
205*ac9112b8SAlp Dener 
206*ac9112b8SAlp Dener         /* Nothing left to do but fail out of the optimization */
207*ac9112b8SAlp Dener         step = 0.0;
208*ac9112b8SAlp Dener         tao->reason = TAO_DIVERGED_LS_FAILURE;
209*ac9112b8SAlp Dener       }
210*ac9112b8SAlp Dener     }
211*ac9112b8SAlp Dener 
212*ac9112b8SAlp Dener     /* Compute the projected gradient and its norm */
213*ac9112b8SAlp Dener     ierr = VecBoundGradientProjection(cg->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
214*ac9112b8SAlp Dener     ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr);
215*ac9112b8SAlp Dener     gnorm2 = gnorm*gnorm;
216*ac9112b8SAlp Dener 
217*ac9112b8SAlp Dener     /* Convergence test */
218*ac9112b8SAlp Dener     tao->niter++;
219*ac9112b8SAlp Dener     ierr = TaoLogConvergenceHistory(tao, f, gnorm, 0.0, tao->ksp_its);CHKERRQ(ierr);
220*ac9112b8SAlp Dener     ierr = TaoMonitor(tao, tao->niter, f, gnorm, 0.0, step);CHKERRQ(ierr);
221*ac9112b8SAlp Dener     ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
222*ac9112b8SAlp Dener   }
223*ac9112b8SAlp Dener   PetscFunctionReturn(0);
224*ac9112b8SAlp Dener }
225*ac9112b8SAlp Dener 
226*ac9112b8SAlp Dener static PetscErrorCode TaoSetUp_BNCG(Tao tao)
227*ac9112b8SAlp Dener {
228*ac9112b8SAlp Dener   TAO_BNCG         *cg = (TAO_BNCG*)tao->data;
229*ac9112b8SAlp Dener   PetscErrorCode ierr;
230*ac9112b8SAlp Dener 
231*ac9112b8SAlp Dener   PetscFunctionBegin;
232*ac9112b8SAlp Dener   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);}
233*ac9112b8SAlp Dener   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr); }
234*ac9112b8SAlp Dener   if (!cg->X_old) {ierr = VecDuplicate(tao->solution,&cg->X_old);CHKERRQ(ierr);}
235*ac9112b8SAlp Dener   if (!cg->G_old) {ierr = VecDuplicate(tao->gradient,&cg->G_old);CHKERRQ(ierr); }
236*ac9112b8SAlp Dener   if (!cg->unprojected_gradient) {ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient);CHKERRQ(ierr);}
237*ac9112b8SAlp Dener   if (!cg->unprojected_gradient_old) {ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient_old);CHKERRQ(ierr);}
238*ac9112b8SAlp Dener   PetscFunctionReturn(0);
239*ac9112b8SAlp Dener }
240*ac9112b8SAlp Dener 
241*ac9112b8SAlp Dener static PetscErrorCode TaoDestroy_BNCG(Tao tao)
242*ac9112b8SAlp Dener {
243*ac9112b8SAlp Dener   TAO_BNCG       *cg = (TAO_BNCG*) tao->data;
244*ac9112b8SAlp Dener   PetscErrorCode ierr;
245*ac9112b8SAlp Dener 
246*ac9112b8SAlp Dener   PetscFunctionBegin;
247*ac9112b8SAlp Dener   if (tao->setupcalled) {
248*ac9112b8SAlp Dener     ierr = VecDestroy(&cg->X_old);CHKERRQ(ierr);
249*ac9112b8SAlp Dener     ierr = VecDestroy(&cg->G_old);CHKERRQ(ierr);
250*ac9112b8SAlp Dener     ierr = VecDestroy(&cg->unprojected_gradient);CHKERRQ(ierr);
251*ac9112b8SAlp Dener     ierr = VecDestroy(&cg->unprojected_gradient_old);CHKERRQ(ierr);
252*ac9112b8SAlp Dener   }
253*ac9112b8SAlp Dener   ierr = TaoLineSearchDestroy(&tao->linesearch);CHKERRQ(ierr);
254*ac9112b8SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
255*ac9112b8SAlp Dener   PetscFunctionReturn(0);
256*ac9112b8SAlp Dener }
257*ac9112b8SAlp Dener 
258*ac9112b8SAlp Dener static PetscErrorCode TaoSetFromOptions_BNCG(PetscOptionItems *PetscOptionsObject,Tao tao)
259*ac9112b8SAlp Dener  {
260*ac9112b8SAlp Dener     TAO_BNCG       *cg = (TAO_BNCG*)tao->data;
261*ac9112b8SAlp Dener     PetscErrorCode ierr;
262*ac9112b8SAlp Dener 
263*ac9112b8SAlp Dener     PetscFunctionBegin;
264*ac9112b8SAlp Dener     ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
265*ac9112b8SAlp Dener     ierr = PetscOptionsHead(PetscOptionsObject,"Nonlinear Conjugate Gradient method for unconstrained optimization");CHKERRQ(ierr);
266*ac9112b8SAlp Dener     ierr = PetscOptionsReal("-tao_BNCG_eta","restart tolerance", "", cg->eta,&cg->eta,NULL);CHKERRQ(ierr);
267*ac9112b8SAlp Dener     ierr = PetscOptionsReal("-tao_BNCG_rho","descent direction tolerance", "", cg->rho,&cg->rho,NULL);CHKERRQ(ierr);
268*ac9112b8SAlp Dener     ierr = PetscOptionsReal("-tao_BNCG_pow","descent direction exponent", "", cg->pow,&cg->pow,NULL);CHKERRQ(ierr);
269*ac9112b8SAlp Dener     ierr = PetscOptionsEList("-tao_BNCG_type","cg formula", "", CG_Table, CG_Types, CG_Table[cg->cg_type], &cg->cg_type,NULL);CHKERRQ(ierr);
270*ac9112b8SAlp Dener     ierr = PetscOptionsReal("-tao_BNCG_delta_min","minimum delta value", "", cg->delta_min,&cg->delta_min,NULL);CHKERRQ(ierr);
271*ac9112b8SAlp Dener     ierr = PetscOptionsReal("-tao_BNCG_delta_max","maximum delta value", "", cg->delta_max,&cg->delta_max,NULL);CHKERRQ(ierr);
272*ac9112b8SAlp Dener    ierr = PetscOptionsTail();CHKERRQ(ierr);
273*ac9112b8SAlp Dener    PetscFunctionReturn(0);
274*ac9112b8SAlp Dener }
275*ac9112b8SAlp Dener 
276*ac9112b8SAlp Dener static PetscErrorCode TaoView_BNCG(Tao tao, PetscViewer viewer)
277*ac9112b8SAlp Dener {
278*ac9112b8SAlp Dener   PetscBool      isascii;
279*ac9112b8SAlp Dener   TAO_BNCG       *cg = (TAO_BNCG*)tao->data;
280*ac9112b8SAlp Dener   PetscErrorCode ierr;
281*ac9112b8SAlp Dener 
282*ac9112b8SAlp Dener   PetscFunctionBegin;
283*ac9112b8SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr);
284*ac9112b8SAlp Dener   if (isascii) {
285*ac9112b8SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
286*ac9112b8SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG Type: %s\n", CG_Table[cg->cg_type]);CHKERRQ(ierr);
287*ac9112b8SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Resets: %i\n", cg->resets);CHKERRQ(ierr);
288*ac9112b8SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  Broken ortho: %i\n", cg->broken_ortho);CHKERRQ(ierr);
289*ac9112b8SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  Not a descent dir.: %i\n", cg->descent_error);CHKERRQ(ierr);
290*ac9112b8SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Line search fails: %i\n", cg->ls_fails);CHKERRQ(ierr);
291*ac9112b8SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
292*ac9112b8SAlp Dener   }
293*ac9112b8SAlp Dener   PetscFunctionReturn(0);
294*ac9112b8SAlp Dener }
295*ac9112b8SAlp Dener 
296*ac9112b8SAlp Dener /*MC
297*ac9112b8SAlp Dener      TAOBNCG -   Bound-constrained Nonlinear Conjugate Gradient method.
298*ac9112b8SAlp Dener 
299*ac9112b8SAlp Dener    Options Database Keys:
300*ac9112b8SAlp Dener +      -tao_BNCG_eta <r> - restart tolerance
301*ac9112b8SAlp Dener .      -tao_BNCG_type <taocg_type> - cg formula
302*ac9112b8SAlp Dener .      -tao_BNCG_delta_min <r> - minimum delta value
303*ac9112b8SAlp Dener -      -tao_BNCG_delta_max <r> - maximum delta value
304*ac9112b8SAlp Dener 
305*ac9112b8SAlp Dener   Notes:
306*ac9112b8SAlp Dener      CG formulas are:
307*ac9112b8SAlp Dener          "fr" - Fletcher-Reeves
308*ac9112b8SAlp Dener          "pr" - Polak-Ribiere
309*ac9112b8SAlp Dener          "prp" - Polak-Ribiere-Plus
310*ac9112b8SAlp Dener          "hs" - Hestenes-Steifel
311*ac9112b8SAlp Dener          "dy" - Dai-Yuan
312*ac9112b8SAlp Dener   Level: beginner
313*ac9112b8SAlp Dener M*/
314*ac9112b8SAlp Dener 
315*ac9112b8SAlp Dener 
316*ac9112b8SAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNCG(Tao tao)
317*ac9112b8SAlp Dener {
318*ac9112b8SAlp Dener   TAO_BNCG       *cg;
319*ac9112b8SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
320*ac9112b8SAlp Dener   PetscErrorCode ierr;
321*ac9112b8SAlp Dener 
322*ac9112b8SAlp Dener   PetscFunctionBegin;
323*ac9112b8SAlp Dener   tao->ops->setup = TaoSetUp_BNCG;
324*ac9112b8SAlp Dener   tao->ops->solve = TaoSolve_BNCG;
325*ac9112b8SAlp Dener   tao->ops->view = TaoView_BNCG;
326*ac9112b8SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNCG;
327*ac9112b8SAlp Dener   tao->ops->destroy = TaoDestroy_BNCG;
328*ac9112b8SAlp Dener 
329*ac9112b8SAlp Dener   /* Override default settings (unless already changed) */
330*ac9112b8SAlp Dener   if (!tao->max_it_changed) tao->max_it = 2000;
331*ac9112b8SAlp Dener   if (!tao->max_funcs_changed) tao->max_funcs = 4000;
332*ac9112b8SAlp Dener 
333*ac9112b8SAlp Dener   /*  Note: nondefault values should be used for nonlinear conjugate gradient  */
334*ac9112b8SAlp Dener   /*  method.  In particular, gtol should be less that 0.5; the value used in  */
335*ac9112b8SAlp Dener   /*  Nocedal and Wright is 0.10.  We use the default values for the  */
336*ac9112b8SAlp Dener   /*  linesearch because it seems to work better. */
337*ac9112b8SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr);
338*ac9112b8SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
339*ac9112b8SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch, morethuente_type);CHKERRQ(ierr);
340*ac9112b8SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch, tao);CHKERRQ(ierr);
341*ac9112b8SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
342*ac9112b8SAlp Dener 
343*ac9112b8SAlp Dener   ierr = PetscNewLog(tao,&cg);CHKERRQ(ierr);
344*ac9112b8SAlp Dener   tao->data = (void*)cg;
345*ac9112b8SAlp Dener   cg->rho = 1e-4;
346*ac9112b8SAlp Dener   cg->pow = 2.1;
347*ac9112b8SAlp Dener   cg->eta = 0.5;
348*ac9112b8SAlp Dener   cg->delta_min = 1e-7;
349*ac9112b8SAlp Dener   cg->delta_max = 100;
350*ac9112b8SAlp Dener   cg->cg_type = CG_DaiYuan;
351*ac9112b8SAlp Dener   PetscFunctionReturn(0);
352*ac9112b8SAlp Dener }
353