xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision 937a31a162199036c7d7383da36013b6a359c186)
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);
6128017e9fSAlp Dener   ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
6208752603SAlp Dener   ierr = VecNorm(tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
6328017e9fSAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
6428017e9fSAlp Dener 
65c0f10754SAlp Dener   /* Test the initial point for convergence */
66e031d6f5SAlp Dener   ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr);
67e031d6f5SAlp Dener   ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr);
68e031d6f5SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
69e031d6f5SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
70c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
71c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
72c0f10754SAlp Dener 
73e031d6f5SAlp Dener   /* Reset KSP stopping reason counters */
74eb910715SAlp Dener   bnk->ksp_atol = 0;
75eb910715SAlp Dener   bnk->ksp_rtol = 0;
76eb910715SAlp Dener   bnk->ksp_dtol = 0;
77eb910715SAlp Dener   bnk->ksp_ctol = 0;
78eb910715SAlp Dener   bnk->ksp_negc = 0;
79eb910715SAlp Dener   bnk->ksp_iter = 0;
80eb910715SAlp Dener   bnk->ksp_othr = 0;
81eb910715SAlp Dener 
82e031d6f5SAlp Dener   /* Reset accepted step type counters */
83e031d6f5SAlp Dener   bnk->tot_cg_its = 0;
84e031d6f5SAlp Dener   bnk->newt = 0;
85e031d6f5SAlp Dener   bnk->bfgs = 0;
86e031d6f5SAlp Dener   bnk->sgrad = 0;
87e031d6f5SAlp Dener   bnk->grad = 0;
88e031d6f5SAlp Dener 
89fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
90fed79b8eSAlp Dener   bnk->pert = bnk->sval;
91fed79b8eSAlp Dener 
92*937a31a1SAlp Dener   /* Reset initial steplength to zero (this helps BNCG reset its direction internally) */
93*937a31a1SAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
94*937a31a1SAlp Dener 
95e031d6f5SAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
96e031d6f5SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
97e031d6f5SAlp Dener     if (!bnk->M) {
98eb910715SAlp Dener       ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr);
99eb910715SAlp Dener       ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr);
100eb910715SAlp Dener       ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&bnk->M);CHKERRQ(ierr);
101eb910715SAlp Dener       ierr = MatLMVMAllocateVectors(bnk->M,tao->solution);CHKERRQ(ierr);
102eb910715SAlp Dener     }
103e031d6f5SAlp Dener     if (bnk->bfgs_scale_type != BFGS_SCALE_BFGS && !bnk->Diag) {
104e031d6f5SAlp Dener       ierr = VecDuplicate(tao->solution,&bnk->Diag);CHKERRQ(ierr);
1055e9b73cbSAlp Dener     }
106e031d6f5SAlp Dener   }
107e031d6f5SAlp Dener 
108e031d6f5SAlp Dener   /* Prepare the min/max vectors for safeguarding diagonal scales */
10962675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
11062675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
111eb910715SAlp Dener 
112eb910715SAlp Dener   /* Modify the preconditioner to use the bfgs approximation */
113eb910715SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
114eb910715SAlp Dener   switch(bnk->pc_type) {
115eb910715SAlp Dener   case BNK_PC_NONE:
116eb910715SAlp Dener     ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr);
117eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
118eb910715SAlp Dener     break;
119eb910715SAlp Dener 
120eb910715SAlp Dener   case BNK_PC_AHESS:
121eb910715SAlp Dener     ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr);
122eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
123eb910715SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
124eb910715SAlp Dener     break;
125eb910715SAlp Dener 
126eb910715SAlp Dener   case BNK_PC_BFGS:
127eb910715SAlp Dener     ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr);
128eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
129eb910715SAlp Dener     ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr);
130eb910715SAlp Dener     ierr = PCShellSetContext(pc, bnk->M);CHKERRQ(ierr);
131eb910715SAlp Dener     ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr);
132eb910715SAlp Dener     break;
133eb910715SAlp Dener 
134eb910715SAlp Dener   default:
135eb910715SAlp Dener     /* Use the pc method set by pc_type */
136eb910715SAlp Dener     break;
137eb910715SAlp Dener   }
138eb910715SAlp Dener 
139eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
140eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
141c0f10754SAlp Dener   *needH = PETSC_TRUE;
142eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
14362675beeSAlp Dener     switch(initType) {
144eb910715SAlp Dener     case BNK_INIT_CONSTANT:
145eb910715SAlp Dener       /* Use the initial radius specified */
146c0f10754SAlp Dener       tao->trust = tao->trust0;
147eb910715SAlp Dener       break;
148eb910715SAlp Dener 
149eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
150c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
151eb910715SAlp Dener       max_radius = 0.0;
15208752603SAlp Dener       tao->trust = tao->trust0;
153eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1540a4511e9SAlp Dener         f_min = bnk->f;
155eb910715SAlp Dener         sigma = 0.0;
156eb910715SAlp Dener 
157c0f10754SAlp Dener         if (*needH) {
15862602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
159e031d6f5SAlp Dener           ierr = TaoBNKComputeHessian(tao);CHKERRQ(ierr);
16008752603SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, BNK_AS_NONE);CHKERRQ(ierr);
16128017e9fSAlp Dener           if (bnk->inactive_idx) {
1622ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
16328017e9fSAlp Dener           } else {
16408752603SAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
16528017e9fSAlp Dener           }
166c0f10754SAlp Dener           *needH = PETSC_FALSE;
167eb910715SAlp Dener         }
168eb910715SAlp Dener 
169eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
17062602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
17162602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
17262602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
17362602cfbSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
174770b7498SAlp Dener           /* Recompute the step after bound snapping so that it can be used in predicted decrease calculation later */
175eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
17662602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
17762602cfbSAlp Dener           /* Compute the objective at the trial */
17862602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
17962602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
180eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
181eb910715SAlp Dener             tau = bnk->gamma1_i;
182eb910715SAlp Dener           } else {
1830a4511e9SAlp Dener             if (ftrial < f_min) {
1840a4511e9SAlp Dener               f_min = ftrial;
185eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
186eb910715SAlp Dener             }
18708752603SAlp Dener 
188770b7498SAlp Dener             /* Compute the predicted and actual reduction */
1892ab2a32cSAlp Dener             if (bnk->inactive_idx) {
19008752603SAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
19108752603SAlp Dener               ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1922ab2a32cSAlp Dener             } else {
19308752603SAlp Dener               bnk->X_inactive = bnk->W;
19408752603SAlp Dener               bnk->inactive_work = bnk->Xwork;
1952ab2a32cSAlp Dener             }
19608752603SAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
19708752603SAlp Dener             ierr = VecDot(bnk->X_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
1982ab2a32cSAlp Dener             if (bnk->inactive_idx) {
19908752603SAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
20008752603SAlp Dener               ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
2012ab2a32cSAlp Dener             }
202eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
203eb910715SAlp Dener             actred = bnk->f - ftrial;
20408752603SAlp Dener             if ((PetscAbsScalar(actred) <= bnk->epsilon) &&
20508752603SAlp Dener                 (PetscAbsScalar(prered) <= bnk->epsilon)) {
206eb910715SAlp Dener               kappa = 1.0;
20708752603SAlp Dener             }
20808752603SAlp Dener             else {
209eb910715SAlp Dener               kappa = actred / prered;
210eb910715SAlp Dener             }
211eb910715SAlp Dener 
212eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
213eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
214eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
215eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
216eb910715SAlp Dener 
217eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
218eb910715SAlp Dener               /*  Great agreement */
219eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
220eb910715SAlp Dener 
221eb910715SAlp Dener               if (tau_max < 1.0) {
222eb910715SAlp Dener                 tau = bnk->gamma3_i;
22308752603SAlp Dener               }
22408752603SAlp Dener               else if (tau_max > bnk->gamma4_i) {
225eb910715SAlp Dener                 tau = bnk->gamma4_i;
22608752603SAlp Dener               }
22708752603SAlp Dener               else {
228eb910715SAlp Dener                 tau = tau_max;
229eb910715SAlp Dener               }
23008752603SAlp Dener             }
23108752603SAlp Dener             else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
232eb910715SAlp Dener               /*  Good agreement */
233eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
234eb910715SAlp Dener 
235eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
236eb910715SAlp Dener                 tau = bnk->gamma2_i;
237eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
238eb910715SAlp Dener                 tau = bnk->gamma3_i;
239eb910715SAlp Dener               } else {
240eb910715SAlp Dener                 tau = tau_max;
241eb910715SAlp Dener               }
24208752603SAlp Dener             }
24308752603SAlp Dener             else {
244eb910715SAlp Dener               /*  Not good agreement */
245eb910715SAlp Dener               if (tau_min > 1.0) {
246eb910715SAlp Dener                 tau = bnk->gamma2_i;
247eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
248eb910715SAlp Dener                 tau = bnk->gamma1_i;
249eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
250eb910715SAlp Dener                 tau = bnk->gamma1_i;
25108752603SAlp Dener               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) &&
25208752603SAlp Dener                         ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
253eb910715SAlp Dener                 tau = tau_1;
25408752603SAlp Dener               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) &&
25508752603SAlp Dener                         ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
256eb910715SAlp Dener                 tau = tau_2;
257eb910715SAlp Dener               } else {
258eb910715SAlp Dener                 tau = tau_max;
259eb910715SAlp Dener               }
260eb910715SAlp Dener             }
261eb910715SAlp Dener           }
262eb910715SAlp Dener           tao->trust = tau * tao->trust;
263eb910715SAlp Dener         }
264eb910715SAlp Dener 
2650a4511e9SAlp Dener         if (f_min < bnk->f) {
266*937a31a1SAlp Dener           /* We accidentally found a solution better than the initial, so accept it */
2670a4511e9SAlp Dener           bnk->f = f_min;
268*937a31a1SAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
269eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
27087602d1eSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
271*937a31a1SAlp Dener           ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr);
272*937a31a1SAlp Dener           ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr);
27309164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
27409164190SAlp Dener           ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
275*937a31a1SAlp Dener           /* Compute gradient at the new iterate and flip switch to compute the Hessian later */
276eb910715SAlp Dener           ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
277eb910715SAlp Dener           if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN");
278c0f10754SAlp Dener           *needH = PETSC_TRUE;
279*937a31a1SAlp Dener           /* Test the new step for convergence */
280e031d6f5SAlp Dener           ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr);
281e031d6f5SAlp Dener           ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr);
282e031d6f5SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
283e031d6f5SAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
284eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
285eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
286*937a31a1SAlp Dener           /* active BNCG recycling early because we have a stepdirection computed */
287*937a31a1SAlp Dener           ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
288eb910715SAlp Dener         }
289eb910715SAlp Dener       }
290eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
291e031d6f5SAlp Dener 
292e031d6f5SAlp Dener       /* Ensure that the trust radius is within the limits */
293e031d6f5SAlp Dener       tao->trust = PetscMax(tao->trust, bnk->min_radius);
294e031d6f5SAlp Dener       tao->trust = PetscMin(tao->trust, bnk->max_radius);
295eb910715SAlp Dener       break;
296eb910715SAlp Dener 
297eb910715SAlp Dener     default:
298eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
299eb910715SAlp Dener       tao->trust = 0.0;
300eb910715SAlp Dener       break;
301eb910715SAlp Dener     }
302eb910715SAlp Dener   }
303e031d6f5SAlp Dener 
304eb910715SAlp Dener   /* Set initial scaling for the BFGS preconditioner
305eb910715SAlp Dener      This step is done after computing the initial trust-region radius
306eb910715SAlp Dener      since the function value may have decreased */
307eb910715SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
3089b6ef848SAlp Dener     delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
309eb910715SAlp Dener     ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
310eb910715SAlp Dener   }
311eb910715SAlp Dener   PetscFunctionReturn(0);
312eb910715SAlp Dener }
313eb910715SAlp Dener 
314df278d8fSAlp Dener /*------------------------------------------------------------*/
315df278d8fSAlp Dener 
31662675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */
31762675beeSAlp Dener 
31862675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
31962675beeSAlp Dener {
32062675beeSAlp Dener   PetscErrorCode               ierr;
32162675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
32262675beeSAlp Dener 
32362675beeSAlp Dener   PetscFunctionBegin;
32462675beeSAlp Dener   /* Compute the Hessian */
32562675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
32662675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
32762675beeSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
32862675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
32962675beeSAlp Dener     /* Update the BFGS diagonal scaling */
33062675beeSAlp Dener     if (BFGS_SCALE_AHESS == bnk->bfgs_scale_type) {
33162675beeSAlp Dener       ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr);
33262675beeSAlp Dener       ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
33362675beeSAlp Dener       ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
33462675beeSAlp Dener       ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
33562675beeSAlp Dener       ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
33662675beeSAlp Dener     }
33762675beeSAlp Dener   }
33862675beeSAlp Dener   PetscFunctionReturn(0);
33962675beeSAlp Dener }
34062675beeSAlp Dener 
34162675beeSAlp Dener /*------------------------------------------------------------*/
34262675beeSAlp Dener 
3432f75a4aaSAlp Dener /* Routine for estimating the active set */
3442f75a4aaSAlp Dener 
34508752603SAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao, PetscInt asType)
3462f75a4aaSAlp Dener {
3472f75a4aaSAlp Dener   PetscErrorCode               ierr;
3482f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3492f75a4aaSAlp Dener 
3502f75a4aaSAlp Dener   PetscFunctionBegin;
35108752603SAlp Dener   switch (asType) {
3522f75a4aaSAlp Dener   case BNK_AS_NONE:
3532f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
3542f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
3552f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
3562f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
3572f75a4aaSAlp Dener     break;
3582f75a4aaSAlp Dener 
3592f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3602f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
3612f75a4aaSAlp Dener     if (BNK_PC_BFGS == bnk->pc_type) {
3622f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
3635e9b73cbSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
3642f75a4aaSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3652f75a4aaSAlp Dener     } else {
3669b6ef848SAlp Dener       /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3672f75a4aaSAlp Dener       ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3689b6ef848SAlp Dener       ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3699b6ef848SAlp Dener       ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3702f75a4aaSAlp Dener       ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3712f75a4aaSAlp Dener       ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
3722f75a4aaSAlp Dener     }
3732f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
3740a4511e9SAlp 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);
3752f75a4aaSAlp Dener 
3762f75a4aaSAlp Dener   default:
3772f75a4aaSAlp Dener     break;
3782f75a4aaSAlp Dener   }
3792f75a4aaSAlp Dener   PetscFunctionReturn(0);
3802f75a4aaSAlp Dener }
3812f75a4aaSAlp Dener 
3822f75a4aaSAlp Dener /*------------------------------------------------------------*/
3832f75a4aaSAlp Dener 
3842f75a4aaSAlp Dener /* Routine for bounding the step direction */
3852f75a4aaSAlp Dener 
3862f75a4aaSAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, Vec step)
3872f75a4aaSAlp Dener {
3882f75a4aaSAlp Dener   PetscErrorCode               ierr;
3892f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3902f75a4aaSAlp Dener 
3912f75a4aaSAlp Dener   PetscFunctionBegin;
39228017e9fSAlp Dener   if (bnk->active_idx) {
3932f75a4aaSAlp Dener     switch (bnk->as_type) {
3942f75a4aaSAlp Dener     case BNK_AS_NONE:
3952f75a4aaSAlp Dener       if (bnk->active_idx) {
3962f75a4aaSAlp Dener         ierr = VecGetSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr);
3972f75a4aaSAlp Dener         ierr = VecSet(bnk->active_work, 0.0);CHKERRQ(ierr);
3982f75a4aaSAlp Dener         ierr = VecRestoreSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr);
3992f75a4aaSAlp Dener       }
4002f75a4aaSAlp Dener       break;
4012f75a4aaSAlp Dener 
4022f75a4aaSAlp Dener     case BNK_AS_BERTSEKAS:
4032f75a4aaSAlp Dener       ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, step);CHKERRQ(ierr);
4042f75a4aaSAlp Dener       break;
4052f75a4aaSAlp Dener 
4062f75a4aaSAlp Dener     default:
4072f75a4aaSAlp Dener       break;
4082f75a4aaSAlp Dener     }
409e465cd6fSAlp Dener   }
4102f75a4aaSAlp Dener   PetscFunctionReturn(0);
4112f75a4aaSAlp Dener }
4122f75a4aaSAlp Dener 
413e031d6f5SAlp Dener /*------------------------------------------------------------*/
414e031d6f5SAlp Dener 
415e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to
416e031d6f5SAlp Dener    accelerate Newton convergence.
417e031d6f5SAlp Dener 
418e031d6f5SAlp Dener    In practice, this approach simply trades off Hessian evaluations
419e031d6f5SAlp Dener    for more gradient evaluations.
420e031d6f5SAlp Dener */
421e031d6f5SAlp Dener 
422c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
423c0f10754SAlp Dener {
424c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
425c0f10754SAlp Dener   PetscErrorCode               ierr;
426c0f10754SAlp Dener 
427c0f10754SAlp Dener   PetscFunctionBegin;
428c0f10754SAlp Dener   *terminate = PETSC_FALSE;
429c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
430c0f10754SAlp Dener     /* Copy the current solution, unprojected gradient and step info into BNCG */
431c0f10754SAlp Dener     bnk->bncg_ctx->f = bnk->f;
432*937a31a1SAlp Dener     ierr = VecCopy(tao->solution, bnk->bncg->solution);CHKERRQ(ierr);
433c0f10754SAlp Dener     ierr = VecCopy(bnk->unprojected_gradient, bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
434c0f10754SAlp Dener     ierr = VecCopy(tao->stepdirection, bnk->bncg->stepdirection);CHKERRQ(ierr);
435c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
436c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
437c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
438c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
439c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
440c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
441c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
442e031d6f5SAlp Dener     bnk->tot_cg_its += bnk->bncg->niter;
443c0f10754SAlp Dener     /* Extract the BNCG solution out and save it into BNK */
444c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
445c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg->solution, tao->solution);
446c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg_ctx->unprojected_gradient, bnk->unprojected_gradient);
447*937a31a1SAlp Dener     ierr = VecCopy(bnk->bncg->gradient, tao->gradient);CHKERRQ(ierr);
448c0f10754SAlp 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) {
449c0f10754SAlp Dener       *terminate = PETSC_TRUE;
450c0f10754SAlp Dener     }
451c0f10754SAlp Dener   }
452c0f10754SAlp Dener   PetscFunctionReturn(0);
453c0f10754SAlp Dener }
454c0f10754SAlp Dener 
4552f75a4aaSAlp Dener /*------------------------------------------------------------*/
4562f75a4aaSAlp Dener 
457c0f10754SAlp Dener /* Routine for computing the Newton step. */
458df278d8fSAlp Dener 
45962675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason)
460eb910715SAlp Dener {
461eb910715SAlp Dener   PetscErrorCode               ierr;
462eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
463eb910715SAlp Dener 
464e465cd6fSAlp Dener   PetscReal                    delta;
465eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
466eb910715SAlp Dener   PetscInt                     kspits;
467eb910715SAlp Dener 
468eb910715SAlp Dener   PetscFunctionBegin;
4695e9b73cbSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
47008752603SAlp Dener   ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
4712f75a4aaSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) { ierr = MatLMVMSetInactive(bnk->M, bnk->inactive_idx);CHKERRQ(ierr); }
4722f75a4aaSAlp Dener   if (bnk->inactive_idx) {
4735e9b73cbSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
4745e9b73cbSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
475eb3ba6a7SAlp Dener     if (tao->hessian == tao->hessian_pre) {
476eb3ba6a7SAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
477eb3ba6a7SAlp Dener     } else {
4785e9b73cbSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
4795e9b73cbSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
480eb3ba6a7SAlp Dener     }
4812f75a4aaSAlp Dener   } else {
48262675beeSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
48362675beeSAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);
48462675beeSAlp Dener     if (tao->hessian == tao->hessian_pre) {
48562675beeSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
48662675beeSAlp Dener     } else {
48762675beeSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
48862675beeSAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);
48962675beeSAlp Dener     }
49062675beeSAlp Dener   }
49162675beeSAlp Dener 
49262675beeSAlp Dener   /* Shift the reduced Hessian matrix */
49362675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
49462675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
49562675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
49662675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
49762675beeSAlp Dener     }
49862675beeSAlp Dener   }
49962675beeSAlp Dener 
50062675beeSAlp Dener   /* Update the diagonal scaling for the BFGS preconditioner, this time with the Hessian perturbation */
50162675beeSAlp Dener   if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_PHESS == bnk->bfgs_scale_type)) {
50262675beeSAlp Dener     /* Obtain diagonal for the bfgs preconditioner  */
5035e9b73cbSAlp Dener     ierr = VecSet(bnk->Diag, 1.0);CHKERRQ(ierr);
5045e9b73cbSAlp Dener     if (bnk->inactive_idx) {
5055e9b73cbSAlp Dener       ierr = VecGetSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
5065e9b73cbSAlp Dener     } else {
5075e9b73cbSAlp Dener       bnk->Diag_red = bnk->Diag;
5085e9b73cbSAlp Dener     }
5095e9b73cbSAlp Dener     ierr = MatGetDiagonal(bnk->H_inactive, bnk->Diag_red);CHKERRQ(ierr);
5105e9b73cbSAlp Dener     if (bnk->inactive_idx) {
5115e9b73cbSAlp Dener       ierr = VecRestoreSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
5125e9b73cbSAlp Dener     }
51362675beeSAlp Dener     ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
51462675beeSAlp Dener     ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
51562675beeSAlp Dener     ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
51662675beeSAlp Dener     ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
5172f75a4aaSAlp Dener   }
51809164190SAlp Dener 
519eb910715SAlp Dener   /* Solve the Newton system of equations */
520*937a31a1SAlp Dener   tao->ksp_its = 0;
5212f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
5225e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
52309164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
5245e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
5255e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5265e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5275e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5285e9b73cbSAlp Dener   } else {
5295e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
5305e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
53128017e9fSAlp Dener   }
532eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
533fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5345e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
535eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
536eb910715SAlp Dener     tao->ksp_its+=kspits;
537eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
538080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
539eb910715SAlp Dener 
540eb910715SAlp Dener     if (0.0 == tao->trust) {
541eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
542080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
543080d2917SAlp Dener         tao->trust = bnk->dnorm;
544eb910715SAlp Dener 
545eb910715SAlp Dener         /* Modify the radius if it is too large or small */
546eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
547eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
548eb910715SAlp Dener       } else {
549eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
550eb910715SAlp Dener            the trust-region subproblem to get a direction */
551eb910715SAlp Dener         tao->trust = tao->trust0;
552eb910715SAlp Dener 
553eb910715SAlp Dener         /* Modify the radius if it is too large or small */
554eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
555eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
556eb910715SAlp Dener 
557fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5585e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
559eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
560eb910715SAlp Dener         tao->ksp_its+=kspits;
561eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
562080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
563eb910715SAlp Dener 
564080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
565eb910715SAlp Dener       }
566eb910715SAlp Dener     }
567eb910715SAlp Dener   } else {
5685e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
569eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
570eb910715SAlp Dener     tao->ksp_its += kspits;
571eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
572eb910715SAlp Dener   }
5735e9b73cbSAlp Dener   /* Restore sub vectors back */
5745e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5755e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5765e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5775e9b73cbSAlp Dener   }
578770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
579fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
5802f75a4aaSAlp Dener   ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
581770b7498SAlp Dener 
582770b7498SAlp Dener   /* Record convergence reasons */
583e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
584e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
585770b7498SAlp Dener     ++bnk->ksp_atol;
586e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
587770b7498SAlp Dener     ++bnk->ksp_rtol;
588e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
589770b7498SAlp Dener     ++bnk->ksp_ctol;
590e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
591770b7498SAlp Dener     ++bnk->ksp_negc;
592e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
593770b7498SAlp Dener     ++bnk->ksp_dtol;
594e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
595770b7498SAlp Dener     ++bnk->ksp_iter;
596770b7498SAlp Dener   } else {
597770b7498SAlp Dener     ++bnk->ksp_othr;
598770b7498SAlp Dener   }
599fed79b8eSAlp Dener 
600fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
601fed79b8eSAlp Dener   if (bnk->pc_type == BNK_PC_BFGS) {
602fed79b8eSAlp Dener     ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
603e465cd6fSAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 1)) {
604fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
6059b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
606eb910715SAlp Dener       ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
607eb910715SAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
60809164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
609eb910715SAlp Dener     }
610fed79b8eSAlp Dener   }
611e465cd6fSAlp Dener   PetscFunctionReturn(0);
612e465cd6fSAlp Dener }
613eb910715SAlp Dener 
61462675beeSAlp Dener /*------------------------------------------------------------*/
61562675beeSAlp Dener 
6165e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
6175e9b73cbSAlp Dener 
6185e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
6195e9b73cbSAlp Dener {
6205e9b73cbSAlp Dener   PetscErrorCode               ierr;
6215e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
6225e9b73cbSAlp Dener 
6235e9b73cbSAlp Dener   PetscFunctionBegin;
6245e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
6255e9b73cbSAlp Dener   if (bnk->inactive_idx){
6265e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6275e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6285e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6295e9b73cbSAlp Dener   } else {
6305e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
6315e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
6325e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
6335e9b73cbSAlp Dener   }
6345e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
6355e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
6365e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
6375e9b73cbSAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);
6385e9b73cbSAlp Dener   /* Restore the sub vectors */
6395e9b73cbSAlp Dener   if (bnk->inactive_idx){
6405e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6415e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6425e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6435e9b73cbSAlp Dener   }
6445e9b73cbSAlp Dener   PetscFunctionReturn(0);
6455e9b73cbSAlp Dener }
6465e9b73cbSAlp Dener 
6475e9b73cbSAlp Dener /*------------------------------------------------------------*/
6485e9b73cbSAlp Dener 
64962675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
65062675beeSAlp Dener 
65162675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
65262675beeSAlp Dener    in the event that the Newton step fails the test.
65362675beeSAlp Dener */
65462675beeSAlp Dener 
655e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
656e465cd6fSAlp Dener {
657e465cd6fSAlp Dener   PetscErrorCode               ierr;
658e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
659e465cd6fSAlp Dener 
660e465cd6fSAlp Dener   PetscReal                    gdx, delta, e_min;
661e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
662e465cd6fSAlp Dener 
663e465cd6fSAlp Dener   PetscFunctionBegin;
664080d2917SAlp Dener   ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
665eb910715SAlp Dener   if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
666eb910715SAlp Dener     /* Newton step is not descent or direction produced Inf or NaN
667eb910715SAlp Dener        Update the perturbation for next time */
668eb910715SAlp Dener     if (bnk->pert <= 0.0) {
669eb910715SAlp Dener       /* Initialize the perturbation */
670eb910715SAlp Dener       bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
671eb910715SAlp Dener       if (bnk->is_gltr) {
672eb910715SAlp Dener         ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
673eb910715SAlp Dener         bnk->pert = PetscMax(bnk->pert, -e_min);
674eb910715SAlp Dener       }
675eb910715SAlp Dener     } else {
676eb910715SAlp Dener       /* Increase the perturbation */
677eb910715SAlp Dener       bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
678eb910715SAlp Dener     }
679eb910715SAlp Dener 
680eb910715SAlp Dener     if (BNK_PC_BFGS != bnk->pc_type) {
681eb910715SAlp Dener       /* We don't have the bfgs matrix around and updated
682eb910715SAlp Dener          Must use gradient direction in this case */
683080d2917SAlp Dener       ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
684eb910715SAlp Dener       *stepType = BNK_GRADIENT;
685eb910715SAlp Dener     } else {
686eb910715SAlp Dener       /* Attempt to use the BFGS direction */
6872ab2a32cSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
68809164190SAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
689eb910715SAlp Dener 
6908d5ead36SAlp Dener       /* Check for success (descent direction)
6918d5ead36SAlp Dener          NOTE: Negative gdx here means not a descent direction because
6928d5ead36SAlp Dener          the fall-back step is missing a negative sign. */
693080d2917SAlp Dener       ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
6948d5ead36SAlp Dener       if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
695eb910715SAlp Dener         /* BFGS direction is not descent or direction produced not a number
696eb910715SAlp Dener            We can assert bfgsUpdates > 1 in this case because
697eb910715SAlp Dener            the first solve produces the scaled gradient direction,
698eb910715SAlp Dener            which is guaranteed to be descent */
699eb910715SAlp Dener 
700eb910715SAlp Dener         /* Use steepest descent direction (scaled) */
7019b6ef848SAlp Dener         delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
702eb910715SAlp Dener         ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
703eb910715SAlp Dener         ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
70409164190SAlp Dener         ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
70509164190SAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
706eb910715SAlp Dener 
707eb910715SAlp Dener         *stepType = BNK_SCALED_GRADIENT;
708eb910715SAlp Dener       } else {
709770b7498SAlp Dener         ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
710eb910715SAlp Dener         if (1 == bfgsUpdates) {
711eb910715SAlp Dener           /* The first BFGS direction is always the scaled gradient */
712eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
713eb910715SAlp Dener         } else {
714eb910715SAlp Dener           *stepType = BNK_BFGS;
715eb910715SAlp Dener         }
716eb910715SAlp Dener       }
717eb910715SAlp Dener     }
7188d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
7198d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
7202f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
721eb910715SAlp Dener   } else {
722eb910715SAlp Dener     /* Computed Newton step is descent */
723eb910715SAlp Dener     switch (ksp_reason) {
724eb910715SAlp Dener     case KSP_DIVERGED_NANORINF:
725eb910715SAlp Dener     case KSP_DIVERGED_BREAKDOWN:
726eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_MAT:
727eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_PC:
728eb910715SAlp Dener     case KSP_CONVERGED_CG_NEG_CURVE:
729eb910715SAlp Dener       /* Matrix or preconditioner is indefinite; increase perturbation */
730eb910715SAlp Dener       if (bnk->pert <= 0.0) {
731eb910715SAlp Dener         /* Initialize the perturbation */
732eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
733eb910715SAlp Dener         if (bnk->is_gltr) {
734eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
735eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
736eb910715SAlp Dener         }
737eb910715SAlp Dener       } else {
738eb910715SAlp Dener         /* Increase the perturbation */
739eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
740eb910715SAlp Dener       }
741eb910715SAlp Dener       break;
742eb910715SAlp Dener 
743eb910715SAlp Dener     default:
744eb910715SAlp Dener       /* Newton step computation is good; decrease perturbation */
745eb910715SAlp Dener       bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
746eb910715SAlp Dener       if (bnk->pert < bnk->pmin) {
747eb910715SAlp Dener         bnk->pert = 0.0;
748eb910715SAlp Dener       }
749eb910715SAlp Dener       break;
750eb910715SAlp Dener     }
751fed79b8eSAlp Dener     *stepType = BNK_NEWTON;
752eb910715SAlp Dener   }
753eb910715SAlp Dener   PetscFunctionReturn(0);
754eb910715SAlp Dener }
755eb910715SAlp Dener 
756df278d8fSAlp Dener /*------------------------------------------------------------*/
757df278d8fSAlp Dener 
758df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
759df278d8fSAlp Dener 
760df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
761df278d8fSAlp Dener   Newton step does not produce a valid step length.
762df278d8fSAlp Dener */
763df278d8fSAlp Dener 
764*937a31a1SAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt *stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
765c14b763aSAlp Dener {
766c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
767c14b763aSAlp Dener   PetscErrorCode ierr;
768c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
769c14b763aSAlp Dener 
770c14b763aSAlp Dener   PetscReal      e_min, gdx, delta;
771c14b763aSAlp Dener   PetscInt       bfgsUpdates;
772c14b763aSAlp Dener 
773c14b763aSAlp Dener   PetscFunctionBegin;
774c14b763aSAlp Dener   /* Perform the linesearch */
775c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
776c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
777c14b763aSAlp Dener 
778*937a31a1SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && *stepType != BNK_GRADIENT) {
779c14b763aSAlp Dener     /* Linesearch failed, revert solution */
780c14b763aSAlp Dener     bnk->f = bnk->fold;
781c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
782c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
783c14b763aSAlp Dener 
784*937a31a1SAlp Dener     switch(*stepType) {
785c14b763aSAlp Dener     case BNK_NEWTON:
7868d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
787c14b763aSAlp Dener          Update the perturbation for next time */
788c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
789c14b763aSAlp Dener         /* Initialize the perturbation */
790c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
791c14b763aSAlp Dener         if (bnk->is_gltr) {
792c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
793c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
794c14b763aSAlp Dener         }
795c14b763aSAlp Dener       } else {
796c14b763aSAlp Dener         /* Increase the perturbation */
797c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
798c14b763aSAlp Dener       }
799c14b763aSAlp Dener 
800c14b763aSAlp Dener       if (BNK_PC_BFGS != bnk->pc_type) {
801c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
802c14b763aSAlp Dener            Must use gradient direction in this case */
803*937a31a1SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
804*937a31a1SAlp Dener         *stepType = BNK_GRADIENT;
805c14b763aSAlp Dener       } else {
806c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
807*937a31a1SAlp Dener         ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
808c14b763aSAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
8098d5ead36SAlp Dener         /* Check for success (descent direction)
8108d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
811c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
812c14b763aSAlp Dener         if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
813c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
814c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
815c14b763aSAlp Dener              Use steepest descent direction (scaled) */
8169b6ef848SAlp Dener           delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
817c14b763aSAlp Dener           ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
818c14b763aSAlp Dener           ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
819c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
820c14b763aSAlp Dener           ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
821c14b763aSAlp Dener 
822c14b763aSAlp Dener           bfgsUpdates = 1;
823*937a31a1SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
824c14b763aSAlp Dener         } else {
825c14b763aSAlp Dener           ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
826c14b763aSAlp Dener           if (1 == bfgsUpdates) {
827c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
828*937a31a1SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
829c14b763aSAlp Dener           } else {
830*937a31a1SAlp Dener             *stepType = BNK_BFGS;
831c14b763aSAlp Dener           }
832c14b763aSAlp Dener         }
833c14b763aSAlp Dener       }
834c14b763aSAlp Dener       break;
835c14b763aSAlp Dener 
836c14b763aSAlp Dener     case BNK_BFGS:
837c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
838c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
839c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
8409b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
841c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
842c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
843c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
844*937a31a1SAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
845c14b763aSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
846c14b763aSAlp Dener 
847c14b763aSAlp Dener       bfgsUpdates = 1;
848*937a31a1SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
849c14b763aSAlp Dener       break;
850c14b763aSAlp Dener 
851c14b763aSAlp Dener     case BNK_SCALED_GRADIENT:
852c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
853c14b763aSAlp Dener          The scaled gradient step did not produce a new iterate;
854*937a31a1SAlp Dener          reset the BFGS matrix and attemp to use the gradient direction. */
855c14b763aSAlp Dener       ierr = MatLMVMSetScale(bnk->M,0);CHKERRQ(ierr);
856c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M,1.0);CHKERRQ(ierr);
857c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
858c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
859*937a31a1SAlp Dener       ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
860c14b763aSAlp Dener 
861c14b763aSAlp Dener       bfgsUpdates = 1;
862*937a31a1SAlp Dener       *stepType = BNK_GRADIENT;
863c14b763aSAlp Dener       break;
864c14b763aSAlp Dener     }
8658d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
8668d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
8672f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
868c14b763aSAlp Dener 
8698d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
870c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
871c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
872c14b763aSAlp Dener   }
873c14b763aSAlp Dener   *reason = ls_reason;
874c14b763aSAlp Dener   PetscFunctionReturn(0);
875c14b763aSAlp Dener }
876c14b763aSAlp Dener 
877df278d8fSAlp Dener /*------------------------------------------------------------*/
878df278d8fSAlp Dener 
879df278d8fSAlp Dener /* Routine for updating the trust radius.
880df278d8fSAlp Dener 
881df278d8fSAlp Dener   Function features three different update methods:
882df278d8fSAlp Dener   1) Line-search step length based
883df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
884df278d8fSAlp Dener   3) Interpolation
885df278d8fSAlp Dener */
886df278d8fSAlp Dener 
88728017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
888080d2917SAlp Dener {
889080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
890080d2917SAlp Dener   PetscErrorCode ierr;
891080d2917SAlp Dener 
892b1c2d0e3SAlp Dener   PetscReal      step, kappa;
893080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
894080d2917SAlp Dener 
895080d2917SAlp Dener   PetscFunctionBegin;
896080d2917SAlp Dener   /* Update trust region radius */
897080d2917SAlp Dener   *accept = PETSC_FALSE;
89828017e9fSAlp Dener   switch(updateType) {
899080d2917SAlp Dener   case BNK_UPDATE_STEP:
900c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
901080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
902080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
903080d2917SAlp Dener       if (step < bnk->nu1) {
904080d2917SAlp Dener         /* Very bad step taken; reduce radius */
905080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
906080d2917SAlp Dener       } else if (step < bnk->nu2) {
907080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
908080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
909080d2917SAlp Dener       } else if (step < bnk->nu3) {
910080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
911080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
912080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
913080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
914080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
915080d2917SAlp Dener         }
916080d2917SAlp Dener       } else if (step < bnk->nu4) {
917080d2917SAlp Dener         /*  Full step taken; increase the radius */
918080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
919080d2917SAlp Dener       } else {
920080d2917SAlp Dener         /*  More than full step taken; increase the radius */
921080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
922080d2917SAlp Dener       }
923080d2917SAlp Dener     } else {
924080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
925080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
926080d2917SAlp Dener     }
927080d2917SAlp Dener     break;
928080d2917SAlp Dener 
929080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
930080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
931b1c2d0e3SAlp Dener       if (prered < 0.0) {
932fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
933fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
934fed79b8eSAlp Dener            be rejected! */
935080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
936fed79b8eSAlp Dener       }
937fed79b8eSAlp Dener       else {
938b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
939080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
940080d2917SAlp Dener         } else {
9410a4511e9SAlp Dener           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) &&
9420a4511e9SAlp Dener               (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
943080d2917SAlp Dener             kappa = 1.0;
944fed79b8eSAlp Dener           }
945fed79b8eSAlp Dener           else {
946080d2917SAlp Dener             kappa = actred / prered;
947080d2917SAlp Dener           }
948fed79b8eSAlp Dener 
949fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
950080d2917SAlp Dener           if (kappa < bnk->eta1) {
951fed79b8eSAlp Dener             /* Reject the step */
952080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
953fed79b8eSAlp Dener           }
954fed79b8eSAlp Dener           else {
955fed79b8eSAlp Dener             /* Accept the step */
956c133c014SAlp Dener             *accept = PETSC_TRUE;
957c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
9588d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
959080d2917SAlp Dener               if (kappa < bnk->eta2) {
960080d2917SAlp Dener                 /* Marginal bad step */
961c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
962080d2917SAlp Dener               }
963fed79b8eSAlp Dener               else if (kappa < bnk->eta3) {
964fed79b8eSAlp Dener                 /* Reasonable step */
965fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
966fed79b8eSAlp Dener               }
967fed79b8eSAlp Dener               else if (kappa < bnk->eta4) {
968080d2917SAlp Dener                 /* Good step */
969c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
970fed79b8eSAlp Dener               }
971fed79b8eSAlp Dener               else {
972080d2917SAlp Dener                 /* Very good step */
973c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
974080d2917SAlp Dener               }
975c133c014SAlp Dener             }
976080d2917SAlp Dener           }
977080d2917SAlp Dener         }
978080d2917SAlp Dener       }
979080d2917SAlp Dener     } else {
980080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
981080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
982080d2917SAlp Dener     }
983080d2917SAlp Dener     break;
984080d2917SAlp Dener 
985080d2917SAlp Dener   default:
986080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
987b1c2d0e3SAlp Dener       if (prered < 0.0) {
988080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
989080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
990080d2917SAlp Dener         /*  be rejected! */
991080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
992080d2917SAlp Dener       } else {
993b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
994080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
995080d2917SAlp Dener         } else {
996080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
997080d2917SAlp Dener             kappa = 1.0;
998080d2917SAlp Dener           } else {
999080d2917SAlp Dener             kappa = actred / prered;
1000080d2917SAlp Dener           }
1001080d2917SAlp Dener 
1002080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
1003080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
1004080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
1005080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
1006080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
1007080d2917SAlp Dener 
1008080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
1009080d2917SAlp Dener             /*  Great agreement */
1010080d2917SAlp Dener             *accept = PETSC_TRUE;
1011080d2917SAlp Dener             if (tau_max < 1.0) {
1012080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1013080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
1014080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
1015080d2917SAlp Dener             } else {
1016080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1017080d2917SAlp Dener             }
1018080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
1019080d2917SAlp Dener             /*  Good agreement */
1020080d2917SAlp Dener             *accept = PETSC_TRUE;
1021080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
1022080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1023080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
1024080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1025080d2917SAlp Dener             } else if (tau_max < 1.0) {
1026080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1027080d2917SAlp Dener             } else {
1028080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1029080d2917SAlp Dener             }
1030080d2917SAlp Dener           } else {
1031080d2917SAlp Dener             /*  Not good agreement */
1032080d2917SAlp Dener             if (tau_min > 1.0) {
1033080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1034080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
1035080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1036080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
1037080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1038080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
1039080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
1040080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
1041080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
1042080d2917SAlp Dener             } else {
1043080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1044080d2917SAlp Dener             }
1045080d2917SAlp Dener           }
1046080d2917SAlp Dener         }
1047080d2917SAlp Dener       }
1048080d2917SAlp Dener     } else {
1049080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
1050080d2917SAlp Dener       tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust);
1051080d2917SAlp Dener     }
105228017e9fSAlp Dener     break;
1053080d2917SAlp Dener   }
1054c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
1055c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
1056fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
1057080d2917SAlp Dener   PetscFunctionReturn(0);
1058080d2917SAlp Dener }
1059080d2917SAlp Dener 
1060eb910715SAlp Dener /* ---------------------------------------------------------- */
1061df278d8fSAlp Dener 
106262675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
106362675beeSAlp Dener {
106462675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
106562675beeSAlp Dener 
106662675beeSAlp Dener   PetscFunctionBegin;
106762675beeSAlp Dener   switch (stepType) {
106862675beeSAlp Dener   case BNK_NEWTON:
106962675beeSAlp Dener     ++bnk->newt;
107062675beeSAlp Dener     break;
107162675beeSAlp Dener   case BNK_BFGS:
107262675beeSAlp Dener     ++bnk->bfgs;
107362675beeSAlp Dener     break;
107462675beeSAlp Dener   case BNK_SCALED_GRADIENT:
107562675beeSAlp Dener     ++bnk->sgrad;
107662675beeSAlp Dener     break;
107762675beeSAlp Dener   case BNK_GRADIENT:
107862675beeSAlp Dener     ++bnk->grad;
107962675beeSAlp Dener     break;
108062675beeSAlp Dener   default:
108162675beeSAlp Dener     break;
108262675beeSAlp Dener   }
108362675beeSAlp Dener   PetscFunctionReturn(0);
108462675beeSAlp Dener }
108562675beeSAlp Dener 
108662675beeSAlp Dener /* ---------------------------------------------------------- */
108762675beeSAlp Dener 
10889b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
1089eb910715SAlp Dener {
1090eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1091eb910715SAlp Dener   PetscErrorCode ierr;
10929b6ef848SAlp Dener   KSPType        ksp_type;
1093e031d6f5SAlp Dener   PetscInt       i;
1094eb910715SAlp Dener 
1095eb910715SAlp Dener   PetscFunctionBegin;
1096eb910715SAlp Dener   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);}
1097eb910715SAlp Dener   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);}
1098eb910715SAlp Dener   if (!bnk->W) {ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);}
1099eb910715SAlp Dener   if (!bnk->Xold) {ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);}
1100eb910715SAlp Dener   if (!bnk->Gold) {ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);}
110109164190SAlp Dener   if (!bnk->Xwork) {ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);}
110209164190SAlp Dener   if (!bnk->Gwork) {ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);}
110309164190SAlp Dener   if (!bnk->unprojected_gradient) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);}
110409164190SAlp Dener   if (!bnk->unprojected_gradient_old) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);}
11055e9b73cbSAlp Dener   if (!bnk->Diag_min) {ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);}
11065e9b73cbSAlp Dener   if (!bnk->Diag_max) {ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);}
1107e031d6f5SAlp Dener   if (bnk->max_cg_its > 0) {
1108e031d6f5SAlp Dener     if (!bnk->bncg_sol) {ierr = VecDuplicate(tao->solution,&bnk->bncg_sol);CHKERRQ(ierr);}
1109e031d6f5SAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, bnk->bncg_sol);CHKERRQ(ierr);
1110e031d6f5SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
1111e031d6f5SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
1112e031d6f5SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
1113e031d6f5SAlp Dener 
1114*937a31a1SAlp Dener     ierr = TaoSetConvergenceTest(bnk->bncg, tao->ops->convergencetest, tao->cnvP);CHKERRQ(ierr);
1115e031d6f5SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
1116e031d6f5SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
1117e031d6f5SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
1118e031d6f5SAlp Dener     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr);
1119e031d6f5SAlp Dener     for (i=0; i<tao->numbermonitors; i++) {
1120e031d6f5SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
1121e031d6f5SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
1122e031d6f5SAlp Dener     }
1123*937a31a1SAlp Dener     ierr = TaoSetUp(bnk->bncg);CHKERRQ(ierr);
1124e031d6f5SAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
1125e031d6f5SAlp Dener   }
1126eb910715SAlp Dener   bnk->Diag = 0;
1127c0f10754SAlp Dener   bnk->Diag_red = 0;
1128c0f10754SAlp Dener   bnk->X_inactive = 0;
1129c0f10754SAlp Dener   bnk->G_inactive = 0;
113062675beeSAlp Dener   bnk->inactive_work = 0;
113162675beeSAlp Dener   bnk->active_work = 0;
113262675beeSAlp Dener   bnk->inactive_idx = 0;
113362675beeSAlp Dener   bnk->active_idx = 0;
113462675beeSAlp Dener   bnk->active_lower = 0;
113562675beeSAlp Dener   bnk->active_upper = 0;
113662675beeSAlp Dener   bnk->active_fixed = 0;
1137eb910715SAlp Dener   bnk->M = 0;
113809164190SAlp Dener   bnk->H_inactive = 0;
113909164190SAlp Dener   bnk->Hpre_inactive = 0;
11409b6ef848SAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
11419b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
11429b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
11439b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1144eb910715SAlp Dener   PetscFunctionReturn(0);
1145eb910715SAlp Dener }
1146eb910715SAlp Dener 
1147eb910715SAlp Dener /*------------------------------------------------------------*/
1148df278d8fSAlp Dener 
1149eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao)
1150eb910715SAlp Dener {
1151eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1152eb910715SAlp Dener   PetscErrorCode ierr;
1153eb910715SAlp Dener 
1154eb910715SAlp Dener   PetscFunctionBegin;
1155eb910715SAlp Dener   if (tao->setupcalled) {
1156eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1157eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1158eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
115909164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
116009164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
116109164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
116209164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
116362675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
116462675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1165c0f10754SAlp Dener     if (bnk->max_cg_its > 0) {
1166c0f10754SAlp Dener       ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1167c0f10754SAlp Dener       ierr = VecDestroy(&bnk->bncg_sol);CHKERRQ(ierr);
1168c0f10754SAlp Dener     }
11695e9b73cbSAlp Dener   }
11705e9b73cbSAlp Dener   ierr = VecDestroy(&bnk->Diag);CHKERRQ(ierr);
1171eb910715SAlp Dener   ierr = MatDestroy(&bnk->M);CHKERRQ(ierr);
1172c0f10754SAlp Dener   if (bnk->Hpre_inactive != tao->hessian_pre && bnk->Hpre_inactive != bnk->H_inactive) {ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);}
1173c0f10754SAlp Dener   if (bnk->H_inactive != tao->hessian) {ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);}
1174eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1175eb910715SAlp Dener   PetscFunctionReturn(0);
1176eb910715SAlp Dener }
1177eb910715SAlp Dener 
1178eb910715SAlp Dener /*------------------------------------------------------------*/
1179df278d8fSAlp Dener 
1180eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1181eb910715SAlp Dener {
1182eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1183eb910715SAlp Dener   PetscErrorCode ierr;
1184eb910715SAlp Dener 
1185eb910715SAlp Dener   PetscFunctionBegin;
1186eb910715SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr);
11878d5ead36SAlp 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);
11888d5ead36SAlp 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);
11898d5ead36SAlp 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);
11908d5ead36SAlp 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);
11912f75a4aaSAlp 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);
11928d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
11938d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "minimum initial perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
11948d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "maximum initial perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
11958d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "initial merit factor", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
11968d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "minimum perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
11978d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "maximum perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
11988d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
11998d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
12008d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "merit growth factor", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
12018d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "merit shrink factor", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
12028d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "poor steplength; reduce radius", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
12038d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "reasonable steplength; leave radius alone", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
12048d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "good steplength; increase radius", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
12058d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "excellent steplength; greatly increase radius", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
12068d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha1", "", "", bnk->alpha1, &bnk->alpha1,NULL);CHKERRQ(ierr);
12078d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha2", "", "", bnk->alpha2, &bnk->alpha2,NULL);CHKERRQ(ierr);
12088d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha3", "", "", bnk->alpha3, &bnk->alpha3,NULL);CHKERRQ(ierr);
12098d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha4", "", "", bnk->alpha4, &bnk->alpha4,NULL);CHKERRQ(ierr);
12108d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha5", "", "", bnk->alpha5, &bnk->alpha5,NULL);CHKERRQ(ierr);
12118d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu1", "poor steplength; reduce radius", "", bnk->nu1, &bnk->nu1,NULL);CHKERRQ(ierr);
12128d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu2", "reasonable steplength; leave radius alone", "", bnk->nu2, &bnk->nu2,NULL);CHKERRQ(ierr);
12138d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu3", "good steplength; increase radius", "", bnk->nu3, &bnk->nu3,NULL);CHKERRQ(ierr);
12148d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu4", "excellent steplength; greatly increase radius", "", bnk->nu4, &bnk->nu4,NULL);CHKERRQ(ierr);
12158d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega1", "", "", bnk->omega1, &bnk->omega1,NULL);CHKERRQ(ierr);
12168d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega2", "", "", bnk->omega2, &bnk->omega2,NULL);CHKERRQ(ierr);
12178d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega3", "", "", bnk->omega3, &bnk->omega3,NULL);CHKERRQ(ierr);
12188d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega4", "", "", bnk->omega4, &bnk->omega4,NULL);CHKERRQ(ierr);
12198d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega5", "", "", bnk->omega5, &bnk->omega5,NULL);CHKERRQ(ierr);
12208d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1_i", "", "", bnk->mu1_i, &bnk->mu1_i,NULL);CHKERRQ(ierr);
12218d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2_i", "", "", bnk->mu2_i, &bnk->mu2_i,NULL);CHKERRQ(ierr);
12228d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1_i", "", "", bnk->gamma1_i, &bnk->gamma1_i,NULL);CHKERRQ(ierr);
12238d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2_i", "", "", bnk->gamma2_i, &bnk->gamma2_i,NULL);CHKERRQ(ierr);
12248d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3_i", "", "", bnk->gamma3_i, &bnk->gamma3_i,NULL);CHKERRQ(ierr);
12258d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4_i", "", "", bnk->gamma4_i, &bnk->gamma4_i,NULL);CHKERRQ(ierr);
12268d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta_i", "", "", bnk->theta_i, &bnk->theta_i,NULL);CHKERRQ(ierr);
12278d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1", "", "", bnk->mu1, &bnk->mu1,NULL);CHKERRQ(ierr);
12288d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
12298d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1", "", "", bnk->gamma1, &bnk->gamma1,NULL);CHKERRQ(ierr);
12308d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2", "", "", bnk->gamma2, &bnk->gamma2,NULL);CHKERRQ(ierr);
12318d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3", "", "", bnk->gamma3, &bnk->gamma3,NULL);CHKERRQ(ierr);
12328d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4", "", "", bnk->gamma4, &bnk->gamma4,NULL);CHKERRQ(ierr);
12338d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
12348d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
12358d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
12368d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
12370a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_tol", "initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol,NULL);CHKERRQ(ierr);
12380a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_step", "step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step,NULL);CHKERRQ(ierr);
1239c0f10754SAlp 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);
1240eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
1241e031d6f5SAlp Dener   ierr = TaoSetFromOptions(bnk->bncg);
1242eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1243eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1244eb910715SAlp Dener   PetscFunctionReturn(0);
1245eb910715SAlp Dener }
1246eb910715SAlp Dener 
1247eb910715SAlp Dener /*------------------------------------------------------------*/
1248df278d8fSAlp Dener 
1249eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1250eb910715SAlp Dener {
1251eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1252eb910715SAlp Dener   PetscInt       nrejects;
1253eb910715SAlp Dener   PetscBool      isascii;
1254eb910715SAlp Dener   PetscErrorCode ierr;
1255eb910715SAlp Dener 
1256eb910715SAlp Dener   PetscFunctionBegin;
1257eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1258eb910715SAlp Dener   if (isascii) {
1259eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1260eb910715SAlp Dener     if (BNK_PC_BFGS == bnk->pc_type && bnk->M) {
1261eb910715SAlp Dener       ierr = MatLMVMGetRejects(bnk->M,&nrejects);CHKERRQ(ierr);
1262eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects);CHKERRQ(ierr);
1263eb910715SAlp Dener     }
1264e031d6f5SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr);
1265eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1266eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1267eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1268eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1269eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1270eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1271eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1272eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1273eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1274eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1275eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1276eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1277eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1278eb910715SAlp Dener   }
1279eb910715SAlp Dener   PetscFunctionReturn(0);
1280eb910715SAlp Dener }
1281eb910715SAlp Dener 
1282eb910715SAlp Dener /* ---------------------------------------------------------- */
1283df278d8fSAlp Dener 
1284eb910715SAlp Dener /*MC
1285eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
128666ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1287eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1288eb910715SAlp Dener               Hk dk = -gk
12892b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12902b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1291eb910715SAlp Dener 
1292eb910715SAlp Dener     Options Database Keys:
12938d5ead36SAlp Dener + -tao_bnk_pc_type - "none","ahess","bfgs","petsc"
12948d5ead36SAlp Dener . -tao_bnk_bfgs_scale_type - "ahess","phess","bfgs"
12958d5ead36SAlp Dener . -tao_bnk_init_type - "constant","direction","interpolation"
12968d5ead36SAlp Dener . -tao_bnk_update_type - "step","direction","interpolation"
12972f75a4aaSAlp Dener . -tao_bnk_as_type - "none","bertsekas"
12988d5ead36SAlp Dener . -tao_bnk_sval - perturbation starting value
12998d5ead36SAlp Dener . -tao_bnk_imin - minimum initial perturbation
13008d5ead36SAlp Dener . -tao_bnk_imax - maximum initial perturbation
13018d5ead36SAlp Dener . -tao_bnk_pmin - minimum perturbation
13028d5ead36SAlp Dener . -tao_bnk_pmax - maximum perturbation
13038d5ead36SAlp Dener . -tao_bnk_pgfac - growth factor
13048d5ead36SAlp Dener . -tao_bnk_psfac - shrink factor
13058d5ead36SAlp Dener . -tao_bnk_imfac - initial merit factor
13068d5ead36SAlp Dener . -tao_bnk_pmgfac - merit growth factor
13078d5ead36SAlp Dener . -tao_bnk_pmsfac - merit shrink factor
13088d5ead36SAlp Dener . -tao_bnk_eta1 - poor steplength; reduce radius
13098d5ead36SAlp Dener . -tao_bnk_eta2 - reasonable steplength; leave radius
13108d5ead36SAlp Dener . -tao_bnk_eta3 - good steplength; increase readius
13118d5ead36SAlp Dener . -tao_bnk_eta4 - excellent steplength; greatly increase radius
13128d5ead36SAlp Dener . -tao_bnk_alpha1 - alpha1 reduction
13138d5ead36SAlp Dener . -tao_bnk_alpha2 - alpha2 reduction
13148d5ead36SAlp Dener . -tao_bnk_alpha3 - alpha3 reduction
13158d5ead36SAlp Dener . -tao_bnk_alpha4 - alpha4 reduction
13168d5ead36SAlp Dener . -tao_bnk_alpha - alpha5 reduction
13178d5ead36SAlp Dener . -tao_bnk_mu1 - mu1 interpolation update
13188d5ead36SAlp Dener . -tao_bnk_mu2 - mu2 interpolation update
13198d5ead36SAlp Dener . -tao_bnk_gamma1 - gamma1 interpolation update
13208d5ead36SAlp Dener . -tao_bnk_gamma2 - gamma2 interpolation update
13218d5ead36SAlp Dener . -tao_bnk_gamma3 - gamma3 interpolation update
13228d5ead36SAlp Dener . -tao_bnk_gamma4 - gamma4 interpolation update
13238d5ead36SAlp Dener . -tao_bnk_theta - theta interpolation update
13248d5ead36SAlp Dener . -tao_bnk_omega1 - omega1 step update
13258d5ead36SAlp Dener . -tao_bnk_omega2 - omega2 step update
13268d5ead36SAlp Dener . -tao_bnk_omega3 - omega3 step update
13278d5ead36SAlp Dener . -tao_bnk_omega4 - omega4 step update
13288d5ead36SAlp Dener . -tao_bnk_omega5 - omega5 step update
13298d5ead36SAlp Dener . -tao_bnk_mu1_i -  mu1 interpolation init factor
13308d5ead36SAlp Dener . -tao_bnk_mu2_i -  mu2 interpolation init factor
13318d5ead36SAlp Dener . -tao_bnk_gamma1_i -  gamma1 interpolation init factor
13328d5ead36SAlp Dener . -tao_bnk_gamma2_i -  gamma2 interpolation init factor
13338d5ead36SAlp Dener . -tao_bnk_gamma3_i -  gamma3 interpolation init factor
13348d5ead36SAlp Dener . -tao_bnk_gamma4_i -  gamma4 interpolation init factor
13352f75a4aaSAlp Dener . -tao_bnk_theta_i -  theta interpolation init factor
13362f75a4aaSAlp Dener - -tao_bnk_bound_tol -  initial tolerance used in estimating bounded active variables
1337eb910715SAlp Dener 
1338eb910715SAlp Dener   Level: beginner
1339eb910715SAlp Dener M*/
1340eb910715SAlp Dener 
1341eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1342eb910715SAlp Dener {
1343eb910715SAlp Dener   TAO_BNK        *bnk;
1344eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1345eb910715SAlp Dener   PetscErrorCode ierr;
1346eb910715SAlp Dener 
1347eb910715SAlp Dener   PetscFunctionBegin;
1348eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1349eb910715SAlp Dener 
1350eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1351eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1352eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1353eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1354eb910715SAlp Dener 
1355eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1356eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1357eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1358eb910715SAlp Dener 
1359eb910715SAlp Dener   tao->data = (void*)bnk;
1360eb910715SAlp Dener 
136166ed3702SAlp Dener   /*  Hessian shifting parameters */
1362eb910715SAlp Dener   bnk->sval   = 0.0;
1363eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1364eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1365eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1366eb910715SAlp Dener 
1367eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1368eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1369eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1370eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1371eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1372eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1373eb910715SAlp Dener 
1374eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1375eb910715SAlp Dener   bnk->nu1 = 0.25;
1376eb910715SAlp Dener   bnk->nu2 = 0.50;
1377eb910715SAlp Dener   bnk->nu3 = 1.00;
1378eb910715SAlp Dener   bnk->nu4 = 1.25;
1379eb910715SAlp Dener 
1380eb910715SAlp Dener   bnk->omega1 = 0.25;
1381eb910715SAlp Dener   bnk->omega2 = 0.50;
1382eb910715SAlp Dener   bnk->omega3 = 1.00;
1383eb910715SAlp Dener   bnk->omega4 = 2.00;
1384eb910715SAlp Dener   bnk->omega5 = 4.00;
1385eb910715SAlp Dener 
1386eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1387eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1388eb910715SAlp Dener   bnk->eta2 = 0.25;
1389eb910715SAlp Dener   bnk->eta3 = 0.50;
1390eb910715SAlp Dener   bnk->eta4 = 0.90;
1391eb910715SAlp Dener 
1392eb910715SAlp Dener   bnk->alpha1 = 0.25;
1393eb910715SAlp Dener   bnk->alpha2 = 0.50;
1394eb910715SAlp Dener   bnk->alpha3 = 1.00;
1395eb910715SAlp Dener   bnk->alpha4 = 2.00;
1396eb910715SAlp Dener   bnk->alpha5 = 4.00;
1397eb910715SAlp Dener 
1398eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1399eb910715SAlp Dener   bnk->mu1 = 0.10;
1400eb910715SAlp Dener   bnk->mu2 = 0.50;
1401eb910715SAlp Dener 
1402eb910715SAlp Dener   bnk->gamma1 = 0.25;
1403eb910715SAlp Dener   bnk->gamma2 = 0.50;
1404eb910715SAlp Dener   bnk->gamma3 = 2.00;
1405eb910715SAlp Dener   bnk->gamma4 = 4.00;
1406eb910715SAlp Dener 
1407eb910715SAlp Dener   bnk->theta = 0.05;
1408eb910715SAlp Dener 
1409eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1410eb910715SAlp Dener   bnk->mu1_i = 0.35;
1411eb910715SAlp Dener   bnk->mu2_i = 0.50;
1412eb910715SAlp Dener 
1413eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1414eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1415eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1416eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1417eb910715SAlp Dener 
1418eb910715SAlp Dener   bnk->theta_i = 0.25;
1419eb910715SAlp Dener 
1420eb910715SAlp Dener   /*  Remaining parameters */
1421c0f10754SAlp Dener   bnk->max_cg_its = 0;
1422eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1423eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1424770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
14250a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
14260a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
142762675beeSAlp Dener   bnk->dmin = 1.0e-6;
142862675beeSAlp Dener   bnk->dmax = 1.0e6;
1429eb910715SAlp Dener 
1430e031d6f5SAlp Dener   bnk->pc_type         = BNK_PC_AHESS;
1431eb910715SAlp Dener   bnk->bfgs_scale_type = BFGS_SCALE_PHESS;
1432eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
1433fed79b8eSAlp Dener   bnk->update_type     = BNK_UPDATE_INTERPOLATION;
14342f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1435eb910715SAlp Dener 
1436e031d6f5SAlp Dener   /* Create the embedded BNCG solver */
1437e031d6f5SAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
1438e031d6f5SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
1439e031d6f5SAlp Dener   ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr);
1440e031d6f5SAlp Dener   ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
1441e031d6f5SAlp Dener 
1442c0f10754SAlp Dener   /* Create the line search */
1443eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1444eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1445e031d6f5SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1446eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1447eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1448eb910715SAlp Dener 
1449eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1450eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1451eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1452eb910715SAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr);
1453eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1454eb910715SAlp Dener   PetscFunctionReturn(0);
1455eb910715SAlp Dener }
1456