xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision 61be54a68cd238714af883d2215bb04911cc1c21)
1eb910715SAlp Dener #include <petsctaolinesearch.h>
2eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h>
3eb910715SAlp Dener 
4eb910715SAlp Dener #include <petscksp.h>
5eb910715SAlp Dener 
6e031d6f5SAlp Dener static const char *BNK_PC[64] = {"none", "ahess", "bfgs", "petsc"};
7e031d6f5SAlp Dener static const char *BFGS_SCALE[64] = {"ahess", "phess", "bfgs"};
8e031d6f5SAlp Dener static const char *BNK_INIT[64] = {"constant", "direction", "interpolation"};
9e031d6f5SAlp Dener static const char *BNK_UPDATE[64] = {"step", "reduction", "interpolation"};
10e031d6f5SAlp Dener static const char *BNK_AS[64] = {"none", "bertsekas"};
11e031d6f5SAlp Dener 
12e031d6f5SAlp Dener /*------------------------------------------------------------*/
13e031d6f5SAlp 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;
42e031d6f5SAlp 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);
53e031d6f5SAlp 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);
61*61be54a6SAlp Dener   ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
62*61be54a6SAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
63*61be54a6SAlp Dener   ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
6408752603SAlp Dener   ierr = VecNorm(tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
6528017e9fSAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
6628017e9fSAlp Dener 
67c0f10754SAlp Dener   /* Test the initial point for convergence */
68e031d6f5SAlp Dener   ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr);
69e031d6f5SAlp Dener   ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr);
70e031d6f5SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
71e031d6f5SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
72c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
73c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
74c0f10754SAlp Dener 
75e031d6f5SAlp Dener   /* Reset KSP stopping reason counters */
76eb910715SAlp Dener   bnk->ksp_atol = 0;
77eb910715SAlp Dener   bnk->ksp_rtol = 0;
78eb910715SAlp Dener   bnk->ksp_dtol = 0;
79eb910715SAlp Dener   bnk->ksp_ctol = 0;
80eb910715SAlp Dener   bnk->ksp_negc = 0;
81eb910715SAlp Dener   bnk->ksp_iter = 0;
82eb910715SAlp Dener   bnk->ksp_othr = 0;
83eb910715SAlp Dener 
84e031d6f5SAlp Dener   /* Reset accepted step type counters */
85e031d6f5SAlp Dener   bnk->tot_cg_its = 0;
86e031d6f5SAlp Dener   bnk->newt = 0;
87e031d6f5SAlp Dener   bnk->bfgs = 0;
88e031d6f5SAlp Dener   bnk->sgrad = 0;
89e031d6f5SAlp Dener   bnk->grad = 0;
90e031d6f5SAlp Dener 
91fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
92fed79b8eSAlp Dener   bnk->pert = bnk->sval;
93fed79b8eSAlp Dener 
94937a31a1SAlp Dener   /* Reset initial steplength to zero (this helps BNCG reset its direction internally) */
95937a31a1SAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
96937a31a1SAlp Dener 
97e031d6f5SAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
98e031d6f5SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
99e031d6f5SAlp Dener     if (!bnk->M) {
100eb910715SAlp Dener       ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr);
101eb910715SAlp Dener       ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr);
102eb910715SAlp Dener       ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&bnk->M);CHKERRQ(ierr);
103eb910715SAlp Dener       ierr = MatLMVMAllocateVectors(bnk->M,tao->solution);CHKERRQ(ierr);
104eb910715SAlp Dener     }
105e031d6f5SAlp Dener     if (bnk->bfgs_scale_type != BFGS_SCALE_BFGS && !bnk->Diag) {
106e031d6f5SAlp Dener       ierr = VecDuplicate(tao->solution,&bnk->Diag);CHKERRQ(ierr);
1075e9b73cbSAlp Dener     }
108e031d6f5SAlp Dener   }
109e031d6f5SAlp Dener 
110e031d6f5SAlp Dener   /* Prepare the min/max vectors for safeguarding diagonal scales */
11162675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
11262675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
113eb910715SAlp Dener 
114eb910715SAlp Dener   /* Modify the preconditioner to use the bfgs approximation */
115eb910715SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
116eb910715SAlp Dener   switch(bnk->pc_type) {
117eb910715SAlp Dener   case BNK_PC_NONE:
118eb910715SAlp Dener     ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr);
119eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
120eb910715SAlp Dener     break;
121eb910715SAlp Dener 
122eb910715SAlp Dener   case BNK_PC_AHESS:
123eb910715SAlp Dener     ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr);
124eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
125eb910715SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
126eb910715SAlp Dener     break;
127eb910715SAlp Dener 
128eb910715SAlp Dener   case BNK_PC_BFGS:
129eb910715SAlp Dener     ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr);
130eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
131eb910715SAlp Dener     ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr);
132eb910715SAlp Dener     ierr = PCShellSetContext(pc, bnk->M);CHKERRQ(ierr);
133eb910715SAlp Dener     ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr);
134eb910715SAlp Dener     break;
135eb910715SAlp Dener 
136eb910715SAlp Dener   default:
137eb910715SAlp Dener     /* Use the pc method set by pc_type */
138eb910715SAlp Dener     break;
139eb910715SAlp Dener   }
140eb910715SAlp Dener 
141eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
142eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
143c0f10754SAlp Dener   *needH = PETSC_TRUE;
144eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
14562675beeSAlp Dener     switch(initType) {
146eb910715SAlp Dener     case BNK_INIT_CONSTANT:
147eb910715SAlp Dener       /* Use the initial radius specified */
148c0f10754SAlp Dener       tao->trust = tao->trust0;
149eb910715SAlp Dener       break;
150eb910715SAlp Dener 
151eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
152c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
153eb910715SAlp Dener       max_radius = 0.0;
15408752603SAlp Dener       tao->trust = tao->trust0;
155eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1560a4511e9SAlp Dener         f_min = bnk->f;
157eb910715SAlp Dener         sigma = 0.0;
158eb910715SAlp Dener 
159c0f10754SAlp Dener         if (*needH) {
16062602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
161e031d6f5SAlp Dener           ierr = TaoBNKComputeHessian(tao);CHKERRQ(ierr);
16208752603SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, BNK_AS_NONE);CHKERRQ(ierr);
16328017e9fSAlp Dener           if (bnk->inactive_idx) {
1642ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
16528017e9fSAlp Dener           } else {
16608752603SAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
16728017e9fSAlp Dener           }
168c0f10754SAlp Dener           *needH = PETSC_FALSE;
169eb910715SAlp Dener         }
170eb910715SAlp Dener 
171eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
17262602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
17362602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
17462602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
17562602cfbSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
176770b7498SAlp Dener           /* Recompute the step after bound snapping so that it can be used in predicted decrease calculation later */
177eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
17862602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
17962602cfbSAlp Dener           /* Compute the objective at the trial */
18062602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
18162602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
182eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
183eb910715SAlp Dener             tau = bnk->gamma1_i;
184eb910715SAlp Dener           } else {
1850a4511e9SAlp Dener             if (ftrial < f_min) {
1860a4511e9SAlp Dener               f_min = ftrial;
187eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
188eb910715SAlp Dener             }
18908752603SAlp Dener 
190770b7498SAlp Dener             /* Compute the predicted and actual reduction */
1912ab2a32cSAlp Dener             if (bnk->inactive_idx) {
19208752603SAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
19308752603SAlp Dener               ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1942ab2a32cSAlp Dener             } else {
19508752603SAlp Dener               bnk->X_inactive = bnk->W;
19608752603SAlp Dener               bnk->inactive_work = bnk->Xwork;
1972ab2a32cSAlp Dener             }
19808752603SAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
19908752603SAlp Dener             ierr = VecDot(bnk->X_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
2002ab2a32cSAlp Dener             if (bnk->inactive_idx) {
20108752603SAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
20208752603SAlp Dener               ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
2032ab2a32cSAlp Dener             }
204eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
205eb910715SAlp Dener             actred = bnk->f - ftrial;
20608752603SAlp Dener             if ((PetscAbsScalar(actred) <= bnk->epsilon) &&
20708752603SAlp Dener                 (PetscAbsScalar(prered) <= bnk->epsilon)) {
208eb910715SAlp Dener               kappa = 1.0;
20908752603SAlp Dener             }
21008752603SAlp Dener             else {
211eb910715SAlp Dener               kappa = actred / prered;
212eb910715SAlp Dener             }
213eb910715SAlp Dener 
214eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
215eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
216eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
217eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
218eb910715SAlp Dener 
219eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
220eb910715SAlp Dener               /*  Great agreement */
221eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
222eb910715SAlp Dener 
223eb910715SAlp Dener               if (tau_max < 1.0) {
224eb910715SAlp Dener                 tau = bnk->gamma3_i;
22508752603SAlp Dener               }
22608752603SAlp Dener               else if (tau_max > bnk->gamma4_i) {
227eb910715SAlp Dener                 tau = bnk->gamma4_i;
22808752603SAlp Dener               }
22908752603SAlp Dener               else {
230eb910715SAlp Dener                 tau = tau_max;
231eb910715SAlp Dener               }
23208752603SAlp Dener             }
23308752603SAlp Dener             else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
234eb910715SAlp Dener               /*  Good agreement */
235eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
236eb910715SAlp Dener 
237eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
238eb910715SAlp Dener                 tau = bnk->gamma2_i;
239eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
240eb910715SAlp Dener                 tau = bnk->gamma3_i;
241eb910715SAlp Dener               } else {
242eb910715SAlp Dener                 tau = tau_max;
243eb910715SAlp Dener               }
24408752603SAlp Dener             }
24508752603SAlp Dener             else {
246eb910715SAlp Dener               /*  Not good agreement */
247eb910715SAlp Dener               if (tau_min > 1.0) {
248eb910715SAlp Dener                 tau = bnk->gamma2_i;
249eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
250eb910715SAlp Dener                 tau = bnk->gamma1_i;
251eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
252eb910715SAlp Dener                 tau = bnk->gamma1_i;
25308752603SAlp Dener               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) &&
25408752603SAlp Dener                         ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
255eb910715SAlp Dener                 tau = tau_1;
25608752603SAlp Dener               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) &&
25708752603SAlp Dener                         ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
258eb910715SAlp Dener                 tau = tau_2;
259eb910715SAlp Dener               } else {
260eb910715SAlp Dener                 tau = tau_max;
261eb910715SAlp Dener               }
262eb910715SAlp Dener             }
263eb910715SAlp Dener           }
264eb910715SAlp Dener           tao->trust = tau * tao->trust;
265eb910715SAlp Dener         }
266eb910715SAlp Dener 
2670a4511e9SAlp Dener         if (f_min < bnk->f) {
268937a31a1SAlp Dener           /* We accidentally found a solution better than the initial, so accept it */
2690a4511e9SAlp Dener           bnk->f = f_min;
270937a31a1SAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
271eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
27287602d1eSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
273937a31a1SAlp Dener           ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr);
274937a31a1SAlp Dener           ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr);
27509164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
276*61be54a6SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
277*61be54a6SAlp Dener           ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
278*61be54a6SAlp Dener           ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
279937a31a1SAlp Dener           /* Compute gradient at the new iterate and flip switch to compute the Hessian later */
280eb910715SAlp Dener           ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
281eb910715SAlp Dener           if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN");
282c0f10754SAlp Dener           *needH = PETSC_TRUE;
283937a31a1SAlp Dener           /* Test the new step for convergence */
284e031d6f5SAlp Dener           ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr);
285e031d6f5SAlp Dener           ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr);
286e031d6f5SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
287e031d6f5SAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
288eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
289eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
290937a31a1SAlp Dener           /* active BNCG recycling early because we have a stepdirection computed */
291937a31a1SAlp Dener           ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
292eb910715SAlp Dener         }
293eb910715SAlp Dener       }
294eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
295e031d6f5SAlp Dener 
296e031d6f5SAlp Dener       /* Ensure that the trust radius is within the limits */
297e031d6f5SAlp Dener       tao->trust = PetscMax(tao->trust, bnk->min_radius);
298e031d6f5SAlp Dener       tao->trust = PetscMin(tao->trust, bnk->max_radius);
299eb910715SAlp Dener       break;
300eb910715SAlp Dener 
301eb910715SAlp Dener     default:
302eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
303eb910715SAlp Dener       tao->trust = 0.0;
304eb910715SAlp Dener       break;
305eb910715SAlp Dener     }
306eb910715SAlp Dener   }
307e031d6f5SAlp Dener 
308eb910715SAlp Dener   /* Set initial scaling for the BFGS preconditioner
309eb910715SAlp Dener      This step is done after computing the initial trust-region radius
310eb910715SAlp Dener      since the function value may have decreased */
311eb910715SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
3129b6ef848SAlp Dener     delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
313eb910715SAlp Dener     ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
314eb910715SAlp Dener   }
315eb910715SAlp Dener   PetscFunctionReturn(0);
316eb910715SAlp Dener }
317eb910715SAlp Dener 
318df278d8fSAlp Dener /*------------------------------------------------------------*/
319df278d8fSAlp Dener 
32062675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */
32162675beeSAlp Dener 
32262675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
32362675beeSAlp Dener {
32462675beeSAlp Dener   PetscErrorCode               ierr;
32562675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
32662675beeSAlp Dener 
32762675beeSAlp Dener   PetscFunctionBegin;
32862675beeSAlp Dener   /* Compute the Hessian */
32962675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
33062675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
33162675beeSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
33262675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
33362675beeSAlp Dener     /* Update the BFGS diagonal scaling */
33462675beeSAlp Dener     if (BFGS_SCALE_AHESS == bnk->bfgs_scale_type) {
33562675beeSAlp Dener       ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr);
33662675beeSAlp Dener       ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
33762675beeSAlp Dener       ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
33862675beeSAlp Dener       ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
33962675beeSAlp Dener       ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
34062675beeSAlp Dener     }
34162675beeSAlp Dener   }
34262675beeSAlp Dener   PetscFunctionReturn(0);
34362675beeSAlp Dener }
34462675beeSAlp Dener 
34562675beeSAlp Dener /*------------------------------------------------------------*/
34662675beeSAlp Dener 
3472f75a4aaSAlp Dener /* Routine for estimating the active set */
3482f75a4aaSAlp Dener 
34908752603SAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao, PetscInt asType)
3502f75a4aaSAlp Dener {
3512f75a4aaSAlp Dener   PetscErrorCode               ierr;
3522f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
353*61be54a6SAlp Dener   PetscBool                    hessComputed;
3542f75a4aaSAlp Dener 
3552f75a4aaSAlp Dener   PetscFunctionBegin;
35608752603SAlp Dener   switch (asType) {
3572f75a4aaSAlp Dener   case BNK_AS_NONE:
3582f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
3592f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
3602f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
3612f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
3622f75a4aaSAlp Dener     break;
3632f75a4aaSAlp Dener 
3642f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3652f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
3662f75a4aaSAlp Dener     if (BNK_PC_BFGS == bnk->pc_type) {
3672f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
3685e9b73cbSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
3692f75a4aaSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3702f75a4aaSAlp Dener     } else {
371*61be54a6SAlp Dener       ierr = MatAssembled(tao->hessian, &hessComputed);CHKERRQ(ierr);
372*61be54a6SAlp Dener       if (hessComputed) {
3739b6ef848SAlp Dener         /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3742f75a4aaSAlp Dener         ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3759b6ef848SAlp Dener         ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3769b6ef848SAlp Dener         ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3772f75a4aaSAlp Dener         ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3782f75a4aaSAlp Dener         ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
379*61be54a6SAlp Dener       } else {
380*61be54a6SAlp Dener         /* If the Hessian does not exist yet, we will simply use gradient step */
381*61be54a6SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
382*61be54a6SAlp Dener       }
3832f75a4aaSAlp Dener     }
3842f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
3850a4511e9SAlp 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);
3862f75a4aaSAlp Dener 
3872f75a4aaSAlp Dener   default:
3882f75a4aaSAlp Dener     break;
3892f75a4aaSAlp Dener   }
3902f75a4aaSAlp Dener   PetscFunctionReturn(0);
3912f75a4aaSAlp Dener }
3922f75a4aaSAlp Dener 
3932f75a4aaSAlp Dener /*------------------------------------------------------------*/
3942f75a4aaSAlp Dener 
3952f75a4aaSAlp Dener /* Routine for bounding the step direction */
3962f75a4aaSAlp Dener 
3972f75a4aaSAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, Vec step)
3982f75a4aaSAlp Dener {
3992f75a4aaSAlp Dener   PetscErrorCode               ierr;
4002f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
4012f75a4aaSAlp Dener 
4022f75a4aaSAlp Dener   PetscFunctionBegin;
4032f75a4aaSAlp Dener   switch (bnk->as_type) {
4042f75a4aaSAlp Dener   case BNK_AS_NONE:
405*61be54a6SAlp Dener     if (bnk->active_idx) {ierr = VecISSet(step, bnk->active_idx, 0.0);CHKERRQ(ierr);}
4062f75a4aaSAlp Dener     break;
4072f75a4aaSAlp Dener 
4082f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
4092f75a4aaSAlp Dener     ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, step);CHKERRQ(ierr);
4102f75a4aaSAlp Dener     break;
4112f75a4aaSAlp Dener 
4122f75a4aaSAlp Dener   default:
4132f75a4aaSAlp Dener     break;
4142f75a4aaSAlp Dener   }
4152f75a4aaSAlp Dener   PetscFunctionReturn(0);
4162f75a4aaSAlp Dener }
4172f75a4aaSAlp Dener 
418e031d6f5SAlp Dener /*------------------------------------------------------------*/
419e031d6f5SAlp Dener 
420e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to
421e031d6f5SAlp Dener    accelerate Newton convergence.
422e031d6f5SAlp Dener 
423e031d6f5SAlp Dener    In practice, this approach simply trades off Hessian evaluations
424e031d6f5SAlp Dener    for more gradient evaluations.
425e031d6f5SAlp Dener */
426e031d6f5SAlp Dener 
427c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
428c0f10754SAlp Dener {
429c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
430c0f10754SAlp Dener   PetscErrorCode               ierr;
431c0f10754SAlp Dener 
432c0f10754SAlp Dener   PetscFunctionBegin;
433c0f10754SAlp Dener   *terminate = PETSC_FALSE;
434c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
435c0f10754SAlp Dener     /* Copy the current solution, unprojected gradient and step info into BNCG */
436c0f10754SAlp Dener     bnk->bncg_ctx->f = bnk->f;
437937a31a1SAlp Dener     ierr = VecCopy(tao->solution, bnk->bncg->solution);CHKERRQ(ierr);
438c0f10754SAlp Dener     ierr = VecCopy(bnk->unprojected_gradient, bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
439c0f10754SAlp Dener     ierr = VecCopy(tao->stepdirection, bnk->bncg->stepdirection);CHKERRQ(ierr);
440c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
441c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
442c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
443c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
444c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
445c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
446c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
447e031d6f5SAlp Dener     bnk->tot_cg_its += bnk->bncg->niter;
448c0f10754SAlp Dener     /* Extract the BNCG solution out and save it into BNK */
449c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
450c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg->solution, tao->solution);
451c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg_ctx->unprojected_gradient, bnk->unprojected_gradient);
452937a31a1SAlp Dener     ierr = VecCopy(bnk->bncg->gradient, tao->gradient);CHKERRQ(ierr);
453c0f10754SAlp 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) {
454c0f10754SAlp Dener       *terminate = PETSC_TRUE;
455*61be54a6SAlp Dener     } else {
456*61be54a6SAlp Dener       ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);
457c0f10754SAlp Dener     }
458c0f10754SAlp Dener   }
459c0f10754SAlp Dener   PetscFunctionReturn(0);
460c0f10754SAlp Dener }
461c0f10754SAlp Dener 
4622f75a4aaSAlp Dener /*------------------------------------------------------------*/
4632f75a4aaSAlp Dener 
464c0f10754SAlp Dener /* Routine for computing the Newton step. */
465df278d8fSAlp Dener 
46662675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason)
467eb910715SAlp Dener {
468eb910715SAlp Dener   PetscErrorCode               ierr;
469eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
470eb910715SAlp Dener 
471e465cd6fSAlp Dener   PetscReal                    delta;
472eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
473eb910715SAlp Dener   PetscInt                     kspits;
474eb910715SAlp Dener 
475eb910715SAlp Dener   PetscFunctionBegin;
4765e9b73cbSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
4772f75a4aaSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) { ierr = MatLMVMSetInactive(bnk->M, bnk->inactive_idx);CHKERRQ(ierr); }
4782f75a4aaSAlp Dener   if (bnk->inactive_idx) {
4795e9b73cbSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
4805e9b73cbSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
481eb3ba6a7SAlp Dener     if (tao->hessian == tao->hessian_pre) {
482eb3ba6a7SAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
483eb3ba6a7SAlp Dener     } else {
4845e9b73cbSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
4855e9b73cbSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
486eb3ba6a7SAlp Dener     }
4872f75a4aaSAlp Dener   } else {
48862675beeSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
48962675beeSAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);
49062675beeSAlp Dener     if (tao->hessian == tao->hessian_pre) {
49162675beeSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
49262675beeSAlp Dener     } else {
49362675beeSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
49462675beeSAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);
49562675beeSAlp Dener     }
49662675beeSAlp Dener   }
49762675beeSAlp Dener 
49862675beeSAlp Dener   /* Shift the reduced Hessian matrix */
49962675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
50062675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
50162675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
50262675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
50362675beeSAlp Dener     }
50462675beeSAlp Dener   }
50562675beeSAlp Dener 
50662675beeSAlp Dener   /* Update the diagonal scaling for the BFGS preconditioner, this time with the Hessian perturbation */
50762675beeSAlp Dener   if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_PHESS == bnk->bfgs_scale_type)) {
50862675beeSAlp Dener     /* Obtain diagonal for the bfgs preconditioner  */
5095e9b73cbSAlp Dener     ierr = VecSet(bnk->Diag, 1.0);CHKERRQ(ierr);
5105e9b73cbSAlp Dener     if (bnk->inactive_idx) {
5115e9b73cbSAlp Dener       ierr = VecGetSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
5125e9b73cbSAlp Dener     } else {
5135e9b73cbSAlp Dener       bnk->Diag_red = bnk->Diag;
5145e9b73cbSAlp Dener     }
5155e9b73cbSAlp Dener     ierr = MatGetDiagonal(bnk->H_inactive, bnk->Diag_red);CHKERRQ(ierr);
5165e9b73cbSAlp Dener     if (bnk->inactive_idx) {
5175e9b73cbSAlp Dener       ierr = VecRestoreSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
5185e9b73cbSAlp Dener     }
51962675beeSAlp Dener     ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
52062675beeSAlp Dener     ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
52162675beeSAlp Dener     ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
52262675beeSAlp Dener     ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
5232f75a4aaSAlp Dener   }
52409164190SAlp Dener 
525eb910715SAlp Dener   /* Solve the Newton system of equations */
526937a31a1SAlp Dener   tao->ksp_its = 0;
5272f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
5285e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
52909164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
5305e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
5315e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5325e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5335e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5345e9b73cbSAlp Dener   } else {
5355e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
5365e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
53728017e9fSAlp Dener   }
538eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
539fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5405e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
541eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
542eb910715SAlp Dener     tao->ksp_its+=kspits;
543eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
544080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
545eb910715SAlp Dener 
546eb910715SAlp Dener     if (0.0 == tao->trust) {
547eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
548080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
549080d2917SAlp Dener         tao->trust = bnk->dnorm;
550eb910715SAlp Dener 
551eb910715SAlp Dener         /* Modify the radius if it is too large or small */
552eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
553eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
554eb910715SAlp Dener       } else {
555eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
556eb910715SAlp Dener            the trust-region subproblem to get a direction */
557eb910715SAlp Dener         tao->trust = tao->trust0;
558eb910715SAlp Dener 
559eb910715SAlp Dener         /* Modify the radius if it is too large or small */
560eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
561eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
562eb910715SAlp Dener 
563fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5645e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
565eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
566eb910715SAlp Dener         tao->ksp_its+=kspits;
567eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
568080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
569eb910715SAlp Dener 
570080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
571eb910715SAlp Dener       }
572eb910715SAlp Dener     }
573eb910715SAlp Dener   } else {
5745e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
575eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
576eb910715SAlp Dener     tao->ksp_its += kspits;
577eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
578eb910715SAlp Dener   }
5795e9b73cbSAlp Dener   /* Restore sub vectors back */
5805e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5815e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5825e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5835e9b73cbSAlp Dener   }
584770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
585fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
5862f75a4aaSAlp Dener   ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
587770b7498SAlp Dener 
588770b7498SAlp Dener   /* Record convergence reasons */
589e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
590e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
591770b7498SAlp Dener     ++bnk->ksp_atol;
592e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
593770b7498SAlp Dener     ++bnk->ksp_rtol;
594e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
595770b7498SAlp Dener     ++bnk->ksp_ctol;
596e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
597770b7498SAlp Dener     ++bnk->ksp_negc;
598e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
599770b7498SAlp Dener     ++bnk->ksp_dtol;
600e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
601770b7498SAlp Dener     ++bnk->ksp_iter;
602770b7498SAlp Dener   } else {
603770b7498SAlp Dener     ++bnk->ksp_othr;
604770b7498SAlp Dener   }
605fed79b8eSAlp Dener 
606fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
607fed79b8eSAlp Dener   if (bnk->pc_type == BNK_PC_BFGS) {
608fed79b8eSAlp Dener     ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
609e465cd6fSAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 1)) {
610fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
6119b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
612eb910715SAlp Dener       ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
613eb910715SAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
61409164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
615eb910715SAlp Dener     }
616fed79b8eSAlp Dener   }
617e465cd6fSAlp Dener   PetscFunctionReturn(0);
618e465cd6fSAlp Dener }
619eb910715SAlp Dener 
62062675beeSAlp Dener /*------------------------------------------------------------*/
62162675beeSAlp Dener 
6225e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
6235e9b73cbSAlp Dener 
6245e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
6255e9b73cbSAlp Dener {
6265e9b73cbSAlp Dener   PetscErrorCode               ierr;
6275e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
6285e9b73cbSAlp Dener 
6295e9b73cbSAlp Dener   PetscFunctionBegin;
6305e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
6315e9b73cbSAlp Dener   if (bnk->inactive_idx){
6325e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6335e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6345e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6355e9b73cbSAlp Dener   } else {
6365e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
6375e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
6385e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
6395e9b73cbSAlp Dener   }
6405e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
6415e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
6425e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
6435e9b73cbSAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);
6445e9b73cbSAlp Dener   /* Restore the sub vectors */
6455e9b73cbSAlp Dener   if (bnk->inactive_idx){
6465e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6475e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6485e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6495e9b73cbSAlp Dener   }
6505e9b73cbSAlp Dener   PetscFunctionReturn(0);
6515e9b73cbSAlp Dener }
6525e9b73cbSAlp Dener 
6535e9b73cbSAlp Dener /*------------------------------------------------------------*/
6545e9b73cbSAlp Dener 
65562675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
65662675beeSAlp Dener 
65762675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
65862675beeSAlp Dener    in the event that the Newton step fails the test.
65962675beeSAlp Dener */
66062675beeSAlp Dener 
661e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
662e465cd6fSAlp Dener {
663e465cd6fSAlp Dener   PetscErrorCode               ierr;
664e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
665e465cd6fSAlp Dener 
666e465cd6fSAlp Dener   PetscReal                    gdx, delta, e_min;
667e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
668e465cd6fSAlp Dener 
669e465cd6fSAlp Dener   PetscFunctionBegin;
670080d2917SAlp Dener   ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
671eb910715SAlp Dener   if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
672eb910715SAlp Dener     /* Newton step is not descent or direction produced Inf or NaN
673eb910715SAlp Dener        Update the perturbation for next time */
674eb910715SAlp Dener     if (bnk->pert <= 0.0) {
675eb910715SAlp Dener       /* Initialize the perturbation */
676eb910715SAlp Dener       bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
677eb910715SAlp Dener       if (bnk->is_gltr) {
678eb910715SAlp Dener         ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
679eb910715SAlp Dener         bnk->pert = PetscMax(bnk->pert, -e_min);
680eb910715SAlp Dener       }
681eb910715SAlp Dener     } else {
682eb910715SAlp Dener       /* Increase the perturbation */
683eb910715SAlp Dener       bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
684eb910715SAlp Dener     }
685eb910715SAlp Dener 
686eb910715SAlp Dener     if (BNK_PC_BFGS != bnk->pc_type) {
687eb910715SAlp Dener       /* We don't have the bfgs matrix around and updated
688eb910715SAlp Dener          Must use gradient direction in this case */
689080d2917SAlp Dener       ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
690eb910715SAlp Dener       *stepType = BNK_GRADIENT;
691eb910715SAlp Dener     } else {
692eb910715SAlp Dener       /* Attempt to use the BFGS direction */
6932ab2a32cSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
69409164190SAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
695eb910715SAlp Dener 
6968d5ead36SAlp Dener       /* Check for success (descent direction)
6978d5ead36SAlp Dener          NOTE: Negative gdx here means not a descent direction because
6988d5ead36SAlp Dener          the fall-back step is missing a negative sign. */
699080d2917SAlp Dener       ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
7008d5ead36SAlp Dener       if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
701eb910715SAlp Dener         /* BFGS direction is not descent or direction produced not a number
702eb910715SAlp Dener            We can assert bfgsUpdates > 1 in this case because
703eb910715SAlp Dener            the first solve produces the scaled gradient direction,
704eb910715SAlp Dener            which is guaranteed to be descent */
705eb910715SAlp Dener 
706eb910715SAlp Dener         /* Use steepest descent direction (scaled) */
7079b6ef848SAlp Dener         delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
708eb910715SAlp Dener         ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
709eb910715SAlp Dener         ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
71009164190SAlp Dener         ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
71109164190SAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
712eb910715SAlp Dener 
713eb910715SAlp Dener         *stepType = BNK_SCALED_GRADIENT;
714eb910715SAlp Dener       } else {
715770b7498SAlp Dener         ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
716eb910715SAlp Dener         if (1 == bfgsUpdates) {
717eb910715SAlp Dener           /* The first BFGS direction is always the scaled gradient */
718eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
719eb910715SAlp Dener         } else {
720eb910715SAlp Dener           *stepType = BNK_BFGS;
721eb910715SAlp Dener         }
722eb910715SAlp Dener       }
723eb910715SAlp Dener     }
7248d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
7258d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
7262f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
727eb910715SAlp Dener   } else {
728eb910715SAlp Dener     /* Computed Newton step is descent */
729eb910715SAlp Dener     switch (ksp_reason) {
730eb910715SAlp Dener     case KSP_DIVERGED_NANORINF:
731eb910715SAlp Dener     case KSP_DIVERGED_BREAKDOWN:
732eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_MAT:
733eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_PC:
734eb910715SAlp Dener     case KSP_CONVERGED_CG_NEG_CURVE:
735eb910715SAlp Dener       /* Matrix or preconditioner is indefinite; increase perturbation */
736eb910715SAlp Dener       if (bnk->pert <= 0.0) {
737eb910715SAlp Dener         /* Initialize the perturbation */
738eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
739eb910715SAlp Dener         if (bnk->is_gltr) {
740eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
741eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
742eb910715SAlp Dener         }
743eb910715SAlp Dener       } else {
744eb910715SAlp Dener         /* Increase the perturbation */
745eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
746eb910715SAlp Dener       }
747eb910715SAlp Dener       break;
748eb910715SAlp Dener 
749eb910715SAlp Dener     default:
750eb910715SAlp Dener       /* Newton step computation is good; decrease perturbation */
751eb910715SAlp Dener       bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
752eb910715SAlp Dener       if (bnk->pert < bnk->pmin) {
753eb910715SAlp Dener         bnk->pert = 0.0;
754eb910715SAlp Dener       }
755eb910715SAlp Dener       break;
756eb910715SAlp Dener     }
757fed79b8eSAlp Dener     *stepType = BNK_NEWTON;
758eb910715SAlp Dener   }
759eb910715SAlp Dener   PetscFunctionReturn(0);
760eb910715SAlp Dener }
761eb910715SAlp Dener 
762df278d8fSAlp Dener /*------------------------------------------------------------*/
763df278d8fSAlp Dener 
764df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
765df278d8fSAlp Dener 
766df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
767df278d8fSAlp Dener   Newton step does not produce a valid step length.
768df278d8fSAlp Dener */
769df278d8fSAlp Dener 
770937a31a1SAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt *stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
771c14b763aSAlp Dener {
772c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
773c14b763aSAlp Dener   PetscErrorCode ierr;
774c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
775c14b763aSAlp Dener 
776c14b763aSAlp Dener   PetscReal      e_min, gdx, delta;
777c14b763aSAlp Dener   PetscInt       bfgsUpdates;
778c14b763aSAlp Dener 
779c14b763aSAlp Dener   PetscFunctionBegin;
780c14b763aSAlp Dener   /* Perform the linesearch */
781c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
782c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
783c14b763aSAlp Dener 
784937a31a1SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && *stepType != BNK_GRADIENT) {
785c14b763aSAlp Dener     /* Linesearch failed, revert solution */
786c14b763aSAlp Dener     bnk->f = bnk->fold;
787c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
788c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
789c14b763aSAlp Dener 
790937a31a1SAlp Dener     switch(*stepType) {
791c14b763aSAlp Dener     case BNK_NEWTON:
7928d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
793c14b763aSAlp Dener          Update the perturbation for next time */
794c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
795c14b763aSAlp Dener         /* Initialize the perturbation */
796c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
797c14b763aSAlp Dener         if (bnk->is_gltr) {
798c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
799c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
800c14b763aSAlp Dener         }
801c14b763aSAlp Dener       } else {
802c14b763aSAlp Dener         /* Increase the perturbation */
803c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
804c14b763aSAlp Dener       }
805c14b763aSAlp Dener 
806c14b763aSAlp Dener       if (BNK_PC_BFGS != bnk->pc_type) {
807c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
808c14b763aSAlp Dener            Must use gradient direction in this case */
809937a31a1SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
810937a31a1SAlp Dener         *stepType = BNK_GRADIENT;
811c14b763aSAlp Dener       } else {
812c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
813937a31a1SAlp Dener         ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
814c14b763aSAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
8158d5ead36SAlp Dener         /* Check for success (descent direction)
8168d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
817c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
818c14b763aSAlp Dener         if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
819c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
820c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
821c14b763aSAlp Dener              Use steepest descent direction (scaled) */
8229b6ef848SAlp Dener           delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
823c14b763aSAlp Dener           ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
824c14b763aSAlp Dener           ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
825c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
826c14b763aSAlp Dener           ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
827c14b763aSAlp Dener 
828c14b763aSAlp Dener           bfgsUpdates = 1;
829937a31a1SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
830c14b763aSAlp Dener         } else {
831c14b763aSAlp Dener           ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
832c14b763aSAlp Dener           if (1 == bfgsUpdates) {
833c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
834937a31a1SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
835c14b763aSAlp Dener           } else {
836937a31a1SAlp Dener             *stepType = BNK_BFGS;
837c14b763aSAlp Dener           }
838c14b763aSAlp Dener         }
839c14b763aSAlp Dener       }
840c14b763aSAlp Dener       break;
841c14b763aSAlp Dener 
842c14b763aSAlp Dener     case BNK_BFGS:
843c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
844c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
845c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
8469b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
847c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
848c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
849c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
850937a31a1SAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
851c14b763aSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
852c14b763aSAlp Dener 
853c14b763aSAlp Dener       bfgsUpdates = 1;
854937a31a1SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
855c14b763aSAlp Dener       break;
856c14b763aSAlp Dener 
857c14b763aSAlp Dener     case BNK_SCALED_GRADIENT:
858c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
859c14b763aSAlp Dener          The scaled gradient step did not produce a new iterate;
860937a31a1SAlp Dener          reset the BFGS matrix and attemp to use the gradient direction. */
861c14b763aSAlp Dener       ierr = MatLMVMSetScale(bnk->M,0);CHKERRQ(ierr);
862c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M,1.0);CHKERRQ(ierr);
863c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
864c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
865937a31a1SAlp Dener       ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
866c14b763aSAlp Dener 
867c14b763aSAlp Dener       bfgsUpdates = 1;
868937a31a1SAlp Dener       *stepType = BNK_GRADIENT;
869c14b763aSAlp Dener       break;
870c14b763aSAlp Dener     }
8718d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
8728d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
8732f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
874c14b763aSAlp Dener 
8758d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
876c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
877c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
878c14b763aSAlp Dener   }
879c14b763aSAlp Dener   *reason = ls_reason;
880c14b763aSAlp Dener   PetscFunctionReturn(0);
881c14b763aSAlp Dener }
882c14b763aSAlp Dener 
883df278d8fSAlp Dener /*------------------------------------------------------------*/
884df278d8fSAlp Dener 
885df278d8fSAlp Dener /* Routine for updating the trust radius.
886df278d8fSAlp Dener 
887df278d8fSAlp Dener   Function features three different update methods:
888df278d8fSAlp Dener   1) Line-search step length based
889df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
890df278d8fSAlp Dener   3) Interpolation
891df278d8fSAlp Dener */
892df278d8fSAlp Dener 
89328017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
894080d2917SAlp Dener {
895080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
896080d2917SAlp Dener   PetscErrorCode ierr;
897080d2917SAlp Dener 
898b1c2d0e3SAlp Dener   PetscReal      step, kappa;
899080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
900080d2917SAlp Dener 
901080d2917SAlp Dener   PetscFunctionBegin;
902080d2917SAlp Dener   /* Update trust region radius */
903080d2917SAlp Dener   *accept = PETSC_FALSE;
90428017e9fSAlp Dener   switch(updateType) {
905080d2917SAlp Dener   case BNK_UPDATE_STEP:
906c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
907080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
908080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
909080d2917SAlp Dener       if (step < bnk->nu1) {
910080d2917SAlp Dener         /* Very bad step taken; reduce radius */
911080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
912080d2917SAlp Dener       } else if (step < bnk->nu2) {
913080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
914080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
915080d2917SAlp Dener       } else if (step < bnk->nu3) {
916080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
917080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
918080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
919080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
920080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
921080d2917SAlp Dener         }
922080d2917SAlp Dener       } else if (step < bnk->nu4) {
923080d2917SAlp Dener         /*  Full step taken; increase the radius */
924080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
925080d2917SAlp Dener       } else {
926080d2917SAlp Dener         /*  More than full step taken; increase the radius */
927080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
928080d2917SAlp Dener       }
929080d2917SAlp Dener     } else {
930080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
931080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
932080d2917SAlp Dener     }
933080d2917SAlp Dener     break;
934080d2917SAlp Dener 
935080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
936080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
937b1c2d0e3SAlp Dener       if (prered < 0.0) {
938fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
939fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
940fed79b8eSAlp Dener            be rejected! */
941080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
942fed79b8eSAlp Dener       }
943fed79b8eSAlp Dener       else {
944b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
945080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
946080d2917SAlp Dener         } else {
9470a4511e9SAlp Dener           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) &&
9480a4511e9SAlp Dener               (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
949080d2917SAlp Dener             kappa = 1.0;
950fed79b8eSAlp Dener           }
951fed79b8eSAlp Dener           else {
952080d2917SAlp Dener             kappa = actred / prered;
953080d2917SAlp Dener           }
954fed79b8eSAlp Dener 
955fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
956080d2917SAlp Dener           if (kappa < bnk->eta1) {
957fed79b8eSAlp Dener             /* Reject the step */
958080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
959fed79b8eSAlp Dener           }
960fed79b8eSAlp Dener           else {
961fed79b8eSAlp Dener             /* Accept the step */
962c133c014SAlp Dener             *accept = PETSC_TRUE;
963c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
9648d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
965080d2917SAlp Dener               if (kappa < bnk->eta2) {
966080d2917SAlp Dener                 /* Marginal bad step */
967c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
968080d2917SAlp Dener               }
969fed79b8eSAlp Dener               else if (kappa < bnk->eta3) {
970fed79b8eSAlp Dener                 /* Reasonable step */
971fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
972fed79b8eSAlp Dener               }
973fed79b8eSAlp Dener               else if (kappa < bnk->eta4) {
974080d2917SAlp Dener                 /* Good step */
975c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
976fed79b8eSAlp Dener               }
977fed79b8eSAlp Dener               else {
978080d2917SAlp Dener                 /* Very good step */
979c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
980080d2917SAlp Dener               }
981c133c014SAlp Dener             }
982080d2917SAlp Dener           }
983080d2917SAlp Dener         }
984080d2917SAlp Dener       }
985080d2917SAlp Dener     } else {
986080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
987080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
988080d2917SAlp Dener     }
989080d2917SAlp Dener     break;
990080d2917SAlp Dener 
991080d2917SAlp Dener   default:
992080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
993b1c2d0e3SAlp Dener       if (prered < 0.0) {
994080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
995080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
996080d2917SAlp Dener         /*  be rejected! */
997080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
998080d2917SAlp Dener       } else {
999b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
1000080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1001080d2917SAlp Dener         } else {
1002080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
1003080d2917SAlp Dener             kappa = 1.0;
1004080d2917SAlp Dener           } else {
1005080d2917SAlp Dener             kappa = actred / prered;
1006080d2917SAlp Dener           }
1007080d2917SAlp Dener 
1008080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
1009080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
1010080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
1011080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
1012080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
1013080d2917SAlp Dener 
1014080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
1015080d2917SAlp Dener             /*  Great agreement */
1016080d2917SAlp Dener             *accept = PETSC_TRUE;
1017080d2917SAlp Dener             if (tau_max < 1.0) {
1018080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1019080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
1020080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
1021080d2917SAlp Dener             } else {
1022080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1023080d2917SAlp Dener             }
1024080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
1025080d2917SAlp Dener             /*  Good agreement */
1026080d2917SAlp Dener             *accept = PETSC_TRUE;
1027080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
1028080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1029080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
1030080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1031080d2917SAlp Dener             } else if (tau_max < 1.0) {
1032080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1033080d2917SAlp Dener             } else {
1034080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1035080d2917SAlp Dener             }
1036080d2917SAlp Dener           } else {
1037080d2917SAlp Dener             /*  Not good agreement */
1038080d2917SAlp Dener             if (tau_min > 1.0) {
1039080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1040080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
1041080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1042080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
1043080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1044080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
1045080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
1046080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
1047080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
1048080d2917SAlp Dener             } else {
1049080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1050080d2917SAlp Dener             }
1051080d2917SAlp Dener           }
1052080d2917SAlp Dener         }
1053080d2917SAlp Dener       }
1054080d2917SAlp Dener     } else {
1055080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
1056080d2917SAlp Dener       tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust);
1057080d2917SAlp Dener     }
105828017e9fSAlp Dener     break;
1059080d2917SAlp Dener   }
1060c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
1061c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
1062fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
1063080d2917SAlp Dener   PetscFunctionReturn(0);
1064080d2917SAlp Dener }
1065080d2917SAlp Dener 
1066eb910715SAlp Dener /* ---------------------------------------------------------- */
1067df278d8fSAlp Dener 
106862675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
106962675beeSAlp Dener {
107062675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
107162675beeSAlp Dener 
107262675beeSAlp Dener   PetscFunctionBegin;
107362675beeSAlp Dener   switch (stepType) {
107462675beeSAlp Dener   case BNK_NEWTON:
107562675beeSAlp Dener     ++bnk->newt;
107662675beeSAlp Dener     break;
107762675beeSAlp Dener   case BNK_BFGS:
107862675beeSAlp Dener     ++bnk->bfgs;
107962675beeSAlp Dener     break;
108062675beeSAlp Dener   case BNK_SCALED_GRADIENT:
108162675beeSAlp Dener     ++bnk->sgrad;
108262675beeSAlp Dener     break;
108362675beeSAlp Dener   case BNK_GRADIENT:
108462675beeSAlp Dener     ++bnk->grad;
108562675beeSAlp Dener     break;
108662675beeSAlp Dener   default:
108762675beeSAlp Dener     break;
108862675beeSAlp Dener   }
108962675beeSAlp Dener   PetscFunctionReturn(0);
109062675beeSAlp Dener }
109162675beeSAlp Dener 
109262675beeSAlp Dener /* ---------------------------------------------------------- */
109362675beeSAlp Dener 
10949b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
1095eb910715SAlp Dener {
1096eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1097eb910715SAlp Dener   PetscErrorCode ierr;
10989b6ef848SAlp Dener   KSPType        ksp_type;
1099e031d6f5SAlp Dener   PetscInt       i;
1100eb910715SAlp Dener 
1101eb910715SAlp Dener   PetscFunctionBegin;
1102eb910715SAlp Dener   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);}
1103eb910715SAlp Dener   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);}
1104eb910715SAlp Dener   if (!bnk->W) {ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);}
1105eb910715SAlp Dener   if (!bnk->Xold) {ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);}
1106eb910715SAlp Dener   if (!bnk->Gold) {ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);}
110709164190SAlp Dener   if (!bnk->Xwork) {ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);}
110809164190SAlp Dener   if (!bnk->Gwork) {ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);}
110909164190SAlp Dener   if (!bnk->unprojected_gradient) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);}
111009164190SAlp Dener   if (!bnk->unprojected_gradient_old) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);}
11115e9b73cbSAlp Dener   if (!bnk->Diag_min) {ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);}
11125e9b73cbSAlp Dener   if (!bnk->Diag_max) {ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);}
1113e031d6f5SAlp Dener   if (bnk->max_cg_its > 0) {
1114e031d6f5SAlp Dener     if (!bnk->bncg_sol) {ierr = VecDuplicate(tao->solution,&bnk->bncg_sol);CHKERRQ(ierr);}
1115e031d6f5SAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, bnk->bncg_sol);CHKERRQ(ierr);
1116e031d6f5SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
1117e031d6f5SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
1118e031d6f5SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
1119e031d6f5SAlp Dener 
1120937a31a1SAlp Dener     ierr = TaoSetConvergenceTest(bnk->bncg, tao->ops->convergencetest, tao->cnvP);CHKERRQ(ierr);
1121e031d6f5SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
1122e031d6f5SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
1123e031d6f5SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
1124e031d6f5SAlp Dener     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr);
1125e031d6f5SAlp Dener     for (i=0; i<tao->numbermonitors; i++) {
1126e031d6f5SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
1127e031d6f5SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
1128e031d6f5SAlp Dener     }
1129937a31a1SAlp Dener     ierr = TaoSetUp(bnk->bncg);CHKERRQ(ierr);
1130e031d6f5SAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
1131e031d6f5SAlp Dener   }
1132eb910715SAlp Dener   bnk->Diag = 0;
1133c0f10754SAlp Dener   bnk->Diag_red = 0;
1134c0f10754SAlp Dener   bnk->X_inactive = 0;
1135c0f10754SAlp Dener   bnk->G_inactive = 0;
113662675beeSAlp Dener   bnk->inactive_work = 0;
113762675beeSAlp Dener   bnk->active_work = 0;
113862675beeSAlp Dener   bnk->inactive_idx = 0;
113962675beeSAlp Dener   bnk->active_idx = 0;
114062675beeSAlp Dener   bnk->active_lower = 0;
114162675beeSAlp Dener   bnk->active_upper = 0;
114262675beeSAlp Dener   bnk->active_fixed = 0;
1143eb910715SAlp Dener   bnk->M = 0;
114409164190SAlp Dener   bnk->H_inactive = 0;
114509164190SAlp Dener   bnk->Hpre_inactive = 0;
11469b6ef848SAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
11479b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
11489b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
11499b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1150eb910715SAlp Dener   PetscFunctionReturn(0);
1151eb910715SAlp Dener }
1152eb910715SAlp Dener 
1153eb910715SAlp Dener /*------------------------------------------------------------*/
1154df278d8fSAlp Dener 
1155eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao)
1156eb910715SAlp Dener {
1157eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1158eb910715SAlp Dener   PetscErrorCode ierr;
1159eb910715SAlp Dener 
1160eb910715SAlp Dener   PetscFunctionBegin;
1161eb910715SAlp Dener   if (tao->setupcalled) {
1162eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1163eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1164eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
116509164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
116609164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
116709164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
116809164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
116962675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
117062675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1171c0f10754SAlp Dener     if (bnk->max_cg_its > 0) {
1172c0f10754SAlp Dener       ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1173c0f10754SAlp Dener       ierr = VecDestroy(&bnk->bncg_sol);CHKERRQ(ierr);
1174c0f10754SAlp Dener     }
11755e9b73cbSAlp Dener   }
11765e9b73cbSAlp Dener   ierr = VecDestroy(&bnk->Diag);CHKERRQ(ierr);
1177eb910715SAlp Dener   ierr = MatDestroy(&bnk->M);CHKERRQ(ierr);
1178c0f10754SAlp Dener   if (bnk->Hpre_inactive != tao->hessian_pre && bnk->Hpre_inactive != bnk->H_inactive) {ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);}
1179c0f10754SAlp Dener   if (bnk->H_inactive != tao->hessian) {ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);}
1180eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1181eb910715SAlp Dener   PetscFunctionReturn(0);
1182eb910715SAlp Dener }
1183eb910715SAlp Dener 
1184eb910715SAlp Dener /*------------------------------------------------------------*/
1185df278d8fSAlp Dener 
1186eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1187eb910715SAlp Dener {
1188eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1189eb910715SAlp Dener   PetscErrorCode ierr;
1190eb910715SAlp Dener 
1191eb910715SAlp Dener   PetscFunctionBegin;
1192eb910715SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr);
11938d5ead36SAlp 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);
11948d5ead36SAlp 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);
11958d5ead36SAlp 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);
11968d5ead36SAlp 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);
11972f75a4aaSAlp 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);
11988d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
11998d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "minimum initial perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
12008d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "maximum initial perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
12018d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "initial merit factor", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
12028d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "minimum perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
12038d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "maximum perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
12048d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
12058d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
12068d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "merit growth factor", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
12078d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "merit shrink factor", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
12088d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "poor steplength; reduce radius", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
12098d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "reasonable steplength; leave radius alone", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
12108d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "good steplength; increase radius", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
12118d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "excellent steplength; greatly increase radius", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
12128d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha1", "", "", bnk->alpha1, &bnk->alpha1,NULL);CHKERRQ(ierr);
12138d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha2", "", "", bnk->alpha2, &bnk->alpha2,NULL);CHKERRQ(ierr);
12148d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha3", "", "", bnk->alpha3, &bnk->alpha3,NULL);CHKERRQ(ierr);
12158d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha4", "", "", bnk->alpha4, &bnk->alpha4,NULL);CHKERRQ(ierr);
12168d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha5", "", "", bnk->alpha5, &bnk->alpha5,NULL);CHKERRQ(ierr);
12178d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu1", "poor steplength; reduce radius", "", bnk->nu1, &bnk->nu1,NULL);CHKERRQ(ierr);
12188d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu2", "reasonable steplength; leave radius alone", "", bnk->nu2, &bnk->nu2,NULL);CHKERRQ(ierr);
12198d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu3", "good steplength; increase radius", "", bnk->nu3, &bnk->nu3,NULL);CHKERRQ(ierr);
12208d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu4", "excellent steplength; greatly increase radius", "", bnk->nu4, &bnk->nu4,NULL);CHKERRQ(ierr);
12218d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega1", "", "", bnk->omega1, &bnk->omega1,NULL);CHKERRQ(ierr);
12228d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega2", "", "", bnk->omega2, &bnk->omega2,NULL);CHKERRQ(ierr);
12238d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega3", "", "", bnk->omega3, &bnk->omega3,NULL);CHKERRQ(ierr);
12248d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega4", "", "", bnk->omega4, &bnk->omega4,NULL);CHKERRQ(ierr);
12258d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega5", "", "", bnk->omega5, &bnk->omega5,NULL);CHKERRQ(ierr);
12268d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1_i", "", "", bnk->mu1_i, &bnk->mu1_i,NULL);CHKERRQ(ierr);
12278d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2_i", "", "", bnk->mu2_i, &bnk->mu2_i,NULL);CHKERRQ(ierr);
12288d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1_i", "", "", bnk->gamma1_i, &bnk->gamma1_i,NULL);CHKERRQ(ierr);
12298d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2_i", "", "", bnk->gamma2_i, &bnk->gamma2_i,NULL);CHKERRQ(ierr);
12308d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3_i", "", "", bnk->gamma3_i, &bnk->gamma3_i,NULL);CHKERRQ(ierr);
12318d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4_i", "", "", bnk->gamma4_i, &bnk->gamma4_i,NULL);CHKERRQ(ierr);
12328d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta_i", "", "", bnk->theta_i, &bnk->theta_i,NULL);CHKERRQ(ierr);
12338d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1", "", "", bnk->mu1, &bnk->mu1,NULL);CHKERRQ(ierr);
12348d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
12358d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1", "", "", bnk->gamma1, &bnk->gamma1,NULL);CHKERRQ(ierr);
12368d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2", "", "", bnk->gamma2, &bnk->gamma2,NULL);CHKERRQ(ierr);
12378d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3", "", "", bnk->gamma3, &bnk->gamma3,NULL);CHKERRQ(ierr);
12388d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4", "", "", bnk->gamma4, &bnk->gamma4,NULL);CHKERRQ(ierr);
12398d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
12408d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
12418d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
12428d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
12430a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_tol", "initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol,NULL);CHKERRQ(ierr);
12440a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_step", "step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step,NULL);CHKERRQ(ierr);
1245c0f10754SAlp 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);
1246eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
1247e031d6f5SAlp Dener   ierr = TaoSetFromOptions(bnk->bncg);
1248eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1249eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1250eb910715SAlp Dener   PetscFunctionReturn(0);
1251eb910715SAlp Dener }
1252eb910715SAlp Dener 
1253eb910715SAlp Dener /*------------------------------------------------------------*/
1254df278d8fSAlp Dener 
1255eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1256eb910715SAlp Dener {
1257eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1258eb910715SAlp Dener   PetscInt       nrejects;
1259eb910715SAlp Dener   PetscBool      isascii;
1260eb910715SAlp Dener   PetscErrorCode ierr;
1261eb910715SAlp Dener 
1262eb910715SAlp Dener   PetscFunctionBegin;
1263eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1264eb910715SAlp Dener   if (isascii) {
1265eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1266eb910715SAlp Dener     if (BNK_PC_BFGS == bnk->pc_type && bnk->M) {
1267eb910715SAlp Dener       ierr = MatLMVMGetRejects(bnk->M,&nrejects);CHKERRQ(ierr);
1268eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects);CHKERRQ(ierr);
1269eb910715SAlp Dener     }
1270e031d6f5SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr);
1271eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1272eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1273eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1274eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1275eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1276eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1277eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1278eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1279eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1280eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1281eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1282eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1283eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1284eb910715SAlp Dener   }
1285eb910715SAlp Dener   PetscFunctionReturn(0);
1286eb910715SAlp Dener }
1287eb910715SAlp Dener 
1288eb910715SAlp Dener /* ---------------------------------------------------------- */
1289df278d8fSAlp Dener 
1290eb910715SAlp Dener /*MC
1291eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
129266ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1293eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1294eb910715SAlp Dener               Hk dk = -gk
12952b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12962b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1297eb910715SAlp Dener 
1298eb910715SAlp Dener     Options Database Keys:
12998d5ead36SAlp Dener + -tao_bnk_pc_type - "none","ahess","bfgs","petsc"
13008d5ead36SAlp Dener . -tao_bnk_bfgs_scale_type - "ahess","phess","bfgs"
13018d5ead36SAlp Dener . -tao_bnk_init_type - "constant","direction","interpolation"
13028d5ead36SAlp Dener . -tao_bnk_update_type - "step","direction","interpolation"
13032f75a4aaSAlp Dener . -tao_bnk_as_type - "none","bertsekas"
13048d5ead36SAlp Dener . -tao_bnk_sval - perturbation starting value
13058d5ead36SAlp Dener . -tao_bnk_imin - minimum initial perturbation
13068d5ead36SAlp Dener . -tao_bnk_imax - maximum initial perturbation
13078d5ead36SAlp Dener . -tao_bnk_pmin - minimum perturbation
13088d5ead36SAlp Dener . -tao_bnk_pmax - maximum perturbation
13098d5ead36SAlp Dener . -tao_bnk_pgfac - growth factor
13108d5ead36SAlp Dener . -tao_bnk_psfac - shrink factor
13118d5ead36SAlp Dener . -tao_bnk_imfac - initial merit factor
13128d5ead36SAlp Dener . -tao_bnk_pmgfac - merit growth factor
13138d5ead36SAlp Dener . -tao_bnk_pmsfac - merit shrink factor
13148d5ead36SAlp Dener . -tao_bnk_eta1 - poor steplength; reduce radius
13158d5ead36SAlp Dener . -tao_bnk_eta2 - reasonable steplength; leave radius
13168d5ead36SAlp Dener . -tao_bnk_eta3 - good steplength; increase readius
13178d5ead36SAlp Dener . -tao_bnk_eta4 - excellent steplength; greatly increase radius
13188d5ead36SAlp Dener . -tao_bnk_alpha1 - alpha1 reduction
13198d5ead36SAlp Dener . -tao_bnk_alpha2 - alpha2 reduction
13208d5ead36SAlp Dener . -tao_bnk_alpha3 - alpha3 reduction
13218d5ead36SAlp Dener . -tao_bnk_alpha4 - alpha4 reduction
13228d5ead36SAlp Dener . -tao_bnk_alpha - alpha5 reduction
13238d5ead36SAlp Dener . -tao_bnk_mu1 - mu1 interpolation update
13248d5ead36SAlp Dener . -tao_bnk_mu2 - mu2 interpolation update
13258d5ead36SAlp Dener . -tao_bnk_gamma1 - gamma1 interpolation update
13268d5ead36SAlp Dener . -tao_bnk_gamma2 - gamma2 interpolation update
13278d5ead36SAlp Dener . -tao_bnk_gamma3 - gamma3 interpolation update
13288d5ead36SAlp Dener . -tao_bnk_gamma4 - gamma4 interpolation update
13298d5ead36SAlp Dener . -tao_bnk_theta - theta interpolation update
13308d5ead36SAlp Dener . -tao_bnk_omega1 - omega1 step update
13318d5ead36SAlp Dener . -tao_bnk_omega2 - omega2 step update
13328d5ead36SAlp Dener . -tao_bnk_omega3 - omega3 step update
13338d5ead36SAlp Dener . -tao_bnk_omega4 - omega4 step update
13348d5ead36SAlp Dener . -tao_bnk_omega5 - omega5 step update
13358d5ead36SAlp Dener . -tao_bnk_mu1_i -  mu1 interpolation init factor
13368d5ead36SAlp Dener . -tao_bnk_mu2_i -  mu2 interpolation init factor
13378d5ead36SAlp Dener . -tao_bnk_gamma1_i -  gamma1 interpolation init factor
13388d5ead36SAlp Dener . -tao_bnk_gamma2_i -  gamma2 interpolation init factor
13398d5ead36SAlp Dener . -tao_bnk_gamma3_i -  gamma3 interpolation init factor
13408d5ead36SAlp Dener . -tao_bnk_gamma4_i -  gamma4 interpolation init factor
13412f75a4aaSAlp Dener . -tao_bnk_theta_i -  theta interpolation init factor
13422f75a4aaSAlp Dener - -tao_bnk_bound_tol -  initial tolerance used in estimating bounded active variables
1343eb910715SAlp Dener 
1344eb910715SAlp Dener   Level: beginner
1345eb910715SAlp Dener M*/
1346eb910715SAlp Dener 
1347eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1348eb910715SAlp Dener {
1349eb910715SAlp Dener   TAO_BNK        *bnk;
1350eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1351eb910715SAlp Dener   PetscErrorCode ierr;
1352eb910715SAlp Dener 
1353eb910715SAlp Dener   PetscFunctionBegin;
1354eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1355eb910715SAlp Dener 
1356eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1357eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1358eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1359eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1360eb910715SAlp Dener 
1361eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1362eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1363eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1364eb910715SAlp Dener 
1365eb910715SAlp Dener   tao->data = (void*)bnk;
1366eb910715SAlp Dener 
136766ed3702SAlp Dener   /*  Hessian shifting parameters */
1368eb910715SAlp Dener   bnk->sval   = 0.0;
1369eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1370eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1371eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1372eb910715SAlp Dener 
1373eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1374eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1375eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1376eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1377eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1378eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1379eb910715SAlp Dener 
1380eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1381eb910715SAlp Dener   bnk->nu1 = 0.25;
1382eb910715SAlp Dener   bnk->nu2 = 0.50;
1383eb910715SAlp Dener   bnk->nu3 = 1.00;
1384eb910715SAlp Dener   bnk->nu4 = 1.25;
1385eb910715SAlp Dener 
1386eb910715SAlp Dener   bnk->omega1 = 0.25;
1387eb910715SAlp Dener   bnk->omega2 = 0.50;
1388eb910715SAlp Dener   bnk->omega3 = 1.00;
1389eb910715SAlp Dener   bnk->omega4 = 2.00;
1390eb910715SAlp Dener   bnk->omega5 = 4.00;
1391eb910715SAlp Dener 
1392eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1393eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1394eb910715SAlp Dener   bnk->eta2 = 0.25;
1395eb910715SAlp Dener   bnk->eta3 = 0.50;
1396eb910715SAlp Dener   bnk->eta4 = 0.90;
1397eb910715SAlp Dener 
1398eb910715SAlp Dener   bnk->alpha1 = 0.25;
1399eb910715SAlp Dener   bnk->alpha2 = 0.50;
1400eb910715SAlp Dener   bnk->alpha3 = 1.00;
1401eb910715SAlp Dener   bnk->alpha4 = 2.00;
1402eb910715SAlp Dener   bnk->alpha5 = 4.00;
1403eb910715SAlp Dener 
1404eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1405eb910715SAlp Dener   bnk->mu1 = 0.10;
1406eb910715SAlp Dener   bnk->mu2 = 0.50;
1407eb910715SAlp Dener 
1408eb910715SAlp Dener   bnk->gamma1 = 0.25;
1409eb910715SAlp Dener   bnk->gamma2 = 0.50;
1410eb910715SAlp Dener   bnk->gamma3 = 2.00;
1411eb910715SAlp Dener   bnk->gamma4 = 4.00;
1412eb910715SAlp Dener 
1413eb910715SAlp Dener   bnk->theta = 0.05;
1414eb910715SAlp Dener 
1415eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1416eb910715SAlp Dener   bnk->mu1_i = 0.35;
1417eb910715SAlp Dener   bnk->mu2_i = 0.50;
1418eb910715SAlp Dener 
1419eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1420eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1421eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1422eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1423eb910715SAlp Dener 
1424eb910715SAlp Dener   bnk->theta_i = 0.25;
1425eb910715SAlp Dener 
1426eb910715SAlp Dener   /*  Remaining parameters */
1427c0f10754SAlp Dener   bnk->max_cg_its = 0;
1428eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1429eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1430770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
14310a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
14320a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
143362675beeSAlp Dener   bnk->dmin = 1.0e-6;
143462675beeSAlp Dener   bnk->dmax = 1.0e6;
1435eb910715SAlp Dener 
1436e031d6f5SAlp Dener   bnk->pc_type         = BNK_PC_AHESS;
1437eb910715SAlp Dener   bnk->bfgs_scale_type = BFGS_SCALE_PHESS;
1438eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
1439fed79b8eSAlp Dener   bnk->update_type     = BNK_UPDATE_INTERPOLATION;
14402f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1441eb910715SAlp Dener 
1442e031d6f5SAlp Dener   /* Create the embedded BNCG solver */
1443e031d6f5SAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
1444e031d6f5SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
1445e031d6f5SAlp Dener   ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr);
1446e031d6f5SAlp Dener   ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
1447e031d6f5SAlp Dener 
1448c0f10754SAlp Dener   /* Create the line search */
1449eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1450eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1451e031d6f5SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1452eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1453eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1454eb910715SAlp Dener 
1455eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1456eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1457eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1458eb910715SAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr);
1459eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1460eb910715SAlp Dener   PetscFunctionReturn(0);
1461eb910715SAlp Dener }
1462