xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision e031d6f587cbb9f14a00ce52e5e14087387d741b)
1eb910715SAlp Dener #include <petsctaolinesearch.h>
2eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h>
3eb910715SAlp Dener 
4eb910715SAlp Dener #include <petscksp.h>
5eb910715SAlp Dener 
6*e031d6f5SAlp Dener static const char *BNK_PC[64] = {"none", "ahess", "bfgs", "petsc"};
7*e031d6f5SAlp Dener static const char *BFGS_SCALE[64] = {"ahess", "phess", "bfgs"};
8*e031d6f5SAlp Dener static const char *BNK_INIT[64] = {"constant", "direction", "interpolation"};
9*e031d6f5SAlp Dener static const char *BNK_UPDATE[64] = {"step", "reduction", "interpolation"};
10*e031d6f5SAlp Dener static const char *BNK_AS[64] = {"none", "bertsekas"};
11*e031d6f5SAlp Dener 
12*e031d6f5SAlp Dener /*------------------------------------------------------------*/
13*e031d6f5SAlp Dener 
14eb910715SAlp Dener /* Routine for BFGS preconditioner */
15eb910715SAlp Dener 
16eb910715SAlp Dener PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x)
17eb910715SAlp Dener {
18eb910715SAlp Dener   PetscErrorCode ierr;
19eb910715SAlp Dener   Mat            M;
20eb910715SAlp Dener 
21eb910715SAlp Dener   PetscFunctionBegin;
22eb910715SAlp Dener   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
23eb910715SAlp Dener   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
24eb910715SAlp Dener   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
25eb910715SAlp Dener   ierr = PCShellGetContext(pc,(void**)&M);CHKERRQ(ierr);
265e9b73cbSAlp Dener   ierr = MatLMVMSolve(M, b, x);CHKERRQ(ierr);
27eb910715SAlp Dener   PetscFunctionReturn(0);
28eb910715SAlp Dener }
29eb910715SAlp Dener 
30df278d8fSAlp Dener /*------------------------------------------------------------*/
31df278d8fSAlp Dener 
32df278d8fSAlp Dener /* Routine for initializing the KSP solver, the BFGS preconditioner, and the initial trust radius estimation */
33df278d8fSAlp Dener 
34c0f10754SAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType, PetscBool *needH)
35eb910715SAlp Dener {
36eb910715SAlp Dener   PetscErrorCode               ierr;
37eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
38eb910715SAlp Dener   PC                           pc;
39eb910715SAlp Dener 
400a4511e9SAlp Dener   PetscReal                    f_min, ftrial, prered, actred, kappa, sigma;
41eb910715SAlp Dener   PetscReal                    tau, tau_1, tau_2, tau_max, tau_min, max_radius;
42*e031d6f5SAlp Dener   PetscReal                    resnorm, delta;
43eb910715SAlp Dener 
44c0f10754SAlp Dener   PetscInt                     n,N;
45eb910715SAlp Dener 
46eb910715SAlp Dener   PetscInt                     i_max = 5;
47eb910715SAlp Dener   PetscInt                     j_max = 1;
48eb910715SAlp Dener   PetscInt                     i, j;
49eb910715SAlp Dener 
50eb910715SAlp Dener   PetscFunctionBegin;
5128017e9fSAlp Dener   /* Project the current point onto the feasible set */
5228017e9fSAlp Dener   ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr);
53*e031d6f5SAlp Dener   ierr = TaoSetVariableBounds(bnk->bncg, tao->XL, tao->XU);CHKERRQ(ierr);
5428017e9fSAlp Dener   ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr);
5528017e9fSAlp Dener 
5628017e9fSAlp Dener   /* Project the initial point onto the feasible region */
5728017e9fSAlp Dener   ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr);
5828017e9fSAlp Dener 
5928017e9fSAlp Dener   /* Check convergence criteria */
6028017e9fSAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr);
6128017e9fSAlp Dener   ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
6228017e9fSAlp Dener   ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
6328017e9fSAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
6428017e9fSAlp Dener 
65c0f10754SAlp Dener   /* Test the initial point for convergence */
66*e031d6f5SAlp Dener   ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr);
67*e031d6f5SAlp Dener   ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr);
68*e031d6f5SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
69*e031d6f5SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
70c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
71c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
72c0f10754SAlp Dener 
73*e031d6f5SAlp Dener   /* Reset KSP stopping reason counters */
74eb910715SAlp Dener   bnk->ksp_atol = 0;
75eb910715SAlp Dener   bnk->ksp_rtol = 0;
76eb910715SAlp Dener   bnk->ksp_dtol = 0;
77eb910715SAlp Dener   bnk->ksp_ctol = 0;
78eb910715SAlp Dener   bnk->ksp_negc = 0;
79eb910715SAlp Dener   bnk->ksp_iter = 0;
80eb910715SAlp Dener   bnk->ksp_othr = 0;
81eb910715SAlp Dener 
82*e031d6f5SAlp Dener   /* Reset accepted step type counters */
83*e031d6f5SAlp Dener   bnk->tot_cg_its = 0;
84*e031d6f5SAlp Dener   bnk->newt = 0;
85*e031d6f5SAlp Dener   bnk->bfgs = 0;
86*e031d6f5SAlp Dener   bnk->sgrad = 0;
87*e031d6f5SAlp Dener   bnk->grad = 0;
88*e031d6f5SAlp Dener 
89fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
90fed79b8eSAlp Dener   bnk->pert = bnk->sval;
91fed79b8eSAlp Dener 
92*e031d6f5SAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
93*e031d6f5SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
94*e031d6f5SAlp Dener     if (!bnk->M) {
95eb910715SAlp Dener       ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr);
96eb910715SAlp Dener       ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr);
97eb910715SAlp Dener       ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&bnk->M);CHKERRQ(ierr);
98eb910715SAlp Dener       ierr = MatLMVMAllocateVectors(bnk->M,tao->solution);CHKERRQ(ierr);
99eb910715SAlp Dener     }
100*e031d6f5SAlp Dener     if (bnk->bfgs_scale_type != BFGS_SCALE_BFGS && !bnk->Diag) {
101*e031d6f5SAlp Dener       ierr = VecDuplicate(tao->solution,&bnk->Diag);CHKERRQ(ierr);
1025e9b73cbSAlp Dener     }
103*e031d6f5SAlp Dener   }
104*e031d6f5SAlp Dener 
105*e031d6f5SAlp Dener   /* Prepare the min/max vectors for safeguarding diagonal scales */
10662675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
10762675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
108eb910715SAlp Dener 
109eb910715SAlp Dener   /* Modify the preconditioner to use the bfgs approximation */
110eb910715SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
111eb910715SAlp Dener   switch(bnk->pc_type) {
112eb910715SAlp Dener   case BNK_PC_NONE:
113eb910715SAlp Dener     ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr);
114eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
115eb910715SAlp Dener     break;
116eb910715SAlp Dener 
117eb910715SAlp Dener   case BNK_PC_AHESS:
118eb910715SAlp Dener     ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr);
119eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
120eb910715SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
121eb910715SAlp Dener     break;
122eb910715SAlp Dener 
123eb910715SAlp Dener   case BNK_PC_BFGS:
124eb910715SAlp Dener     ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr);
125eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
126eb910715SAlp Dener     ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr);
127eb910715SAlp Dener     ierr = PCShellSetContext(pc, bnk->M);CHKERRQ(ierr);
128eb910715SAlp Dener     ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr);
129eb910715SAlp Dener     break;
130eb910715SAlp Dener 
131eb910715SAlp Dener   default:
132eb910715SAlp Dener     /* Use the pc method set by pc_type */
133eb910715SAlp Dener     break;
134eb910715SAlp Dener   }
135eb910715SAlp Dener 
136eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
137eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
138c0f10754SAlp Dener   *needH = PETSC_TRUE;
139eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
14062675beeSAlp Dener     switch(initType) {
141eb910715SAlp Dener     case BNK_INIT_CONSTANT:
142eb910715SAlp Dener       /* Use the initial radius specified */
143c0f10754SAlp Dener       tao->trust = tao->trust0;
144eb910715SAlp Dener       break;
145eb910715SAlp Dener 
146eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
147c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
148eb910715SAlp Dener       max_radius = 0.0;
149eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1500a4511e9SAlp Dener         f_min = bnk->f;
151eb910715SAlp Dener         sigma = 0.0;
152eb910715SAlp Dener 
153c0f10754SAlp Dener         if (*needH) {
15462602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
155*e031d6f5SAlp Dener           ierr = TaoBNKComputeHessian(tao);CHKERRQ(ierr);
156*e031d6f5SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao);CHKERRQ(ierr);
15728017e9fSAlp Dener           if (bnk->inactive_idx) {
158*e031d6f5SAlp Dener             ierr = MatDestroy(&bnk->H_inactive);
1592ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
16028017e9fSAlp Dener           } else {
161*e031d6f5SAlp Dener             ierr = MatDestroy(&bnk->H_inactive);
16262675beeSAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);
16328017e9fSAlp Dener           }
164c0f10754SAlp Dener           *needH = PETSC_FALSE;
165eb910715SAlp Dener         }
166eb910715SAlp Dener 
167eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
16862602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
16962602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
17062602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
17162602cfbSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
172770b7498SAlp Dener           /* Recompute the step after bound snapping so that it can be used in predicted decrease calculation later */
173eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
17462602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
17562602cfbSAlp Dener           /* Compute the objective at the trial */
17662602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
17762602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
178eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
179eb910715SAlp Dener             tau = bnk->gamma1_i;
180eb910715SAlp Dener           } else {
1810a4511e9SAlp Dener             if (ftrial < f_min) {
1820a4511e9SAlp Dener               f_min = ftrial;
183eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
184eb910715SAlp Dener             }
185770b7498SAlp Dener             /* Compute the predicted and actual reduction */
1862ab2a32cSAlp Dener             if (bnk->inactive_idx) {
1872ab2a32cSAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
188*e031d6f5SAlp Dener               ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
1892ab2a32cSAlp Dener             } else {
1902ab2a32cSAlp Dener               bnk->G_inactive = bnk->unprojected_gradient;
1912ab2a32cSAlp Dener               bnk->inactive_work = bnk->W;
1922ab2a32cSAlp Dener             }
193*e031d6f5SAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->inactive_work, bnk->G_inactive);CHKERRQ(ierr);
1942ab2a32cSAlp Dener             ierr = VecDot(bnk->G_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
1952ab2a32cSAlp Dener             if (bnk->inactive_idx) {
1962ab2a32cSAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
197*e031d6f5SAlp Dener               ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
1982ab2a32cSAlp Dener             }
199eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
200eb910715SAlp Dener             actred = bnk->f - ftrial;
201eb910715SAlp Dener             if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
202eb910715SAlp Dener               kappa = 1.0;
203eb910715SAlp Dener             } else {
204eb910715SAlp Dener               kappa = actred / prered;
205eb910715SAlp Dener             }
206eb910715SAlp Dener 
207eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
208eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
209eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
210eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
211eb910715SAlp Dener 
212eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
213eb910715SAlp Dener               /* Great agreement */
214eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
215eb910715SAlp Dener 
216eb910715SAlp Dener               if (tau_max < 1.0) {
217eb910715SAlp Dener                 tau = bnk->gamma3_i;
218eb910715SAlp Dener               } else if (tau_max > bnk->gamma4_i) {
219eb910715SAlp Dener                 tau = bnk->gamma4_i;
220eb910715SAlp Dener               } else if (tau_1 >= 1.0 && tau_1 <= bnk->gamma4_i && tau_2 < 1.0) {
221eb910715SAlp Dener                 tau = tau_1;
222eb910715SAlp Dener               } else if (tau_2 >= 1.0 && tau_2 <= bnk->gamma4_i && tau_1 < 1.0) {
223eb910715SAlp Dener                 tau = tau_2;
224eb910715SAlp Dener               } else {
225eb910715SAlp Dener                 tau = tau_max;
226eb910715SAlp Dener               }
227eb910715SAlp Dener             } else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
228eb910715SAlp Dener               /* Good agreement */
229eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
230eb910715SAlp Dener 
231eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
232eb910715SAlp Dener                 tau = bnk->gamma2_i;
233eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
234eb910715SAlp Dener                 tau = bnk->gamma3_i;
235eb910715SAlp Dener               } else {
236eb910715SAlp Dener                 tau = tau_max;
237eb910715SAlp Dener               }
238eb910715SAlp Dener             } else {
239eb910715SAlp Dener               /* Not good agreement */
240eb910715SAlp Dener               if (tau_min > 1.0) {
241eb910715SAlp Dener                 tau = bnk->gamma2_i;
242eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
243eb910715SAlp Dener                 tau = bnk->gamma1_i;
244eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
245eb910715SAlp Dener                 tau = bnk->gamma1_i;
246eb910715SAlp Dener               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
247eb910715SAlp Dener                 tau = tau_1;
248eb910715SAlp Dener               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
249eb910715SAlp Dener                 tau = tau_2;
250eb910715SAlp Dener               } else {
251eb910715SAlp Dener                 tau = tau_max;
252eb910715SAlp Dener               }
253eb910715SAlp Dener             }
254eb910715SAlp Dener           }
255eb910715SAlp Dener           tao->trust = tau * tao->trust;
256eb910715SAlp Dener         }
257eb910715SAlp Dener 
2580a4511e9SAlp Dener         if (f_min < bnk->f) {
259*e031d6f5SAlp Dener           /* We found a solution better than the initial, so let's test and accept it */
2600a4511e9SAlp Dener           bnk->f = f_min;
261eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
26287602d1eSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
26309164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
26409164190SAlp Dener           ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
265eb910715SAlp Dener 
266eb910715SAlp Dener           ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
267eb910715SAlp Dener           if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN");
268c0f10754SAlp Dener           *needH = PETSC_TRUE;
269eb910715SAlp Dener 
270*e031d6f5SAlp Dener           ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr);
271*e031d6f5SAlp Dener           ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr);
272*e031d6f5SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
273*e031d6f5SAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
274eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
275eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
276eb910715SAlp Dener         }
277eb910715SAlp Dener       }
278eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
279*e031d6f5SAlp Dener 
280*e031d6f5SAlp Dener       /* Ensure that the trust radius is within the limits */
281*e031d6f5SAlp Dener       tao->trust = PetscMax(tao->trust, bnk->min_radius);
282*e031d6f5SAlp Dener       tao->trust = PetscMin(tao->trust, bnk->max_radius);
283eb910715SAlp Dener       break;
284eb910715SAlp Dener 
285eb910715SAlp Dener     default:
286eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
287eb910715SAlp Dener       tao->trust = 0.0;
288eb910715SAlp Dener       break;
289eb910715SAlp Dener     }
290eb910715SAlp Dener   }
291*e031d6f5SAlp Dener 
292eb910715SAlp Dener   /* Set initial scaling for the BFGS preconditioner
293eb910715SAlp Dener      This step is done after computing the initial trust-region radius
294eb910715SAlp Dener      since the function value may have decreased */
295eb910715SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
2969b6ef848SAlp Dener     delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
297eb910715SAlp Dener     ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
298eb910715SAlp Dener   }
299eb910715SAlp Dener   PetscFunctionReturn(0);
300eb910715SAlp Dener }
301eb910715SAlp Dener 
302df278d8fSAlp Dener /*------------------------------------------------------------*/
303df278d8fSAlp Dener 
30462675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */
30562675beeSAlp Dener 
30662675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
30762675beeSAlp Dener {
30862675beeSAlp Dener   PetscErrorCode               ierr;
30962675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
31062675beeSAlp Dener 
31162675beeSAlp Dener   PetscFunctionBegin;
31262675beeSAlp Dener   /* Compute the Hessian */
31362675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
31462675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
31562675beeSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
31662675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
31762675beeSAlp Dener     /* Update the BFGS diagonal scaling */
31862675beeSAlp Dener     if (BFGS_SCALE_AHESS == bnk->bfgs_scale_type) {
31962675beeSAlp Dener       ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr);
32062675beeSAlp Dener       ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
32162675beeSAlp Dener       ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
32262675beeSAlp Dener       ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
32362675beeSAlp Dener       ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
32462675beeSAlp Dener     }
32562675beeSAlp Dener   }
32662675beeSAlp Dener   PetscFunctionReturn(0);
32762675beeSAlp Dener }
32862675beeSAlp Dener 
32962675beeSAlp Dener /*------------------------------------------------------------*/
33062675beeSAlp Dener 
3312f75a4aaSAlp Dener /* Routine for estimating the active set */
3322f75a4aaSAlp Dener 
3332f75a4aaSAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao)
3342f75a4aaSAlp Dener {
3352f75a4aaSAlp Dener   PetscErrorCode               ierr;
3362f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3372f75a4aaSAlp Dener 
3382f75a4aaSAlp Dener   PetscFunctionBegin;
3392f75a4aaSAlp Dener   switch (bnk->as_type) {
3402f75a4aaSAlp Dener   case BNK_AS_NONE:
3412f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
3422f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
3432f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
3442f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
3452f75a4aaSAlp Dener     break;
3462f75a4aaSAlp Dener 
3472f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3482f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
3492f75a4aaSAlp Dener     if (BNK_PC_BFGS == bnk->pc_type) {
3502f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
3515e9b73cbSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
3522f75a4aaSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3532f75a4aaSAlp Dener     } else {
3549b6ef848SAlp Dener       /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3552f75a4aaSAlp Dener       ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3569b6ef848SAlp Dener       ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3579b6ef848SAlp Dener       ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3582f75a4aaSAlp Dener       ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3592f75a4aaSAlp Dener       ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
3602f75a4aaSAlp Dener     }
3612f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
3620a4511e9SAlp Dener     ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, bnk->unprojected_gradient, bnk->W, bnk->as_step, &bnk->as_tol, &bnk->active_lower, &bnk->active_upper, &bnk->active_fixed, &bnk->active_idx, &bnk->inactive_idx);CHKERRQ(ierr);
3632f75a4aaSAlp Dener 
3642f75a4aaSAlp Dener   default:
3652f75a4aaSAlp Dener     break;
3662f75a4aaSAlp Dener   }
3672f75a4aaSAlp Dener   PetscFunctionReturn(0);
3682f75a4aaSAlp Dener }
3692f75a4aaSAlp Dener 
3702f75a4aaSAlp Dener /*------------------------------------------------------------*/
3712f75a4aaSAlp Dener 
3722f75a4aaSAlp Dener /* Routine for bounding the step direction */
3732f75a4aaSAlp Dener 
3742f75a4aaSAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, Vec step)
3752f75a4aaSAlp Dener {
3762f75a4aaSAlp Dener   PetscErrorCode               ierr;
3772f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3782f75a4aaSAlp Dener 
3792f75a4aaSAlp Dener   PetscFunctionBegin;
38028017e9fSAlp Dener   if (bnk->active_idx) {
3812f75a4aaSAlp Dener     switch (bnk->as_type) {
3822f75a4aaSAlp Dener     case BNK_AS_NONE:
3832f75a4aaSAlp Dener       if (bnk->active_idx) {
3842f75a4aaSAlp Dener         ierr = VecGetSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr);
3852f75a4aaSAlp Dener         ierr = VecSet(bnk->active_work, 0.0);CHKERRQ(ierr);
3862f75a4aaSAlp Dener         ierr = VecRestoreSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr);
3872f75a4aaSAlp Dener       }
3882f75a4aaSAlp Dener       break;
3892f75a4aaSAlp Dener 
3902f75a4aaSAlp Dener     case BNK_AS_BERTSEKAS:
3912f75a4aaSAlp Dener       ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, step);CHKERRQ(ierr);
3922f75a4aaSAlp Dener       break;
3932f75a4aaSAlp Dener 
3942f75a4aaSAlp Dener     default:
3952f75a4aaSAlp Dener       break;
3962f75a4aaSAlp Dener     }
397e465cd6fSAlp Dener   }
3982f75a4aaSAlp Dener   PetscFunctionReturn(0);
3992f75a4aaSAlp Dener }
4002f75a4aaSAlp Dener 
401*e031d6f5SAlp Dener /*------------------------------------------------------------*/
402*e031d6f5SAlp Dener 
403*e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to
404*e031d6f5SAlp Dener    accelerate Newton convergence.
405*e031d6f5SAlp Dener 
406*e031d6f5SAlp Dener    In practice, this approach simply trades off Hessian evaluations
407*e031d6f5SAlp Dener    for more gradient evaluations.
408*e031d6f5SAlp Dener */
409*e031d6f5SAlp Dener 
410c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
411c0f10754SAlp Dener {
412c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
413c0f10754SAlp Dener   PetscErrorCode               ierr;
414c0f10754SAlp Dener 
415c0f10754SAlp Dener   PetscFunctionBegin;
416c0f10754SAlp Dener   *terminate = PETSC_FALSE;
417c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
418c0f10754SAlp Dener     /* Copy the current solution, unprojected gradient and step info into BNCG */
419c0f10754SAlp Dener     ierr = VecCopy(tao->solution, bnk->bncg->solution);CHKERRQ(ierr);
420c0f10754SAlp Dener     if (tao->niter > 1) {
421c0f10754SAlp Dener       bnk->bncg_ctx->f = bnk->f;
422c0f10754SAlp Dener       ierr = VecCopy(bnk->unprojected_gradient, bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
423c0f10754SAlp Dener       ierr = VecCopy(tao->stepdirection, bnk->bncg->stepdirection);CHKERRQ(ierr);
424c0f10754SAlp Dener       ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
425c0f10754SAlp Dener     }
426c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
427c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
428c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
429c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
430c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
431c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
432c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
433*e031d6f5SAlp Dener     bnk->tot_cg_its += bnk->bncg->niter;
434c0f10754SAlp Dener     /* Extract the BNCG solution out and save it into BNK */
435c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
436c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg->solution, tao->solution);
437c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg_ctx->unprojected_gradient, bnk->unprojected_gradient);
438c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg->gradient, tao->gradient);
439c0f10754SAlp Dener     /* Check to see if BNCG converged the problem */
440c0f10754SAlp Dener     if (bnk->bncg->reason == TAO_CONVERGED_GATOL || bnk->bncg->reason == TAO_CONVERGED_GRTOL || bnk->bncg->reason == TAO_CONVERGED_GTTOL || bnk->bncg->reason == TAO_CONVERGED_MINF) {
441c0f10754SAlp Dener       *terminate = PETSC_TRUE;
442c0f10754SAlp Dener     }
443c0f10754SAlp Dener   }
444c0f10754SAlp Dener   PetscFunctionReturn(0);
445c0f10754SAlp Dener }
446c0f10754SAlp Dener 
4472f75a4aaSAlp Dener /*------------------------------------------------------------*/
4482f75a4aaSAlp Dener 
449c0f10754SAlp Dener /* Routine for computing the Newton step. */
450df278d8fSAlp Dener 
45162675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason)
452eb910715SAlp Dener {
453eb910715SAlp Dener   PetscErrorCode               ierr;
454eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
455eb910715SAlp Dener 
456e465cd6fSAlp Dener   PetscReal                    delta;
457eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
458eb910715SAlp Dener   PetscInt                     kspits;
459eb910715SAlp Dener 
460eb910715SAlp Dener   PetscFunctionBegin;
4615e9b73cbSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
4622f75a4aaSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) { ierr = MatLMVMSetInactive(bnk->M, bnk->inactive_idx);CHKERRQ(ierr); }
4632f75a4aaSAlp Dener   if (bnk->inactive_idx) {
4645e9b73cbSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
4655e9b73cbSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
466eb3ba6a7SAlp Dener     if (tao->hessian == tao->hessian_pre) {
467eb3ba6a7SAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
468eb3ba6a7SAlp Dener     } else {
4695e9b73cbSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
4705e9b73cbSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
471eb3ba6a7SAlp Dener     }
4722f75a4aaSAlp Dener   } else {
47362675beeSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
47462675beeSAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);
47562675beeSAlp Dener     if (tao->hessian == tao->hessian_pre) {
47662675beeSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
47762675beeSAlp Dener     } else {
47862675beeSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
47962675beeSAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);
48062675beeSAlp Dener     }
48162675beeSAlp Dener   }
48262675beeSAlp Dener 
48362675beeSAlp Dener   /* Shift the reduced Hessian matrix */
48462675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
48562675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
48662675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
48762675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
48862675beeSAlp Dener     }
48962675beeSAlp Dener   }
49062675beeSAlp Dener 
49162675beeSAlp Dener   /* Update the diagonal scaling for the BFGS preconditioner, this time with the Hessian perturbation */
49262675beeSAlp Dener   if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_PHESS == bnk->bfgs_scale_type)) {
49362675beeSAlp Dener     /* Obtain diagonal for the bfgs preconditioner  */
4945e9b73cbSAlp Dener     ierr = VecSet(bnk->Diag, 1.0);CHKERRQ(ierr);
4955e9b73cbSAlp Dener     if (bnk->inactive_idx) {
4965e9b73cbSAlp Dener       ierr = VecGetSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
4975e9b73cbSAlp Dener     } else {
4985e9b73cbSAlp Dener       bnk->Diag_red = bnk->Diag;
4995e9b73cbSAlp Dener     }
5005e9b73cbSAlp Dener     ierr = MatGetDiagonal(bnk->H_inactive, bnk->Diag_red);CHKERRQ(ierr);
5015e9b73cbSAlp Dener     if (bnk->inactive_idx) {
5025e9b73cbSAlp Dener       ierr = VecRestoreSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
5035e9b73cbSAlp Dener     }
50462675beeSAlp Dener     ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
50562675beeSAlp Dener     ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
50662675beeSAlp Dener     ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
50762675beeSAlp Dener     ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
5082f75a4aaSAlp Dener   }
50909164190SAlp Dener 
510eb910715SAlp Dener   /* Solve the Newton system of equations */
5112f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
5125e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
51309164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
5145e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
5155e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5165e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5175e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5185e9b73cbSAlp Dener   } else {
5195e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
5205e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
52128017e9fSAlp Dener   }
522eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
523fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5245e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
525eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
526eb910715SAlp Dener     tao->ksp_its+=kspits;
527eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
528080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
529eb910715SAlp Dener 
530eb910715SAlp Dener     if (0.0 == tao->trust) {
531eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
532080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
533080d2917SAlp Dener         tao->trust = bnk->dnorm;
534eb910715SAlp Dener 
535eb910715SAlp Dener         /* Modify the radius if it is too large or small */
536eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
537eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
538eb910715SAlp Dener       } else {
539eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
540eb910715SAlp Dener            the trust-region subproblem to get a direction */
541eb910715SAlp Dener         tao->trust = tao->trust0;
542eb910715SAlp Dener 
543eb910715SAlp Dener         /* Modify the radius if it is too large or small */
544eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
545eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
546eb910715SAlp Dener 
547fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5485e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
549eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
550eb910715SAlp Dener         tao->ksp_its+=kspits;
551eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
552080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
553eb910715SAlp Dener 
554080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
555eb910715SAlp Dener       }
556eb910715SAlp Dener     }
557eb910715SAlp Dener   } else {
5585e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
559eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
560eb910715SAlp Dener     tao->ksp_its += kspits;
561eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
562eb910715SAlp Dener   }
5635e9b73cbSAlp Dener   /* Restore sub vectors back */
5645e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5655e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5665e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5675e9b73cbSAlp Dener   }
568770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
569fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
5702f75a4aaSAlp Dener   ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
571770b7498SAlp Dener 
572770b7498SAlp Dener   /* Record convergence reasons */
573e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
574e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
575770b7498SAlp Dener     ++bnk->ksp_atol;
576e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
577770b7498SAlp Dener     ++bnk->ksp_rtol;
578e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
579770b7498SAlp Dener     ++bnk->ksp_ctol;
580e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
581770b7498SAlp Dener     ++bnk->ksp_negc;
582e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
583770b7498SAlp Dener     ++bnk->ksp_dtol;
584e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
585770b7498SAlp Dener     ++bnk->ksp_iter;
586770b7498SAlp Dener   } else {
587770b7498SAlp Dener     ++bnk->ksp_othr;
588770b7498SAlp Dener   }
589fed79b8eSAlp Dener 
590fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
591fed79b8eSAlp Dener   if (bnk->pc_type == BNK_PC_BFGS) {
592fed79b8eSAlp Dener     ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
593e465cd6fSAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 1)) {
594fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
5959b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
596eb910715SAlp Dener       ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
597eb910715SAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
59809164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
599eb910715SAlp Dener     }
600fed79b8eSAlp Dener   }
601e465cd6fSAlp Dener   PetscFunctionReturn(0);
602e465cd6fSAlp Dener }
603eb910715SAlp Dener 
60462675beeSAlp Dener /*------------------------------------------------------------*/
60562675beeSAlp Dener 
6065e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
6075e9b73cbSAlp Dener 
6085e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
6095e9b73cbSAlp Dener {
6105e9b73cbSAlp Dener   PetscErrorCode               ierr;
6115e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
6125e9b73cbSAlp Dener 
6135e9b73cbSAlp Dener   PetscFunctionBegin;
6145e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
6155e9b73cbSAlp Dener   if (bnk->inactive_idx){
6165e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6175e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6185e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6195e9b73cbSAlp Dener   } else {
6205e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
6215e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
6225e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
6235e9b73cbSAlp Dener   }
6245e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
6255e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
6265e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
6275e9b73cbSAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);
6285e9b73cbSAlp Dener   /* Restore the sub vectors */
6295e9b73cbSAlp Dener   if (bnk->inactive_idx){
6305e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6315e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6325e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6335e9b73cbSAlp Dener   }
6345e9b73cbSAlp Dener   PetscFunctionReturn(0);
6355e9b73cbSAlp Dener }
6365e9b73cbSAlp Dener 
6375e9b73cbSAlp Dener /*------------------------------------------------------------*/
6385e9b73cbSAlp Dener 
63962675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
64062675beeSAlp Dener 
64162675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
64262675beeSAlp Dener    in the event that the Newton step fails the test.
64362675beeSAlp Dener */
64462675beeSAlp Dener 
645e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
646e465cd6fSAlp Dener {
647e465cd6fSAlp Dener   PetscErrorCode               ierr;
648e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
649e465cd6fSAlp Dener 
650e465cd6fSAlp Dener   PetscReal                    gdx, delta, e_min;
651e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
652e465cd6fSAlp Dener 
653e465cd6fSAlp Dener   PetscFunctionBegin;
654080d2917SAlp Dener   ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
655eb910715SAlp Dener   if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
656eb910715SAlp Dener     /* Newton step is not descent or direction produced Inf or NaN
657eb910715SAlp Dener        Update the perturbation for next time */
658eb910715SAlp Dener     if (bnk->pert <= 0.0) {
659eb910715SAlp Dener       /* Initialize the perturbation */
660eb910715SAlp Dener       bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
661eb910715SAlp Dener       if (bnk->is_gltr) {
662eb910715SAlp Dener         ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
663eb910715SAlp Dener         bnk->pert = PetscMax(bnk->pert, -e_min);
664eb910715SAlp Dener       }
665eb910715SAlp Dener     } else {
666eb910715SAlp Dener       /* Increase the perturbation */
667eb910715SAlp Dener       bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
668eb910715SAlp Dener     }
669eb910715SAlp Dener 
670eb910715SAlp Dener     if (BNK_PC_BFGS != bnk->pc_type) {
671eb910715SAlp Dener       /* We don't have the bfgs matrix around and updated
672eb910715SAlp Dener          Must use gradient direction in this case */
673080d2917SAlp Dener       ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
674eb910715SAlp Dener       *stepType = BNK_GRADIENT;
675eb910715SAlp Dener     } else {
676eb910715SAlp Dener       /* Attempt to use the BFGS direction */
6772ab2a32cSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
67809164190SAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
679eb910715SAlp Dener 
6808d5ead36SAlp Dener       /* Check for success (descent direction)
6818d5ead36SAlp Dener          NOTE: Negative gdx here means not a descent direction because
6828d5ead36SAlp Dener          the fall-back step is missing a negative sign. */
683080d2917SAlp Dener       ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
6848d5ead36SAlp Dener       if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
685eb910715SAlp Dener         /* BFGS direction is not descent or direction produced not a number
686eb910715SAlp Dener            We can assert bfgsUpdates > 1 in this case because
687eb910715SAlp Dener            the first solve produces the scaled gradient direction,
688eb910715SAlp Dener            which is guaranteed to be descent */
689eb910715SAlp Dener 
690eb910715SAlp Dener         /* Use steepest descent direction (scaled) */
6919b6ef848SAlp Dener         delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
692eb910715SAlp Dener         ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
693eb910715SAlp Dener         ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
69409164190SAlp Dener         ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
69509164190SAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
696eb910715SAlp Dener 
697eb910715SAlp Dener         *stepType = BNK_SCALED_GRADIENT;
698eb910715SAlp Dener       } else {
699770b7498SAlp Dener         ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
700eb910715SAlp Dener         if (1 == bfgsUpdates) {
701eb910715SAlp Dener           /* The first BFGS direction is always the scaled gradient */
702eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
703eb910715SAlp Dener         } else {
704eb910715SAlp Dener           *stepType = BNK_BFGS;
705eb910715SAlp Dener         }
706eb910715SAlp Dener       }
707eb910715SAlp Dener     }
7088d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
7098d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
7102f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
711eb910715SAlp Dener   } else {
712eb910715SAlp Dener     /* Computed Newton step is descent */
713eb910715SAlp Dener     switch (ksp_reason) {
714eb910715SAlp Dener     case KSP_DIVERGED_NANORINF:
715eb910715SAlp Dener     case KSP_DIVERGED_BREAKDOWN:
716eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_MAT:
717eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_PC:
718eb910715SAlp Dener     case KSP_CONVERGED_CG_NEG_CURVE:
719eb910715SAlp Dener       /* Matrix or preconditioner is indefinite; increase perturbation */
720eb910715SAlp Dener       if (bnk->pert <= 0.0) {
721eb910715SAlp Dener         /* Initialize the perturbation */
722eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
723eb910715SAlp Dener         if (bnk->is_gltr) {
724eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
725eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
726eb910715SAlp Dener         }
727eb910715SAlp Dener       } else {
728eb910715SAlp Dener         /* Increase the perturbation */
729eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
730eb910715SAlp Dener       }
731eb910715SAlp Dener       break;
732eb910715SAlp Dener 
733eb910715SAlp Dener     default:
734eb910715SAlp Dener       /* Newton step computation is good; decrease perturbation */
735eb910715SAlp Dener       bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
736eb910715SAlp Dener       if (bnk->pert < bnk->pmin) {
737eb910715SAlp Dener         bnk->pert = 0.0;
738eb910715SAlp Dener       }
739eb910715SAlp Dener       break;
740eb910715SAlp Dener     }
741fed79b8eSAlp Dener     *stepType = BNK_NEWTON;
742eb910715SAlp Dener   }
743eb910715SAlp Dener   PetscFunctionReturn(0);
744eb910715SAlp Dener }
745eb910715SAlp Dener 
746df278d8fSAlp Dener /*------------------------------------------------------------*/
747df278d8fSAlp Dener 
748df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
749df278d8fSAlp Dener 
750df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
751df278d8fSAlp Dener   Newton step does not produce a valid step length.
752df278d8fSAlp Dener */
753df278d8fSAlp Dener 
754c14b763aSAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
755c14b763aSAlp Dener {
756c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
757c14b763aSAlp Dener   PetscErrorCode ierr;
758c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
759c14b763aSAlp Dener 
760c14b763aSAlp Dener   PetscReal      e_min, gdx, delta;
761c14b763aSAlp Dener   PetscInt       bfgsUpdates;
762c14b763aSAlp Dener 
763c14b763aSAlp Dener   PetscFunctionBegin;
764c14b763aSAlp Dener   /* Perform the linesearch */
765c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
766c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
767c14b763aSAlp Dener 
7689b6ef848SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && (stepType != BNK_GRADIENT || stepType !=BNK_SCALED_GRADIENT)) {
769c14b763aSAlp Dener     /* Linesearch failed, revert solution */
770c14b763aSAlp Dener     bnk->f = bnk->fold;
771c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
772c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
773c14b763aSAlp Dener 
774c14b763aSAlp Dener     switch(stepType) {
775c14b763aSAlp Dener     case BNK_NEWTON:
7768d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
777c14b763aSAlp Dener          Update the perturbation for next time */
778c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
779c14b763aSAlp Dener         /* Initialize the perturbation */
780c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
781c14b763aSAlp Dener         if (bnk->is_gltr) {
782c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
783c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
784c14b763aSAlp Dener         }
785c14b763aSAlp Dener       } else {
786c14b763aSAlp Dener         /* Increase the perturbation */
787c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
788c14b763aSAlp Dener       }
789c14b763aSAlp Dener 
790c14b763aSAlp Dener       if (BNK_PC_BFGS != bnk->pc_type) {
791c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
792c14b763aSAlp Dener            Must use gradient direction in this case */
793c14b763aSAlp Dener         ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
794c14b763aSAlp Dener         stepType = BNK_GRADIENT;
795c14b763aSAlp Dener       } else {
796c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
797c14b763aSAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
7988d5ead36SAlp Dener         /* Check for success (descent direction)
7998d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
800c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
801c14b763aSAlp Dener         if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
802c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
803c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
804c14b763aSAlp Dener              Use steepest descent direction (scaled) */
8059b6ef848SAlp Dener           delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
806c14b763aSAlp Dener           ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
807c14b763aSAlp Dener           ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
808c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
809c14b763aSAlp Dener           ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
810c14b763aSAlp Dener 
811c14b763aSAlp Dener           bfgsUpdates = 1;
812c14b763aSAlp Dener           stepType = BNK_SCALED_GRADIENT;
813c14b763aSAlp Dener         } else {
814c14b763aSAlp Dener           ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
815c14b763aSAlp Dener           if (1 == bfgsUpdates) {
816c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
817c14b763aSAlp Dener             stepType = BNK_SCALED_GRADIENT;
818c14b763aSAlp Dener           } else {
819c14b763aSAlp Dener             stepType = BNK_BFGS;
820c14b763aSAlp Dener           }
821c14b763aSAlp Dener         }
822c14b763aSAlp Dener       }
823c14b763aSAlp Dener       break;
824c14b763aSAlp Dener 
825c14b763aSAlp Dener     case BNK_BFGS:
826c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
827c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
828c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
8299b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
830c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
831c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
832c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
833c14b763aSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
834c14b763aSAlp Dener 
835c14b763aSAlp Dener       bfgsUpdates = 1;
836c14b763aSAlp Dener       stepType = BNK_SCALED_GRADIENT;
837c14b763aSAlp Dener       break;
838c14b763aSAlp Dener 
839c14b763aSAlp Dener     case BNK_SCALED_GRADIENT:
840c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
841c14b763aSAlp Dener          The scaled gradient step did not produce a new iterate;
842c14b763aSAlp Dener          attemp to use the gradient direction.
843c14b763aSAlp Dener          Need to make sure we are not using a different diagonal scaling */
844c14b763aSAlp Dener       ierr = MatLMVMSetScale(bnk->M,0);CHKERRQ(ierr);
845c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M,1.0);CHKERRQ(ierr);
846c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
847c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
848c14b763aSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
849c14b763aSAlp Dener 
850c14b763aSAlp Dener       bfgsUpdates = 1;
851c14b763aSAlp Dener       stepType = BNK_GRADIENT;
852c14b763aSAlp Dener       break;
853c14b763aSAlp Dener     }
8548d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
8558d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
8562f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
857c14b763aSAlp Dener 
8588d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
859c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
860c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
861c14b763aSAlp Dener   }
862c14b763aSAlp Dener   *reason = ls_reason;
863c14b763aSAlp Dener   PetscFunctionReturn(0);
864c14b763aSAlp Dener }
865c14b763aSAlp Dener 
866df278d8fSAlp Dener /*------------------------------------------------------------*/
867df278d8fSAlp Dener 
868df278d8fSAlp Dener /* Routine for updating the trust radius.
869df278d8fSAlp Dener 
870df278d8fSAlp Dener   Function features three different update methods:
871df278d8fSAlp Dener   1) Line-search step length based
872df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
873df278d8fSAlp Dener   3) Interpolation
874df278d8fSAlp Dener */
875df278d8fSAlp Dener 
87628017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
877080d2917SAlp Dener {
878080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
879080d2917SAlp Dener   PetscErrorCode ierr;
880080d2917SAlp Dener 
881b1c2d0e3SAlp Dener   PetscReal      step, kappa;
882080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
883080d2917SAlp Dener 
884080d2917SAlp Dener   PetscFunctionBegin;
885080d2917SAlp Dener   /* Update trust region radius */
886080d2917SAlp Dener   *accept = PETSC_FALSE;
88728017e9fSAlp Dener   switch(updateType) {
888080d2917SAlp Dener   case BNK_UPDATE_STEP:
889c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
890080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
891080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
892080d2917SAlp Dener       if (step < bnk->nu1) {
893080d2917SAlp Dener         /* Very bad step taken; reduce radius */
894080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
895080d2917SAlp Dener       } else if (step < bnk->nu2) {
896080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
897080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
898080d2917SAlp Dener       } else if (step < bnk->nu3) {
899080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
900080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
901080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
902080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
903080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
904080d2917SAlp Dener         }
905080d2917SAlp Dener       } else if (step < bnk->nu4) {
906080d2917SAlp Dener         /*  Full step taken; increase the radius */
907080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
908080d2917SAlp Dener       } else {
909080d2917SAlp Dener         /*  More than full step taken; increase the radius */
910080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
911080d2917SAlp Dener       }
912080d2917SAlp Dener     } else {
913080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
914080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
915080d2917SAlp Dener     }
916080d2917SAlp Dener     break;
917080d2917SAlp Dener 
918080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
919080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
920b1c2d0e3SAlp Dener       if (prered < 0.0) {
921fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
922fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
923fed79b8eSAlp Dener            be rejected! */
924080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
925fed79b8eSAlp Dener       }
926fed79b8eSAlp Dener       else {
927b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
928080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
929080d2917SAlp Dener         } else {
9300a4511e9SAlp Dener           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) &&
9310a4511e9SAlp Dener               (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
932080d2917SAlp Dener             kappa = 1.0;
933fed79b8eSAlp Dener           }
934fed79b8eSAlp Dener           else {
935080d2917SAlp Dener             kappa = actred / prered;
936080d2917SAlp Dener           }
937fed79b8eSAlp Dener 
938fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
939080d2917SAlp Dener           if (kappa < bnk->eta1) {
940fed79b8eSAlp Dener             /* Reject the step */
941080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
942fed79b8eSAlp Dener           }
943fed79b8eSAlp Dener           else {
944fed79b8eSAlp Dener             /* Accept the step */
945c133c014SAlp Dener             *accept = PETSC_TRUE;
946c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
9478d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
948080d2917SAlp Dener               if (kappa < bnk->eta2) {
949080d2917SAlp Dener                 /* Marginal bad step */
950c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
951080d2917SAlp Dener               }
952fed79b8eSAlp Dener               else if (kappa < bnk->eta3) {
953fed79b8eSAlp Dener                 /* Reasonable step */
954fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
955fed79b8eSAlp Dener               }
956fed79b8eSAlp Dener               else if (kappa < bnk->eta4) {
957080d2917SAlp Dener                 /* Good step */
958c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
959fed79b8eSAlp Dener               }
960fed79b8eSAlp Dener               else {
961080d2917SAlp Dener                 /* Very good step */
962c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
963080d2917SAlp Dener               }
964c133c014SAlp Dener             }
965080d2917SAlp Dener           }
966080d2917SAlp Dener         }
967080d2917SAlp Dener       }
968080d2917SAlp Dener     } else {
969080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
970080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
971080d2917SAlp Dener     }
972080d2917SAlp Dener     break;
973080d2917SAlp Dener 
974080d2917SAlp Dener   default:
975080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
976b1c2d0e3SAlp Dener       if (prered < 0.0) {
977080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
978080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
979080d2917SAlp Dener         /*  be rejected! */
980080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
981080d2917SAlp Dener       } else {
982b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
983080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
984080d2917SAlp Dener         } else {
985080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
986080d2917SAlp Dener             kappa = 1.0;
987080d2917SAlp Dener           } else {
988080d2917SAlp Dener             kappa = actred / prered;
989080d2917SAlp Dener           }
990080d2917SAlp Dener 
991080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
992080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
993080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
994080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
995080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
996080d2917SAlp Dener 
997080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
998080d2917SAlp Dener             /*  Great agreement */
999080d2917SAlp Dener             *accept = PETSC_TRUE;
1000080d2917SAlp Dener             if (tau_max < 1.0) {
1001080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1002080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
1003080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
1004080d2917SAlp Dener             } else {
1005080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1006080d2917SAlp Dener             }
1007080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
1008080d2917SAlp Dener             /*  Good agreement */
1009080d2917SAlp Dener             *accept = PETSC_TRUE;
1010080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
1011080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1012080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
1013080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1014080d2917SAlp Dener             } else if (tau_max < 1.0) {
1015080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1016080d2917SAlp Dener             } else {
1017080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1018080d2917SAlp Dener             }
1019080d2917SAlp Dener           } else {
1020080d2917SAlp Dener             /*  Not good agreement */
1021080d2917SAlp Dener             if (tau_min > 1.0) {
1022080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1023080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
1024080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1025080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
1026080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1027080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
1028080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
1029080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
1030080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
1031080d2917SAlp Dener             } else {
1032080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1033080d2917SAlp Dener             }
1034080d2917SAlp Dener           }
1035080d2917SAlp Dener         }
1036080d2917SAlp Dener       }
1037080d2917SAlp Dener     } else {
1038080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
1039080d2917SAlp Dener       tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust);
1040080d2917SAlp Dener     }
104128017e9fSAlp Dener     break;
1042080d2917SAlp Dener   }
1043c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
1044c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
1045fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
1046080d2917SAlp Dener   PetscFunctionReturn(0);
1047080d2917SAlp Dener }
1048080d2917SAlp Dener 
1049eb910715SAlp Dener /* ---------------------------------------------------------- */
1050df278d8fSAlp Dener 
105162675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
105262675beeSAlp Dener {
105362675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
105462675beeSAlp Dener 
105562675beeSAlp Dener   PetscFunctionBegin;
105662675beeSAlp Dener   switch (stepType) {
105762675beeSAlp Dener   case BNK_NEWTON:
105862675beeSAlp Dener     ++bnk->newt;
105962675beeSAlp Dener     break;
106062675beeSAlp Dener   case BNK_BFGS:
106162675beeSAlp Dener     ++bnk->bfgs;
106262675beeSAlp Dener     break;
106362675beeSAlp Dener   case BNK_SCALED_GRADIENT:
106462675beeSAlp Dener     ++bnk->sgrad;
106562675beeSAlp Dener     break;
106662675beeSAlp Dener   case BNK_GRADIENT:
106762675beeSAlp Dener     ++bnk->grad;
106862675beeSAlp Dener     break;
106962675beeSAlp Dener   default:
107062675beeSAlp Dener     break;
107162675beeSAlp Dener   }
107262675beeSAlp Dener   PetscFunctionReturn(0);
107362675beeSAlp Dener }
107462675beeSAlp Dener 
107562675beeSAlp Dener /* ---------------------------------------------------------- */
107662675beeSAlp Dener 
10779b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
1078eb910715SAlp Dener {
1079eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1080eb910715SAlp Dener   PetscErrorCode ierr;
10819b6ef848SAlp Dener   KSPType        ksp_type;
1082*e031d6f5SAlp Dener   PetscInt       i;
1083eb910715SAlp Dener 
1084eb910715SAlp Dener   PetscFunctionBegin;
1085eb910715SAlp Dener   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);}
1086eb910715SAlp Dener   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);}
1087eb910715SAlp Dener   if (!bnk->W) {ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);}
1088eb910715SAlp Dener   if (!bnk->Xold) {ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);}
1089eb910715SAlp Dener   if (!bnk->Gold) {ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);}
109009164190SAlp Dener   if (!bnk->Xwork) {ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);}
109109164190SAlp Dener   if (!bnk->Gwork) {ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);}
109209164190SAlp Dener   if (!bnk->unprojected_gradient) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);}
109309164190SAlp Dener   if (!bnk->unprojected_gradient_old) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);}
10945e9b73cbSAlp Dener   if (!bnk->Diag_min) {ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);}
10955e9b73cbSAlp Dener   if (!bnk->Diag_max) {ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);}
1096*e031d6f5SAlp Dener   if (bnk->max_cg_its > 0) {
1097*e031d6f5SAlp Dener     if (!bnk->bncg_sol) {ierr = VecDuplicate(tao->solution,&bnk->bncg_sol);CHKERRQ(ierr);}
1098*e031d6f5SAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, bnk->bncg_sol);CHKERRQ(ierr);
1099*e031d6f5SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
1100*e031d6f5SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
1101*e031d6f5SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
1102*e031d6f5SAlp Dener 
1103*e031d6f5SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
1104*e031d6f5SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
1105*e031d6f5SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
1106*e031d6f5SAlp Dener     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr);
1107*e031d6f5SAlp Dener     for (i=0; i<tao->numbermonitors; i++) {
1108*e031d6f5SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
1109*e031d6f5SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
1110*e031d6f5SAlp Dener     }
1111*e031d6f5SAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
1112*e031d6f5SAlp Dener   }
1113eb910715SAlp Dener   bnk->Diag = 0;
1114c0f10754SAlp Dener   bnk->Diag_red = 0;
1115c0f10754SAlp Dener   bnk->X_inactive = 0;
1116c0f10754SAlp Dener   bnk->G_inactive = 0;
111762675beeSAlp Dener   bnk->inactive_work = 0;
111862675beeSAlp Dener   bnk->active_work = 0;
111962675beeSAlp Dener   bnk->inactive_idx = 0;
112062675beeSAlp Dener   bnk->active_idx = 0;
112162675beeSAlp Dener   bnk->active_lower = 0;
112262675beeSAlp Dener   bnk->active_upper = 0;
112362675beeSAlp Dener   bnk->active_fixed = 0;
1124eb910715SAlp Dener   bnk->M = 0;
112509164190SAlp Dener   bnk->H_inactive = 0;
112609164190SAlp Dener   bnk->Hpre_inactive = 0;
11279b6ef848SAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
11289b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
11299b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
11309b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1131eb910715SAlp Dener   PetscFunctionReturn(0);
1132eb910715SAlp Dener }
1133eb910715SAlp Dener 
1134eb910715SAlp Dener /*------------------------------------------------------------*/
1135df278d8fSAlp Dener 
1136eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao)
1137eb910715SAlp Dener {
1138eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1139eb910715SAlp Dener   PetscErrorCode ierr;
1140eb910715SAlp Dener 
1141eb910715SAlp Dener   PetscFunctionBegin;
1142eb910715SAlp Dener   if (tao->setupcalled) {
1143eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1144eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1145eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
114609164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
114709164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
114809164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
114909164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
115062675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
115162675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1152c0f10754SAlp Dener     if (bnk->max_cg_its > 0) {
1153c0f10754SAlp Dener       ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1154c0f10754SAlp Dener       ierr = VecDestroy(&bnk->bncg_sol);CHKERRQ(ierr);
1155c0f10754SAlp Dener     }
11565e9b73cbSAlp Dener   }
11575e9b73cbSAlp Dener   ierr = VecDestroy(&bnk->Diag);CHKERRQ(ierr);
1158eb910715SAlp Dener   ierr = MatDestroy(&bnk->M);CHKERRQ(ierr);
1159c0f10754SAlp Dener   if (bnk->Hpre_inactive != tao->hessian_pre && bnk->Hpre_inactive != bnk->H_inactive) {ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);}
1160c0f10754SAlp Dener   if (bnk->H_inactive != tao->hessian) {ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);}
1161eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1162eb910715SAlp Dener   PetscFunctionReturn(0);
1163eb910715SAlp Dener }
1164eb910715SAlp Dener 
1165eb910715SAlp Dener /*------------------------------------------------------------*/
1166df278d8fSAlp Dener 
1167eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1168eb910715SAlp Dener {
1169eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1170eb910715SAlp Dener   PetscErrorCode ierr;
1171eb910715SAlp Dener 
1172eb910715SAlp Dener   PetscFunctionBegin;
1173eb910715SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr);
11748d5ead36SAlp Dener   ierr = PetscOptionsEList("-tao_bnk_pc_type", "pc type", "", BNK_PC, BNK_PC_TYPES, BNK_PC[bnk->pc_type], &bnk->pc_type, 0);CHKERRQ(ierr);
11758d5ead36SAlp Dener   ierr = PetscOptionsEList("-tao_bnk_bfgs_scale_type", "bfgs scale type", "", BFGS_SCALE, BFGS_SCALE_TYPES, BFGS_SCALE[bnk->bfgs_scale_type], &bnk->bfgs_scale_type, 0);CHKERRQ(ierr);
11768d5ead36SAlp Dener   ierr = PetscOptionsEList("-tao_bnk_init_type", "radius initialization type", "", BNK_INIT, BNK_INIT_TYPES, BNK_INIT[bnk->init_type], &bnk->init_type, 0);CHKERRQ(ierr);
11778d5ead36SAlp Dener   ierr = PetscOptionsEList("-tao_bnk_update_type", "radius update type", "", BNK_UPDATE, BNK_UPDATE_TYPES, BNK_UPDATE[bnk->update_type], &bnk->update_type, 0);CHKERRQ(ierr);
11782f75a4aaSAlp Dener   ierr = PetscOptionsEList("-tao_bnk_as_type", "active set estimation method", "", BNK_AS, BNK_AS_TYPES, BNK_AS[bnk->as_type], &bnk->as_type, 0);CHKERRQ(ierr);
11798d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
11808d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "minimum initial perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
11818d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "maximum initial perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
11828d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "initial merit factor", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
11838d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "minimum perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
11848d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "maximum perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
11858d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
11868d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
11878d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "merit growth factor", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
11888d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "merit shrink factor", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
11898d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "poor steplength; reduce radius", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
11908d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "reasonable steplength; leave radius alone", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
11918d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "good steplength; increase radius", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
11928d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "excellent steplength; greatly increase radius", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
11938d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha1", "", "", bnk->alpha1, &bnk->alpha1,NULL);CHKERRQ(ierr);
11948d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha2", "", "", bnk->alpha2, &bnk->alpha2,NULL);CHKERRQ(ierr);
11958d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha3", "", "", bnk->alpha3, &bnk->alpha3,NULL);CHKERRQ(ierr);
11968d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha4", "", "", bnk->alpha4, &bnk->alpha4,NULL);CHKERRQ(ierr);
11978d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha5", "", "", bnk->alpha5, &bnk->alpha5,NULL);CHKERRQ(ierr);
11988d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu1", "poor steplength; reduce radius", "", bnk->nu1, &bnk->nu1,NULL);CHKERRQ(ierr);
11998d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu2", "reasonable steplength; leave radius alone", "", bnk->nu2, &bnk->nu2,NULL);CHKERRQ(ierr);
12008d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu3", "good steplength; increase radius", "", bnk->nu3, &bnk->nu3,NULL);CHKERRQ(ierr);
12018d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu4", "excellent steplength; greatly increase radius", "", bnk->nu4, &bnk->nu4,NULL);CHKERRQ(ierr);
12028d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega1", "", "", bnk->omega1, &bnk->omega1,NULL);CHKERRQ(ierr);
12038d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega2", "", "", bnk->omega2, &bnk->omega2,NULL);CHKERRQ(ierr);
12048d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega3", "", "", bnk->omega3, &bnk->omega3,NULL);CHKERRQ(ierr);
12058d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega4", "", "", bnk->omega4, &bnk->omega4,NULL);CHKERRQ(ierr);
12068d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega5", "", "", bnk->omega5, &bnk->omega5,NULL);CHKERRQ(ierr);
12078d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1_i", "", "", bnk->mu1_i, &bnk->mu1_i,NULL);CHKERRQ(ierr);
12088d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2_i", "", "", bnk->mu2_i, &bnk->mu2_i,NULL);CHKERRQ(ierr);
12098d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1_i", "", "", bnk->gamma1_i, &bnk->gamma1_i,NULL);CHKERRQ(ierr);
12108d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2_i", "", "", bnk->gamma2_i, &bnk->gamma2_i,NULL);CHKERRQ(ierr);
12118d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3_i", "", "", bnk->gamma3_i, &bnk->gamma3_i,NULL);CHKERRQ(ierr);
12128d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4_i", "", "", bnk->gamma4_i, &bnk->gamma4_i,NULL);CHKERRQ(ierr);
12138d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta_i", "", "", bnk->theta_i, &bnk->theta_i,NULL);CHKERRQ(ierr);
12148d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1", "", "", bnk->mu1, &bnk->mu1,NULL);CHKERRQ(ierr);
12158d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
12168d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1", "", "", bnk->gamma1, &bnk->gamma1,NULL);CHKERRQ(ierr);
12178d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2", "", "", bnk->gamma2, &bnk->gamma2,NULL);CHKERRQ(ierr);
12188d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3", "", "", bnk->gamma3, &bnk->gamma3,NULL);CHKERRQ(ierr);
12198d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4", "", "", bnk->gamma4, &bnk->gamma4,NULL);CHKERRQ(ierr);
12208d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
12218d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
12228d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
12238d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
12240a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_tol", "initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol,NULL);CHKERRQ(ierr);
12250a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_step", "step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step,NULL);CHKERRQ(ierr);
1226c0f10754SAlp Dener   ierr = PetscOptionsInt("-tao_bnk_max_cg_its", "number of BNCG iterations to take for each Newton step", "", bnk->max_cg_its, &bnk->max_cg_its,NULL);CHKERRQ(ierr);
1227eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
1228*e031d6f5SAlp Dener   ierr = TaoSetFromOptions(bnk->bncg);
1229eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1230eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1231eb910715SAlp Dener   PetscFunctionReturn(0);
1232eb910715SAlp Dener }
1233eb910715SAlp Dener 
1234eb910715SAlp Dener /*------------------------------------------------------------*/
1235df278d8fSAlp Dener 
1236eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1237eb910715SAlp Dener {
1238eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1239eb910715SAlp Dener   PetscInt       nrejects;
1240eb910715SAlp Dener   PetscBool      isascii;
1241eb910715SAlp Dener   PetscErrorCode ierr;
1242eb910715SAlp Dener 
1243eb910715SAlp Dener   PetscFunctionBegin;
1244eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1245eb910715SAlp Dener   if (isascii) {
1246eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1247eb910715SAlp Dener     if (BNK_PC_BFGS == bnk->pc_type && bnk->M) {
1248eb910715SAlp Dener       ierr = MatLMVMGetRejects(bnk->M,&nrejects);CHKERRQ(ierr);
1249eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects);CHKERRQ(ierr);
1250eb910715SAlp Dener     }
1251*e031d6f5SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr);
1252eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1253eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1254eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1255eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1256eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1257eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1258eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1259eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1260eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1261eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1262eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1263eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1264eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1265eb910715SAlp Dener   }
1266eb910715SAlp Dener   PetscFunctionReturn(0);
1267eb910715SAlp Dener }
1268eb910715SAlp Dener 
1269eb910715SAlp Dener /* ---------------------------------------------------------- */
1270df278d8fSAlp Dener 
1271eb910715SAlp Dener /*MC
1272eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
127366ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1274eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1275eb910715SAlp Dener               Hk dk = -gk
12762b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12772b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1278eb910715SAlp Dener 
1279eb910715SAlp Dener     Options Database Keys:
12808d5ead36SAlp Dener + -tao_bnk_pc_type - "none","ahess","bfgs","petsc"
12818d5ead36SAlp Dener . -tao_bnk_bfgs_scale_type - "ahess","phess","bfgs"
12828d5ead36SAlp Dener . -tao_bnk_init_type - "constant","direction","interpolation"
12838d5ead36SAlp Dener . -tao_bnk_update_type - "step","direction","interpolation"
12842f75a4aaSAlp Dener . -tao_bnk_as_type - "none","bertsekas"
12858d5ead36SAlp Dener . -tao_bnk_sval - perturbation starting value
12868d5ead36SAlp Dener . -tao_bnk_imin - minimum initial perturbation
12878d5ead36SAlp Dener . -tao_bnk_imax - maximum initial perturbation
12888d5ead36SAlp Dener . -tao_bnk_pmin - minimum perturbation
12898d5ead36SAlp Dener . -tao_bnk_pmax - maximum perturbation
12908d5ead36SAlp Dener . -tao_bnk_pgfac - growth factor
12918d5ead36SAlp Dener . -tao_bnk_psfac - shrink factor
12928d5ead36SAlp Dener . -tao_bnk_imfac - initial merit factor
12938d5ead36SAlp Dener . -tao_bnk_pmgfac - merit growth factor
12948d5ead36SAlp Dener . -tao_bnk_pmsfac - merit shrink factor
12958d5ead36SAlp Dener . -tao_bnk_eta1 - poor steplength; reduce radius
12968d5ead36SAlp Dener . -tao_bnk_eta2 - reasonable steplength; leave radius
12978d5ead36SAlp Dener . -tao_bnk_eta3 - good steplength; increase readius
12988d5ead36SAlp Dener . -tao_bnk_eta4 - excellent steplength; greatly increase radius
12998d5ead36SAlp Dener . -tao_bnk_alpha1 - alpha1 reduction
13008d5ead36SAlp Dener . -tao_bnk_alpha2 - alpha2 reduction
13018d5ead36SAlp Dener . -tao_bnk_alpha3 - alpha3 reduction
13028d5ead36SAlp Dener . -tao_bnk_alpha4 - alpha4 reduction
13038d5ead36SAlp Dener . -tao_bnk_alpha - alpha5 reduction
13048d5ead36SAlp Dener . -tao_bnk_mu1 - mu1 interpolation update
13058d5ead36SAlp Dener . -tao_bnk_mu2 - mu2 interpolation update
13068d5ead36SAlp Dener . -tao_bnk_gamma1 - gamma1 interpolation update
13078d5ead36SAlp Dener . -tao_bnk_gamma2 - gamma2 interpolation update
13088d5ead36SAlp Dener . -tao_bnk_gamma3 - gamma3 interpolation update
13098d5ead36SAlp Dener . -tao_bnk_gamma4 - gamma4 interpolation update
13108d5ead36SAlp Dener . -tao_bnk_theta - theta interpolation update
13118d5ead36SAlp Dener . -tao_bnk_omega1 - omega1 step update
13128d5ead36SAlp Dener . -tao_bnk_omega2 - omega2 step update
13138d5ead36SAlp Dener . -tao_bnk_omega3 - omega3 step update
13148d5ead36SAlp Dener . -tao_bnk_omega4 - omega4 step update
13158d5ead36SAlp Dener . -tao_bnk_omega5 - omega5 step update
13168d5ead36SAlp Dener . -tao_bnk_mu1_i -  mu1 interpolation init factor
13178d5ead36SAlp Dener . -tao_bnk_mu2_i -  mu2 interpolation init factor
13188d5ead36SAlp Dener . -tao_bnk_gamma1_i -  gamma1 interpolation init factor
13198d5ead36SAlp Dener . -tao_bnk_gamma2_i -  gamma2 interpolation init factor
13208d5ead36SAlp Dener . -tao_bnk_gamma3_i -  gamma3 interpolation init factor
13218d5ead36SAlp Dener . -tao_bnk_gamma4_i -  gamma4 interpolation init factor
13222f75a4aaSAlp Dener . -tao_bnk_theta_i -  theta interpolation init factor
13232f75a4aaSAlp Dener - -tao_bnk_bound_tol -  initial tolerance used in estimating bounded active variables
1324eb910715SAlp Dener 
1325eb910715SAlp Dener   Level: beginner
1326eb910715SAlp Dener M*/
1327eb910715SAlp Dener 
1328eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1329eb910715SAlp Dener {
1330eb910715SAlp Dener   TAO_BNK        *bnk;
1331eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1332eb910715SAlp Dener   PetscErrorCode ierr;
1333eb910715SAlp Dener 
1334eb910715SAlp Dener   PetscFunctionBegin;
1335eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1336eb910715SAlp Dener 
1337eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1338eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1339eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1340eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1341eb910715SAlp Dener 
1342eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1343eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1344eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1345eb910715SAlp Dener 
1346eb910715SAlp Dener   tao->data = (void*)bnk;
1347eb910715SAlp Dener 
134866ed3702SAlp Dener   /*  Hessian shifting parameters */
1349eb910715SAlp Dener   bnk->sval   = 0.0;
1350eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1351eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1352eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1353eb910715SAlp Dener 
1354eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1355eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1356eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1357eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1358eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1359eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1360eb910715SAlp Dener 
1361eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1362eb910715SAlp Dener   bnk->nu1 = 0.25;
1363eb910715SAlp Dener   bnk->nu2 = 0.50;
1364eb910715SAlp Dener   bnk->nu3 = 1.00;
1365eb910715SAlp Dener   bnk->nu4 = 1.25;
1366eb910715SAlp Dener 
1367eb910715SAlp Dener   bnk->omega1 = 0.25;
1368eb910715SAlp Dener   bnk->omega2 = 0.50;
1369eb910715SAlp Dener   bnk->omega3 = 1.00;
1370eb910715SAlp Dener   bnk->omega4 = 2.00;
1371eb910715SAlp Dener   bnk->omega5 = 4.00;
1372eb910715SAlp Dener 
1373eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1374eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1375eb910715SAlp Dener   bnk->eta2 = 0.25;
1376eb910715SAlp Dener   bnk->eta3 = 0.50;
1377eb910715SAlp Dener   bnk->eta4 = 0.90;
1378eb910715SAlp Dener 
1379eb910715SAlp Dener   bnk->alpha1 = 0.25;
1380eb910715SAlp Dener   bnk->alpha2 = 0.50;
1381eb910715SAlp Dener   bnk->alpha3 = 1.00;
1382eb910715SAlp Dener   bnk->alpha4 = 2.00;
1383eb910715SAlp Dener   bnk->alpha5 = 4.00;
1384eb910715SAlp Dener 
1385eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1386eb910715SAlp Dener   bnk->mu1 = 0.10;
1387eb910715SAlp Dener   bnk->mu2 = 0.50;
1388eb910715SAlp Dener 
1389eb910715SAlp Dener   bnk->gamma1 = 0.25;
1390eb910715SAlp Dener   bnk->gamma2 = 0.50;
1391eb910715SAlp Dener   bnk->gamma3 = 2.00;
1392eb910715SAlp Dener   bnk->gamma4 = 4.00;
1393eb910715SAlp Dener 
1394eb910715SAlp Dener   bnk->theta = 0.05;
1395eb910715SAlp Dener 
1396eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1397eb910715SAlp Dener   bnk->mu1_i = 0.35;
1398eb910715SAlp Dener   bnk->mu2_i = 0.50;
1399eb910715SAlp Dener 
1400eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1401eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1402eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1403eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1404eb910715SAlp Dener 
1405eb910715SAlp Dener   bnk->theta_i = 0.25;
1406eb910715SAlp Dener 
1407eb910715SAlp Dener   /*  Remaining parameters */
1408c0f10754SAlp Dener   bnk->max_cg_its = 0;
1409eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1410eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1411770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
14120a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
14130a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
141462675beeSAlp Dener   bnk->dmin = 1.0e-6;
141562675beeSAlp Dener   bnk->dmax = 1.0e6;
1416eb910715SAlp Dener 
1417*e031d6f5SAlp Dener   bnk->pc_type         = BNK_PC_AHESS;
1418eb910715SAlp Dener   bnk->bfgs_scale_type = BFGS_SCALE_PHESS;
1419eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
1420fed79b8eSAlp Dener   bnk->update_type     = BNK_UPDATE_INTERPOLATION;
14212f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1422eb910715SAlp Dener 
1423*e031d6f5SAlp Dener   /* Create the embedded BNCG solver */
1424*e031d6f5SAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
1425*e031d6f5SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
1426*e031d6f5SAlp Dener   ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr);
1427*e031d6f5SAlp Dener   ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
1428*e031d6f5SAlp Dener 
1429c0f10754SAlp Dener   /* Create the line search */
1430eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1431eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1432*e031d6f5SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1433eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1434eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1435eb910715SAlp Dener 
1436eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1437eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1438eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1439eb910715SAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr);
1440eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1441eb910715SAlp Dener   PetscFunctionReturn(0);
1442eb910715SAlp Dener }
1443