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