xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision 70a3f44bee118ee6082c1776abcde12f90c0e20a)
1eb910715SAlp Dener #include <petsctaolinesearch.h>
2eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h>
3eb910715SAlp Dener #include <petscksp.h>
4eb910715SAlp Dener 
5*70a3f44bSAlp Dener static const char *BNK_INIT[64] = {"constant", "direction", "interpolation"};
6*70a3f44bSAlp Dener static const char *BNK_UPDATE[64] = {"step", "reduction", "interpolation"};
7*70a3f44bSAlp Dener static const char *BNK_AS[64] = {"none", "bertsekas"};
8*70a3f44bSAlp Dener 
9e031d6f5SAlp Dener /*------------------------------------------------------------*/
10e031d6f5SAlp Dener 
11df278d8fSAlp Dener /* Routine for initializing the KSP solver, the BFGS preconditioner, and the initial trust radius estimation */
12df278d8fSAlp Dener 
13c0f10754SAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType, PetscBool *needH)
14eb910715SAlp Dener {
15eb910715SAlp Dener   PetscErrorCode               ierr;
16eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
17eb910715SAlp Dener   PC                           pc;
18eb910715SAlp Dener 
1989da521bSAlp Dener   PetscReal                    f_min, ftrial, prered, actred, kappa, sigma, resnorm;
20eb910715SAlp Dener   PetscReal                    tau, tau_1, tau_2, tau_max, tau_min, max_radius;
210ad3a497SAlp Dener   PetscBool                    is_bfgs, is_jacobi, is_symmetric, sym_set;
22c4b75bccSAlp Dener   PetscInt                     n, N, nDiff;
23eb910715SAlp Dener   PetscInt                     i_max = 5;
24eb910715SAlp Dener   PetscInt                     j_max = 1;
25eb910715SAlp Dener   PetscInt                     i, j;
26eb910715SAlp Dener 
27eb910715SAlp Dener   PetscFunctionBegin;
2828017e9fSAlp Dener   /* Project the current point onto the feasible set */
2928017e9fSAlp Dener   ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr);
30e031d6f5SAlp Dener   ierr = TaoSetVariableBounds(bnk->bncg, tao->XL, tao->XU);CHKERRQ(ierr);
31b9ac7092SAlp Dener   if (tao->bounded) {
3228017e9fSAlp Dener     ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr);
33cd929ea3SAlp Dener   }
3428017e9fSAlp Dener 
3528017e9fSAlp Dener   /* Project the initial point onto the feasible region */
363b063059SAlp Dener   ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
3728017e9fSAlp Dener 
3828017e9fSAlp Dener   /* Check convergence criteria */
3928017e9fSAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr);
4061be54a6SAlp Dener   ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
4161be54a6SAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
4261be54a6SAlp Dener   ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
43f5766c09SAlp Dener   ierr = TaoGradientNorm(tao, tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr);
4428017e9fSAlp Dener 
45c0f10754SAlp Dener   /* Test the initial point for convergence */
4689da521bSAlp Dener   ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
4789da521bSAlp Dener   ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
48b4a30f08SAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
49e031d6f5SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
50e031d6f5SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
51c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
52c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
53c0f10754SAlp Dener 
54e031d6f5SAlp Dener   /* Reset KSP stopping reason counters */
55eb910715SAlp Dener   bnk->ksp_atol = 0;
56eb910715SAlp Dener   bnk->ksp_rtol = 0;
57eb910715SAlp Dener   bnk->ksp_dtol = 0;
58eb910715SAlp Dener   bnk->ksp_ctol = 0;
59eb910715SAlp Dener   bnk->ksp_negc = 0;
60eb910715SAlp Dener   bnk->ksp_iter = 0;
61eb910715SAlp Dener   bnk->ksp_othr = 0;
62eb910715SAlp Dener 
63e031d6f5SAlp Dener   /* Reset accepted step type counters */
64e031d6f5SAlp Dener   bnk->tot_cg_its = 0;
65e031d6f5SAlp Dener   bnk->newt = 0;
66e031d6f5SAlp Dener   bnk->bfgs = 0;
67e031d6f5SAlp Dener   bnk->sgrad = 0;
68e031d6f5SAlp Dener   bnk->grad = 0;
69e031d6f5SAlp Dener 
70fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
71fed79b8eSAlp Dener   bnk->pert = bnk->sval;
72fed79b8eSAlp Dener 
73937a31a1SAlp Dener   /* Reset initial steplength to zero (this helps BNCG reset its direction internally) */
74937a31a1SAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
75937a31a1SAlp Dener 
76e031d6f5SAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
77b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
78b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &is_bfgs);CHKERRQ(ierr);
79b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCJACOBI, &is_jacobi);CHKERRQ(ierr);
80b9ac7092SAlp Dener   if (is_bfgs) {
81b9ac7092SAlp Dener     bnk->bfgs_pre = pc;
82b9ac7092SAlp Dener     ierr = PCLMVMGetMatLMVM(bnk->bfgs_pre, &bnk->M);CHKERRQ(ierr);
83eb910715SAlp Dener     ierr = VecGetLocalSize(tao->solution, &n);CHKERRQ(ierr);
84eb910715SAlp Dener     ierr = VecGetSize(tao->solution, &N);CHKERRQ(ierr);
85b9ac7092SAlp Dener     ierr = MatSetSizes(bnk->M, n, n, N, N);CHKERRQ(ierr);
86cd929ea3SAlp Dener     ierr = MatLMVMAllocate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
870ad3a497SAlp Dener     ierr = MatIsSymmetricKnown(bnk->M, &sym_set, &is_symmetric);CHKERRQ(ierr);
880ad3a497SAlp Dener     if (!sym_set || !is_symmetric) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix in the LMVM preconditioner must be symmetric.");
89b9ac7092SAlp Dener   } else if (is_jacobi) {
90b9ac7092SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
91e031d6f5SAlp Dener   }
92e031d6f5SAlp Dener 
93e031d6f5SAlp Dener   /* Prepare the min/max vectors for safeguarding diagonal scales */
9462675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
9562675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
96eb910715SAlp Dener 
97eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
98eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
99c0f10754SAlp Dener   *needH = PETSC_TRUE;
100eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
10162675beeSAlp Dener     switch(initType) {
102eb910715SAlp Dener     case BNK_INIT_CONSTANT:
103eb910715SAlp Dener       /* Use the initial radius specified */
104c0f10754SAlp Dener       tao->trust = tao->trust0;
105eb910715SAlp Dener       break;
106eb910715SAlp Dener 
107eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
108c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
109eb910715SAlp Dener       max_radius = 0.0;
11008752603SAlp Dener       tao->trust = tao->trust0;
111eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1120a4511e9SAlp Dener         f_min = bnk->f;
113eb910715SAlp Dener         sigma = 0.0;
114eb910715SAlp Dener 
115c0f10754SAlp Dener         if (*needH) {
11662602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
117e0ed867bSAlp Dener           ierr = bnk->computehessian(tao);CHKERRQ(ierr);
11808752603SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, BNK_AS_NONE);CHKERRQ(ierr);
11989da521bSAlp Dener           ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
12089da521bSAlp Dener           if (bnk->active_idx) {
1212ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
12228017e9fSAlp Dener           } else {
12308752603SAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
12428017e9fSAlp Dener           }
125c0f10754SAlp Dener           *needH = PETSC_FALSE;
126eb910715SAlp Dener         }
127eb910715SAlp Dener 
128eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
12962602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
13062602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
13162602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
1323b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
13389da521bSAlp Dener           /* Compute the step we actually accepted */
134eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
13562602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
13662602cfbSAlp Dener           /* Compute the objective at the trial */
13762602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
138b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(bnk->f)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
13962602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
140eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
141eb910715SAlp Dener             tau = bnk->gamma1_i;
142eb910715SAlp Dener           } else {
1430a4511e9SAlp Dener             if (ftrial < f_min) {
1440a4511e9SAlp Dener               f_min = ftrial;
145eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
146eb910715SAlp Dener             }
14708752603SAlp Dener 
148770b7498SAlp Dener             /* Compute the predicted and actual reduction */
14989da521bSAlp Dener             if (bnk->active_idx) {
15008752603SAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
15108752603SAlp Dener               ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1522ab2a32cSAlp Dener             } else {
15308752603SAlp Dener               bnk->X_inactive = bnk->W;
15408752603SAlp Dener               bnk->inactive_work = bnk->Xwork;
1552ab2a32cSAlp Dener             }
15608752603SAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
15708752603SAlp Dener             ierr = VecDot(bnk->X_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
15889da521bSAlp Dener             if (bnk->active_idx) {
15908752603SAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
16008752603SAlp Dener               ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1612ab2a32cSAlp Dener             }
162eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
163eb910715SAlp Dener             actred = bnk->f - ftrial;
1643105154fSTodd Munson             if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
165eb910715SAlp Dener               kappa = 1.0;
1663105154fSTodd Munson             } else {
167eb910715SAlp Dener               kappa = actred / prered;
168eb910715SAlp Dener             }
169eb910715SAlp Dener 
170eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
171eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
172eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
173eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
174eb910715SAlp Dener 
175eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
176eb910715SAlp Dener               /*  Great agreement */
177eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
178eb910715SAlp Dener 
179eb910715SAlp Dener               if (tau_max < 1.0) {
180eb910715SAlp Dener                 tau = bnk->gamma3_i;
1813105154fSTodd Munson               } else if (tau_max > bnk->gamma4_i) {
182eb910715SAlp Dener                 tau = bnk->gamma4_i;
1833105154fSTodd Munson               } else {
184eb910715SAlp Dener                 tau = tau_max;
185eb910715SAlp Dener               }
1868f8a4e06SAlp Dener             } else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
187eb910715SAlp Dener               /*  Good agreement */
188eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
189eb910715SAlp Dener 
190eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
191eb910715SAlp Dener                 tau = bnk->gamma2_i;
192eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
193eb910715SAlp Dener                 tau = bnk->gamma3_i;
194eb910715SAlp Dener               } else {
195eb910715SAlp Dener                 tau = tau_max;
196eb910715SAlp Dener               }
1978f8a4e06SAlp Dener             } else {
198eb910715SAlp Dener               /*  Not good agreement */
199eb910715SAlp Dener               if (tau_min > 1.0) {
200eb910715SAlp Dener                 tau = bnk->gamma2_i;
201eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
202eb910715SAlp Dener                 tau = bnk->gamma1_i;
203eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
204eb910715SAlp Dener                 tau = bnk->gamma1_i;
2053105154fSTodd Munson               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
206eb910715SAlp Dener                 tau = tau_1;
2073105154fSTodd Munson               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
208eb910715SAlp Dener                 tau = tau_2;
209eb910715SAlp Dener               } else {
210eb910715SAlp Dener                 tau = tau_max;
211eb910715SAlp Dener               }
212eb910715SAlp Dener             }
213eb910715SAlp Dener           }
214eb910715SAlp Dener           tao->trust = tau * tao->trust;
215eb910715SAlp Dener         }
216eb910715SAlp Dener 
2170a4511e9SAlp Dener         if (f_min < bnk->f) {
218937a31a1SAlp Dener           /* We accidentally found a solution better than the initial, so accept it */
2190a4511e9SAlp Dener           bnk->f = f_min;
220937a31a1SAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
221eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
2223b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
223937a31a1SAlp Dener           ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr);
224937a31a1SAlp Dener           ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr);
22509164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
22661be54a6SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
22761be54a6SAlp Dener           ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
22861be54a6SAlp Dener           ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
229937a31a1SAlp Dener           /* Compute gradient at the new iterate and flip switch to compute the Hessian later */
230f5766c09SAlp Dener           ierr = TaoGradientNorm(tao, tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr);
231c0f10754SAlp Dener           *needH = PETSC_TRUE;
232937a31a1SAlp Dener           /* Test the new step for convergence */
23389da521bSAlp Dener           ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
23489da521bSAlp Dener           ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
235b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
236e031d6f5SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
237e031d6f5SAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
238eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
239eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
240937a31a1SAlp Dener           /* active BNCG recycling early because we have a stepdirection computed */
241937a31a1SAlp Dener           ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
242eb910715SAlp Dener         }
243eb910715SAlp Dener       }
244eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
245e031d6f5SAlp Dener 
246e031d6f5SAlp Dener       /* Ensure that the trust radius is within the limits */
247e031d6f5SAlp Dener       tao->trust = PetscMax(tao->trust, bnk->min_radius);
248e031d6f5SAlp Dener       tao->trust = PetscMin(tao->trust, bnk->max_radius);
249eb910715SAlp Dener       break;
250eb910715SAlp Dener 
251eb910715SAlp Dener     default:
252eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
253eb910715SAlp Dener       tao->trust = 0.0;
254eb910715SAlp Dener       break;
255eb910715SAlp Dener     }
256eb910715SAlp Dener   }
257eb910715SAlp Dener   PetscFunctionReturn(0);
258eb910715SAlp Dener }
259eb910715SAlp Dener 
260df278d8fSAlp Dener /*------------------------------------------------------------*/
261df278d8fSAlp Dener 
262e0ed867bSAlp Dener /* Routine for computing the exact Hessian and preparing the preconditioner at the new iterate */
26362675beeSAlp Dener 
26462675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
26562675beeSAlp Dener {
26662675beeSAlp Dener   PetscErrorCode               ierr;
26762675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
26862675beeSAlp Dener 
26962675beeSAlp Dener   PetscFunctionBegin;
27062675beeSAlp Dener   /* Compute the Hessian */
27162675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
27262675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
273b9ac7092SAlp Dener   if (bnk->M) {
27462675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
27562675beeSAlp Dener   }
276e0ed867bSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
277f5766c09SAlp Dener   if (bnk->Hpre_inactive) {
278f5766c09SAlp Dener     ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
279f5766c09SAlp Dener   }
280f5766c09SAlp Dener   if (bnk->H_inactive) {
281e0ed867bSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
282f5766c09SAlp Dener   }
283f5766c09SAlp Dener   if (bnk->active_idx) {
284e0ed867bSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
285e0ed867bSAlp Dener     if (tao->hessian == tao->hessian_pre) {
286f5766c09SAlp Dener       ierr = PetscObjectReference((PetscObject)bnk->H_inactive);CHKERRQ(ierr);
287e0ed867bSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
288e0ed867bSAlp Dener     } else {
289e0ed867bSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
290e0ed867bSAlp Dener     }
291e0ed867bSAlp Dener     if (bnk->bfgs_pre) {
292e0ed867bSAlp Dener       ierr = PCLMVMSetIS(bnk->bfgs_pre, bnk->inactive_idx);CHKERRQ(ierr);
293e0ed867bSAlp Dener     }
294e0ed867bSAlp Dener   } else {
295e0ed867bSAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
296e0ed867bSAlp Dener     if (tao->hessian == tao->hessian_pre) {
297f5766c09SAlp Dener       ierr = PetscObjectReference((PetscObject)bnk->H_inactive);CHKERRQ(ierr);
298e0ed867bSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
299e0ed867bSAlp Dener     } else {
300e0ed867bSAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);CHKERRQ(ierr);
301e0ed867bSAlp Dener     }
302e0ed867bSAlp Dener     if (bnk->bfgs_pre) {
303e0ed867bSAlp Dener       ierr = PCLMVMClearIS(bnk->bfgs_pre);CHKERRQ(ierr);
304e0ed867bSAlp Dener     }
305e0ed867bSAlp Dener   }
30662675beeSAlp Dener   PetscFunctionReturn(0);
30762675beeSAlp Dener }
30862675beeSAlp Dener 
30962675beeSAlp Dener /*------------------------------------------------------------*/
31062675beeSAlp Dener 
3112f75a4aaSAlp Dener /* Routine for estimating the active set */
3122f75a4aaSAlp Dener 
31308752603SAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao, PetscInt asType)
3142f75a4aaSAlp Dener {
3152f75a4aaSAlp Dener   PetscErrorCode               ierr;
3162f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
317c4b75bccSAlp Dener   PetscBool                    hessComputed, diagExists;
3182f75a4aaSAlp Dener 
3192f75a4aaSAlp Dener   PetscFunctionBegin;
32008752603SAlp Dener   switch (asType) {
3212f75a4aaSAlp Dener   case BNK_AS_NONE:
3222f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
3232f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
3242f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
3252f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
3262f75a4aaSAlp Dener     break;
3272f75a4aaSAlp Dener 
3282f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3292f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
330b9ac7092SAlp Dener     if (bnk->M) {
3312f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
332cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3332f75a4aaSAlp Dener     } else {
334f5766c09SAlp Dener       if (tao->hessian) {
33561be54a6SAlp Dener         ierr = MatAssembled(tao->hessian, &hessComputed);CHKERRQ(ierr);
336c4b75bccSAlp Dener         ierr = MatHasOperation(tao->hessian, MATOP_GET_DIAGONAL, &diagExists);CHKERRQ(ierr);
337f5766c09SAlp Dener       } else {
338f5766c09SAlp Dener         hessComputed = diagExists = PETSC_FALSE;
339f5766c09SAlp Dener       }
340c4b75bccSAlp Dener       if (hessComputed && diagExists) {
3419b6ef848SAlp Dener         /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3422f75a4aaSAlp Dener         ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3439b6ef848SAlp Dener         ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3449b6ef848SAlp Dener         ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3452f75a4aaSAlp Dener         ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3462f75a4aaSAlp Dener         ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
34761be54a6SAlp Dener       } else {
348c4b75bccSAlp Dener         /* If the Hessian or its diagonal does not exist, we will simply use gradient step */
34961be54a6SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
35061be54a6SAlp Dener       }
3512f75a4aaSAlp Dener     }
3522f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
35389da521bSAlp Dener     ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, bnk->unprojected_gradient, bnk->W, bnk->Xwork, bnk->as_step, &bnk->as_tol,
35489da521bSAlp Dener                                    &bnk->active_lower, &bnk->active_upper, &bnk->active_fixed, &bnk->active_idx, &bnk->inactive_idx);CHKERRQ(ierr);
355c4b75bccSAlp Dener     break;
3562f75a4aaSAlp Dener 
3572f75a4aaSAlp Dener   default:
3582f75a4aaSAlp Dener     break;
3592f75a4aaSAlp Dener   }
3602f75a4aaSAlp Dener   PetscFunctionReturn(0);
3612f75a4aaSAlp Dener }
3622f75a4aaSAlp Dener 
3632f75a4aaSAlp Dener /*------------------------------------------------------------*/
3642f75a4aaSAlp Dener 
3652f75a4aaSAlp Dener /* Routine for bounding the step direction */
3662f75a4aaSAlp Dener 
367a1318120SAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, PetscInt asType, Vec step)
3682f75a4aaSAlp Dener {
3692f75a4aaSAlp Dener   PetscErrorCode               ierr;
3702f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3712f75a4aaSAlp Dener 
3722f75a4aaSAlp Dener   PetscFunctionBegin;
373a1318120SAlp Dener   switch (asType) {
3742f75a4aaSAlp Dener   case BNK_AS_NONE:
375c4b75bccSAlp Dener     ierr = VecISSet(step, bnk->active_idx, 0.0);CHKERRQ(ierr);
3762f75a4aaSAlp Dener     break;
3772f75a4aaSAlp Dener 
3782f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
379c4b75bccSAlp Dener     ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, 1.0, step);CHKERRQ(ierr);
3802f75a4aaSAlp Dener     break;
3812f75a4aaSAlp Dener 
3822f75a4aaSAlp Dener   default:
3832f75a4aaSAlp Dener     break;
3842f75a4aaSAlp Dener   }
3852f75a4aaSAlp Dener   PetscFunctionReturn(0);
3862f75a4aaSAlp Dener }
3872f75a4aaSAlp Dener 
388e031d6f5SAlp Dener /*------------------------------------------------------------*/
389e031d6f5SAlp Dener 
390e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to
391e031d6f5SAlp Dener    accelerate Newton convergence.
392e031d6f5SAlp Dener 
393e031d6f5SAlp Dener    In practice, this approach simply trades off Hessian evaluations
394e031d6f5SAlp Dener    for more gradient evaluations.
395e031d6f5SAlp Dener */
396e031d6f5SAlp Dener 
397c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
398c0f10754SAlp Dener {
399c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
400c0f10754SAlp Dener   PetscErrorCode               ierr;
401c0f10754SAlp Dener 
402c0f10754SAlp Dener   PetscFunctionBegin;
403c0f10754SAlp Dener   *terminate = PETSC_FALSE;
404c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
405c4b75bccSAlp Dener     /* Copy the current function value (important vectors are already shared) */
406c0f10754SAlp Dener     bnk->bncg_ctx->f = bnk->f;
407c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
408c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
409c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
410c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
411c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
412c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
413c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
414e031d6f5SAlp Dener     bnk->tot_cg_its += bnk->bncg->niter;
415c4b75bccSAlp Dener     /* Extract the BNCG function value out and save it into BNK */
416c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
417c0f10754SAlp 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) {
418c0f10754SAlp Dener       *terminate = PETSC_TRUE;
41961be54a6SAlp Dener     } else {
42033c78596SAlp Dener       ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
421c0f10754SAlp Dener     }
422c0f10754SAlp Dener   }
423c0f10754SAlp Dener   PetscFunctionReturn(0);
424c0f10754SAlp Dener }
425c0f10754SAlp Dener 
4262f75a4aaSAlp Dener /*------------------------------------------------------------*/
4272f75a4aaSAlp Dener 
428c0f10754SAlp Dener /* Routine for computing the Newton step. */
429df278d8fSAlp Dener 
4306b591159SAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason, PetscInt *step_type)
431eb910715SAlp Dener {
432eb910715SAlp Dener   PetscErrorCode               ierr;
433eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
434eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
435eb910715SAlp Dener   PetscInt                     kspits;
436eb910715SAlp Dener 
437eb910715SAlp Dener   PetscFunctionBegin;
43889da521bSAlp Dener   /* If there are no inactive variables left, save some computation and return an adjusted zero step
43989da521bSAlp Dener      that has (l-x) and (u-x) for lower and upper bounded variables. */
44089da521bSAlp Dener   if (!bnk->inactive_idx) {
44189da521bSAlp Dener     ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
442a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
44389da521bSAlp Dener     PetscFunctionReturn(0);
44489da521bSAlp Dener   }
44589da521bSAlp Dener 
44662675beeSAlp Dener   /* Shift the reduced Hessian matrix */
44762675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
44862675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
44962675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
45062675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
45162675beeSAlp Dener     }
45262675beeSAlp Dener   }
45362675beeSAlp Dener 
454eb910715SAlp Dener   /* Solve the Newton system of equations */
455937a31a1SAlp Dener   tao->ksp_its = 0;
4562f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
4575e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
45809164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
4595e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
46089da521bSAlp Dener   if (bnk->active_idx) {
4615e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
4625e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
4635e9b73cbSAlp Dener   } else {
4645e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
4655e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
46628017e9fSAlp Dener   }
467eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
468fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
4695e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
470eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
471eb910715SAlp Dener     tao->ksp_its+=kspits;
472eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
473080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
474eb910715SAlp Dener 
475eb910715SAlp Dener     if (0.0 == tao->trust) {
476eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
477080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
478080d2917SAlp Dener         tao->trust = bnk->dnorm;
479eb910715SAlp Dener 
480eb910715SAlp Dener         /* Modify the radius if it is too large or small */
481eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
482eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
483eb910715SAlp Dener       } else {
484eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
485eb910715SAlp Dener            the trust-region subproblem to get a direction */
486eb910715SAlp Dener         tao->trust = tao->trust0;
487eb910715SAlp Dener 
488eb910715SAlp Dener         /* Modify the radius if it is too large or small */
489eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
490eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
491eb910715SAlp Dener 
492fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
4935e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
494eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
495eb910715SAlp Dener         tao->ksp_its+=kspits;
496eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
497080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
498eb910715SAlp Dener 
499080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
500eb910715SAlp Dener       }
501eb910715SAlp Dener     }
502eb910715SAlp Dener   } else {
5035e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
504eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
505eb910715SAlp Dener     tao->ksp_its += kspits;
506eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
507eb910715SAlp Dener   }
5085e9b73cbSAlp Dener   /* Restore sub vectors back */
50989da521bSAlp Dener   if (bnk->active_idx) {
5105e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5115e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5125e9b73cbSAlp Dener   }
513770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
514fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
515a1318120SAlp Dener   ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
516770b7498SAlp Dener 
517770b7498SAlp Dener   /* Record convergence reasons */
518e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
519e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
520770b7498SAlp Dener     ++bnk->ksp_atol;
521e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
522770b7498SAlp Dener     ++bnk->ksp_rtol;
523e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
524770b7498SAlp Dener     ++bnk->ksp_ctol;
525e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
526770b7498SAlp Dener     ++bnk->ksp_negc;
527e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
528770b7498SAlp Dener     ++bnk->ksp_dtol;
529e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
530770b7498SAlp Dener     ++bnk->ksp_iter;
531770b7498SAlp Dener   } else {
532770b7498SAlp Dener     ++bnk->ksp_othr;
533770b7498SAlp Dener   }
534fed79b8eSAlp Dener 
535fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
536b9ac7092SAlp Dener   if (bnk->M) {
537cd929ea3SAlp Dener     ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
538b2d8c577SAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 0)) {
539fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
540cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
54109164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
542eb910715SAlp Dener     }
543fed79b8eSAlp Dener   }
5446b591159SAlp Dener   *step_type = BNK_NEWTON;
545e465cd6fSAlp Dener   PetscFunctionReturn(0);
546e465cd6fSAlp Dener }
547eb910715SAlp Dener 
54862675beeSAlp Dener /*------------------------------------------------------------*/
54962675beeSAlp Dener 
5505e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
5515e9b73cbSAlp Dener 
5525e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
5535e9b73cbSAlp Dener {
5545e9b73cbSAlp Dener   PetscErrorCode               ierr;
5555e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
5565e9b73cbSAlp Dener 
5575e9b73cbSAlp Dener   PetscFunctionBegin;
5585e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
55989da521bSAlp Dener   if (bnk->active_idx){
5605e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5615e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5625e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5635e9b73cbSAlp Dener   } else {
5645e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
5655e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
5665e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
5675e9b73cbSAlp Dener   }
5685e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
5695e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
5705e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
57133c78596SAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);CHKERRQ(ierr);
5725e9b73cbSAlp Dener   /* Restore the sub vectors */
57389da521bSAlp Dener   if (bnk->active_idx){
5745e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5755e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5765e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5775e9b73cbSAlp Dener   }
5785e9b73cbSAlp Dener   PetscFunctionReturn(0);
5795e9b73cbSAlp Dener }
5805e9b73cbSAlp Dener 
5815e9b73cbSAlp Dener /*------------------------------------------------------------*/
5825e9b73cbSAlp Dener 
58362675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
58462675beeSAlp Dener 
58562675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
58662675beeSAlp Dener    in the event that the Newton step fails the test.
58762675beeSAlp Dener */
58862675beeSAlp Dener 
589e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
590e465cd6fSAlp Dener {
591e465cd6fSAlp Dener   PetscErrorCode               ierr;
592e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
593e465cd6fSAlp Dener 
594b2d8c577SAlp Dener   PetscReal                    gdx, e_min;
595e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
596e465cd6fSAlp Dener 
597e465cd6fSAlp Dener   PetscFunctionBegin;
5986b591159SAlp Dener   switch (*stepType) {
5996b591159SAlp Dener   case BNK_NEWTON:
600080d2917SAlp Dener     ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
601eb910715SAlp Dener     if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
602eb910715SAlp Dener       /* Newton step is not descent or direction produced Inf or NaN
603eb910715SAlp Dener         Update the perturbation for next time */
604eb910715SAlp Dener       if (bnk->pert <= 0.0) {
605eb910715SAlp Dener         /* Initialize the perturbation */
606eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
607eb910715SAlp Dener         if (bnk->is_gltr) {
608eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
609eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
610eb910715SAlp Dener         }
611eb910715SAlp Dener       } else {
612eb910715SAlp Dener         /* Increase the perturbation */
613eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
614eb910715SAlp Dener       }
615eb910715SAlp Dener 
6160ad3a497SAlp Dener       if (!bnk->M) {
617eb910715SAlp Dener         /* We don't have the bfgs matrix around and updated
618eb910715SAlp Dener           Must use gradient direction in this case */
619080d2917SAlp Dener         ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
620eb910715SAlp Dener         *stepType = BNK_GRADIENT;
621eb910715SAlp Dener       } else {
622eb910715SAlp Dener         /* Attempt to use the BFGS direction */
623cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
624eb910715SAlp Dener 
6258d5ead36SAlp Dener         /* Check for success (descent direction)
6268d5ead36SAlp Dener           NOTE: Negative gdx here means not a descent direction because
6278d5ead36SAlp Dener           the fall-back step is missing a negative sign. */
628080d2917SAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
6293105154fSTodd Munson         if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
630eb910715SAlp Dener           /* BFGS direction is not descent or direction produced not a number
631eb910715SAlp Dener             We can assert bfgsUpdates > 1 in this case because
632eb910715SAlp Dener             the first solve produces the scaled gradient direction,
633eb910715SAlp Dener             which is guaranteed to be descent */
634eb910715SAlp Dener 
635eb910715SAlp Dener           /* Use steepest descent direction (scaled) */
636cd929ea3SAlp Dener           ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
63709164190SAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
638cd929ea3SAlp Dener           ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
639eb910715SAlp Dener 
640eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
641eb910715SAlp Dener         } else {
642cd929ea3SAlp Dener           ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
643eb910715SAlp Dener           if (1 == bfgsUpdates) {
644eb910715SAlp Dener             /* The first BFGS direction is always the scaled gradient */
645eb910715SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
646eb910715SAlp Dener           } else {
647eb910715SAlp Dener             *stepType = BNK_BFGS;
648eb910715SAlp Dener           }
649eb910715SAlp Dener         }
650eb910715SAlp Dener       }
6518d5ead36SAlp Dener       /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
6528d5ead36SAlp Dener       ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
653a1318120SAlp Dener       ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
654eb910715SAlp Dener     } else {
655eb910715SAlp Dener       /* Computed Newton step is descent */
656eb910715SAlp Dener       switch (ksp_reason) {
657eb910715SAlp Dener       case KSP_DIVERGED_NANORINF:
658eb910715SAlp Dener       case KSP_DIVERGED_BREAKDOWN:
659eb910715SAlp Dener       case KSP_DIVERGED_INDEFINITE_MAT:
660eb910715SAlp Dener       case KSP_DIVERGED_INDEFINITE_PC:
661eb910715SAlp Dener       case KSP_CONVERGED_CG_NEG_CURVE:
662eb910715SAlp Dener         /* Matrix or preconditioner is indefinite; increase perturbation */
663eb910715SAlp Dener         if (bnk->pert <= 0.0) {
664eb910715SAlp Dener           /* Initialize the perturbation */
665eb910715SAlp Dener           bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
666eb910715SAlp Dener           if (bnk->is_gltr) {
667eb910715SAlp Dener             ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
668eb910715SAlp Dener             bnk->pert = PetscMax(bnk->pert, -e_min);
669eb910715SAlp Dener           }
670eb910715SAlp Dener         } else {
671eb910715SAlp Dener           /* Increase the perturbation */
672eb910715SAlp Dener           bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
673eb910715SAlp Dener         }
674eb910715SAlp Dener         break;
675eb910715SAlp Dener 
676eb910715SAlp Dener       default:
677eb910715SAlp Dener         /* Newton step computation is good; decrease perturbation */
678eb910715SAlp Dener         bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
679eb910715SAlp Dener         if (bnk->pert < bnk->pmin) {
680eb910715SAlp Dener           bnk->pert = 0.0;
681eb910715SAlp Dener         }
682eb910715SAlp Dener         break;
683eb910715SAlp Dener       }
684fed79b8eSAlp Dener       *stepType = BNK_NEWTON;
685eb910715SAlp Dener     }
6866b591159SAlp Dener     break;
6876b591159SAlp Dener 
6886b591159SAlp Dener   case BNK_BFGS:
6896b591159SAlp Dener     /* Check for success (descent direction) */
6906b591159SAlp Dener     ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
6916b591159SAlp Dener     if (gdx >= 0 || PetscIsInfOrNanReal(gdx)) {
6926b591159SAlp Dener       /* Step is not descent or solve was not successful
6936b591159SAlp Dener          Use steepest descent direction (scaled) */
6946b591159SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
6956b591159SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
6966b591159SAlp Dener       ierr = MatSolve(bnk->M, tao->gradient, tao->stepdirection);CHKERRQ(ierr);
6976b591159SAlp Dener       ierr = VecScale(tao->stepdirection,-1.0);CHKERRQ(ierr);
6986b591159SAlp Dener       ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
6996b591159SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
7006b591159SAlp Dener     } else {
7016b591159SAlp Dener       *stepType = BNK_BFGS;
7026b591159SAlp Dener     }
7036b591159SAlp Dener     break;
7046b591159SAlp Dener 
7056b591159SAlp Dener   case BNK_SCALED_GRADIENT:
7066b591159SAlp Dener     break;
7076b591159SAlp Dener 
7086b591159SAlp Dener   default:
7096b591159SAlp Dener     break;
7106b591159SAlp Dener   }
7116b591159SAlp Dener 
712eb910715SAlp Dener   PetscFunctionReturn(0);
713eb910715SAlp Dener }
714eb910715SAlp Dener 
715df278d8fSAlp Dener /*------------------------------------------------------------*/
716df278d8fSAlp Dener 
717df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
718df278d8fSAlp Dener 
719df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
720df278d8fSAlp Dener   Newton step does not produce a valid step length.
721df278d8fSAlp Dener */
722df278d8fSAlp Dener 
723937a31a1SAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt *stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
724c14b763aSAlp Dener {
725c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
726c14b763aSAlp Dener   PetscErrorCode ierr;
727c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
728c14b763aSAlp Dener 
729b2d8c577SAlp Dener   PetscReal      e_min, gdx;
730c14b763aSAlp Dener   PetscInt       bfgsUpdates;
731c14b763aSAlp Dener 
732c14b763aSAlp Dener   PetscFunctionBegin;
733c14b763aSAlp Dener   /* Perform the linesearch */
734c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
735c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
736c14b763aSAlp Dener 
737b2d8c577SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && *stepType != BNK_SCALED_GRADIENT && *stepType != BNK_GRADIENT) {
738c14b763aSAlp Dener     /* Linesearch failed, revert solution */
739c14b763aSAlp Dener     bnk->f = bnk->fold;
740c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
741c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
742c14b763aSAlp Dener 
743937a31a1SAlp Dener     switch(*stepType) {
744c14b763aSAlp Dener     case BNK_NEWTON:
7458d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
746c14b763aSAlp Dener          Update the perturbation for next time */
747c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
748c14b763aSAlp Dener         /* Initialize the perturbation */
749c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
750c14b763aSAlp Dener         if (bnk->is_gltr) {
751c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
752c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
753c14b763aSAlp Dener         }
754c14b763aSAlp Dener       } else {
755c14b763aSAlp Dener         /* Increase the perturbation */
756c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
757c14b763aSAlp Dener       }
758c14b763aSAlp Dener 
7590ad3a497SAlp Dener       if (!bnk->M) {
760c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
761c14b763aSAlp Dener            Must use gradient direction in this case */
762937a31a1SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
763937a31a1SAlp Dener         *stepType = BNK_GRADIENT;
764c14b763aSAlp Dener       } else {
765c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
766cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
7678d5ead36SAlp Dener         /* Check for success (descent direction)
7688d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
769c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
7703105154fSTodd Munson         if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
771c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
772c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
773c14b763aSAlp Dener              Use steepest descent direction (scaled) */
774cd929ea3SAlp Dener           ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
775c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
776cd929ea3SAlp Dener           ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
777c14b763aSAlp Dener 
778c14b763aSAlp Dener           bfgsUpdates = 1;
779937a31a1SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
780c14b763aSAlp Dener         } else {
781cd929ea3SAlp Dener           ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
782c14b763aSAlp Dener           if (1 == bfgsUpdates) {
783c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
784937a31a1SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
785c14b763aSAlp Dener           } else {
786937a31a1SAlp Dener             *stepType = BNK_BFGS;
787c14b763aSAlp Dener           }
788c14b763aSAlp Dener         }
789c14b763aSAlp Dener       }
790c14b763aSAlp Dener       break;
791c14b763aSAlp Dener 
792c14b763aSAlp Dener     case BNK_BFGS:
793c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
794c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
795c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
796cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
797c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
798cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
799c14b763aSAlp Dener 
800c14b763aSAlp Dener       bfgsUpdates = 1;
801937a31a1SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
802c14b763aSAlp Dener       break;
803c14b763aSAlp Dener     }
8048d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
8058d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
806a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
807c14b763aSAlp Dener 
8088d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
809c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
810c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
811c14b763aSAlp Dener   }
812c14b763aSAlp Dener   *reason = ls_reason;
813c14b763aSAlp Dener   PetscFunctionReturn(0);
814c14b763aSAlp Dener }
815c14b763aSAlp Dener 
816df278d8fSAlp Dener /*------------------------------------------------------------*/
817df278d8fSAlp Dener 
818df278d8fSAlp Dener /* Routine for updating the trust radius.
819df278d8fSAlp Dener 
820df278d8fSAlp Dener   Function features three different update methods:
821df278d8fSAlp Dener   1) Line-search step length based
822df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
823df278d8fSAlp Dener   3) Interpolation
824df278d8fSAlp Dener */
825df278d8fSAlp Dener 
82628017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
827080d2917SAlp Dener {
828080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
829080d2917SAlp Dener   PetscErrorCode ierr;
830080d2917SAlp Dener 
831b1c2d0e3SAlp Dener   PetscReal      step, kappa;
832080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
833080d2917SAlp Dener 
834080d2917SAlp Dener   PetscFunctionBegin;
835080d2917SAlp Dener   /* Update trust region radius */
836080d2917SAlp Dener   *accept = PETSC_FALSE;
83728017e9fSAlp Dener   switch(updateType) {
838080d2917SAlp Dener   case BNK_UPDATE_STEP:
839c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
840080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
841080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
842080d2917SAlp Dener       if (step < bnk->nu1) {
843080d2917SAlp Dener         /* Very bad step taken; reduce radius */
844080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
845080d2917SAlp Dener       } else if (step < bnk->nu2) {
846080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
847080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
848080d2917SAlp Dener       } else if (step < bnk->nu3) {
849080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
850080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
851080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
852080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
853080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
854080d2917SAlp Dener         }
855080d2917SAlp Dener       } else if (step < bnk->nu4) {
856080d2917SAlp Dener         /*  Full step taken; increase the radius */
857080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
858080d2917SAlp Dener       } else {
859080d2917SAlp Dener         /*  More than full step taken; increase the radius */
860080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
861080d2917SAlp Dener       }
862080d2917SAlp Dener     } else {
863080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
864080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
865080d2917SAlp Dener     }
866080d2917SAlp Dener     break;
867080d2917SAlp Dener 
868080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
869080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
870e0ed867bSAlp Dener       if ((prered < 0.0) || PetscIsInfOrNanReal(prered)) {
871fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
872fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
873fed79b8eSAlp Dener            be rejected! */
874080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
8753105154fSTodd Munson       } else {
876b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
877080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
878080d2917SAlp Dener         } else {
8793105154fSTodd Munson           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) && (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
880080d2917SAlp Dener             kappa = 1.0;
8813105154fSTodd Munson           } else {
882080d2917SAlp Dener             kappa = actred / prered;
883080d2917SAlp Dener           }
884fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
885080d2917SAlp Dener           if (kappa < bnk->eta1) {
886fed79b8eSAlp Dener             /* Reject the step */
887080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
8883105154fSTodd Munson           } else {
889fed79b8eSAlp Dener             /* Accept the step */
890c133c014SAlp Dener             *accept = PETSC_TRUE;
891c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
8928d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
893080d2917SAlp Dener               if (kappa < bnk->eta2) {
894080d2917SAlp Dener                 /* Marginal bad step */
895c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
8963105154fSTodd Munson               } else if (kappa < bnk->eta3) {
897fed79b8eSAlp Dener                 /* Reasonable step */
898fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
8993105154fSTodd Munson               } else if (kappa < bnk->eta4) {
900080d2917SAlp Dener                 /* Good step */
901c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
9023105154fSTodd Munson               } else {
903080d2917SAlp Dener                 /* Very good step */
904c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
905080d2917SAlp Dener               }
906c133c014SAlp Dener             }
907080d2917SAlp Dener           }
908080d2917SAlp Dener         }
909080d2917SAlp Dener       }
910080d2917SAlp Dener     } else {
911080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
912080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
913080d2917SAlp Dener     }
914080d2917SAlp Dener     break;
915080d2917SAlp Dener 
916080d2917SAlp Dener   default:
917080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
918b1c2d0e3SAlp Dener       if (prered < 0.0) {
919080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
920080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
921080d2917SAlp Dener         /*  be rejected! */
922080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
923080d2917SAlp Dener       } else {
924b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
925080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
926080d2917SAlp Dener         } else {
927080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
928080d2917SAlp Dener             kappa = 1.0;
929080d2917SAlp Dener           } else {
930080d2917SAlp Dener             kappa = actred / prered;
931080d2917SAlp Dener           }
932080d2917SAlp Dener 
933080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
934080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
935080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
936080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
937080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
938080d2917SAlp Dener 
939080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
940080d2917SAlp Dener             /*  Great agreement */
941080d2917SAlp Dener             *accept = PETSC_TRUE;
942080d2917SAlp Dener             if (tau_max < 1.0) {
943080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
944080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
945080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
946080d2917SAlp Dener             } else {
947080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
948080d2917SAlp Dener             }
949080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
950080d2917SAlp Dener             /*  Good agreement */
951080d2917SAlp Dener             *accept = PETSC_TRUE;
952080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
953080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
954080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
955080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
956080d2917SAlp Dener             } else if (tau_max < 1.0) {
957080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
958080d2917SAlp Dener             } else {
959080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
960080d2917SAlp Dener             }
961080d2917SAlp Dener           } else {
962080d2917SAlp Dener             /*  Not good agreement */
963080d2917SAlp Dener             if (tau_min > 1.0) {
964080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
965080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
966080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
967080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
968080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
969080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
970080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
971080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
972080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
973080d2917SAlp Dener             } else {
974080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
975080d2917SAlp 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->gamma1 * PetscMin(bnk->dnorm, tao->trust);
982080d2917SAlp Dener     }
98328017e9fSAlp Dener     break;
984080d2917SAlp Dener   }
985c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
986c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
987fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
988080d2917SAlp Dener   PetscFunctionReturn(0);
989080d2917SAlp Dener }
990080d2917SAlp Dener 
991eb910715SAlp Dener /* ---------------------------------------------------------- */
992df278d8fSAlp Dener 
99362675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
99462675beeSAlp Dener {
99562675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
99662675beeSAlp Dener 
99762675beeSAlp Dener   PetscFunctionBegin;
99862675beeSAlp Dener   switch (stepType) {
99962675beeSAlp Dener   case BNK_NEWTON:
100062675beeSAlp Dener     ++bnk->newt;
100162675beeSAlp Dener     break;
100262675beeSAlp Dener   case BNK_BFGS:
100362675beeSAlp Dener     ++bnk->bfgs;
100462675beeSAlp Dener     break;
100562675beeSAlp Dener   case BNK_SCALED_GRADIENT:
100662675beeSAlp Dener     ++bnk->sgrad;
100762675beeSAlp Dener     break;
100862675beeSAlp Dener   case BNK_GRADIENT:
100962675beeSAlp Dener     ++bnk->grad;
101062675beeSAlp Dener     break;
101162675beeSAlp Dener   default:
101262675beeSAlp Dener     break;
101362675beeSAlp Dener   }
101462675beeSAlp Dener   PetscFunctionReturn(0);
101562675beeSAlp Dener }
101662675beeSAlp Dener 
101762675beeSAlp Dener /* ---------------------------------------------------------- */
101862675beeSAlp Dener 
10199b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
1020eb910715SAlp Dener {
1021eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1022eb910715SAlp Dener   PetscErrorCode ierr;
1023e031d6f5SAlp Dener   PetscInt       i;
1024eb910715SAlp Dener 
1025eb910715SAlp Dener   PetscFunctionBegin;
1026c4b75bccSAlp Dener   if (!tao->gradient) {
1027c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);
1028c4b75bccSAlp Dener   }
1029c4b75bccSAlp Dener   if (!tao->stepdirection) {
1030c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);
1031c4b75bccSAlp Dener   }
1032c4b75bccSAlp Dener   if (!bnk->W) {
1033c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);
1034c4b75bccSAlp Dener   }
1035c4b75bccSAlp Dener   if (!bnk->Xold) {
1036c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);
1037c4b75bccSAlp Dener   }
1038c4b75bccSAlp Dener   if (!bnk->Gold) {
1039c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);
1040c4b75bccSAlp Dener   }
1041c4b75bccSAlp Dener   if (!bnk->Xwork) {
1042c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);
1043c4b75bccSAlp Dener   }
1044c4b75bccSAlp Dener   if (!bnk->Gwork) {
1045c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);
1046c4b75bccSAlp Dener   }
1047c4b75bccSAlp Dener   if (!bnk->unprojected_gradient) {
1048c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);
1049c4b75bccSAlp Dener   }
1050c4b75bccSAlp Dener   if (!bnk->unprojected_gradient_old) {
1051c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);
1052c4b75bccSAlp Dener   }
1053c4b75bccSAlp Dener   if (!bnk->Diag_min) {
1054c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);
1055c4b75bccSAlp Dener   }
1056c4b75bccSAlp Dener   if (!bnk->Diag_max) {
1057c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);
1058c4b75bccSAlp Dener   }
1059e031d6f5SAlp Dener   if (bnk->max_cg_its > 0) {
1060c4b75bccSAlp Dener     /* Ensure that the important common vectors are shared between BNK and embedded BNCG */
1061c4b75bccSAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
106289da521bSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient_old));CHKERRQ(ierr);
106389da521bSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient_old);CHKERRQ(ierr);
106489da521bSAlp Dener     bnk->bncg_ctx->unprojected_gradient_old = bnk->unprojected_gradient_old;
1065c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient));CHKERRQ(ierr);
1066c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
1067c4b75bccSAlp Dener     bnk->bncg_ctx->unprojected_gradient = bnk->unprojected_gradient;
1068c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->Gold));CHKERRQ(ierr);
1069c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->G_old);CHKERRQ(ierr);
1070c4b75bccSAlp Dener     bnk->bncg_ctx->G_old = bnk->Gold;
1071c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->gradient));CHKERRQ(ierr);
1072c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->gradient);CHKERRQ(ierr);
1073c4b75bccSAlp Dener     bnk->bncg->gradient = tao->gradient;
1074c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->stepdirection));CHKERRQ(ierr);
1075c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->stepdirection);CHKERRQ(ierr);
1076c4b75bccSAlp Dener     bnk->bncg->stepdirection = tao->stepdirection;
1077c4b75bccSAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, tao->solution);CHKERRQ(ierr);
1078c4b75bccSAlp Dener     /* Copy over some settings from BNK into BNCG */
1079e031d6f5SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
1080e031d6f5SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
1081e031d6f5SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
1082937a31a1SAlp Dener     ierr = TaoSetConvergenceTest(bnk->bncg, tao->ops->convergencetest, tao->cnvP);CHKERRQ(ierr);
1083e031d6f5SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
1084e031d6f5SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
1085e031d6f5SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
1086e031d6f5SAlp Dener     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr);
1087c4b75bccSAlp Dener     for (i=0; i<tao->numbermonitors; ++i) {
1088e031d6f5SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
1089e031d6f5SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
1090e031d6f5SAlp Dener     }
1091e031d6f5SAlp Dener   }
1092c0f10754SAlp Dener   bnk->X_inactive = 0;
1093c0f10754SAlp Dener   bnk->G_inactive = 0;
109462675beeSAlp Dener   bnk->inactive_work = 0;
109562675beeSAlp Dener   bnk->active_work = 0;
109662675beeSAlp Dener   bnk->inactive_idx = 0;
109762675beeSAlp Dener   bnk->active_idx = 0;
109862675beeSAlp Dener   bnk->active_lower = 0;
109962675beeSAlp Dener   bnk->active_upper = 0;
110062675beeSAlp Dener   bnk->active_fixed = 0;
1101eb910715SAlp Dener   bnk->M = 0;
110209164190SAlp Dener   bnk->H_inactive = 0;
110309164190SAlp Dener   bnk->Hpre_inactive = 0;
1104eb910715SAlp Dener   PetscFunctionReturn(0);
1105eb910715SAlp Dener }
1106eb910715SAlp Dener 
1107eb910715SAlp Dener /*------------------------------------------------------------*/
1108df278d8fSAlp Dener 
1109e0ed867bSAlp Dener PetscErrorCode TaoDestroy_BNK(Tao tao)
1110eb910715SAlp Dener {
1111eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1112eb910715SAlp Dener   PetscErrorCode ierr;
1113eb910715SAlp Dener 
1114eb910715SAlp Dener   PetscFunctionBegin;
1115eb910715SAlp Dener   if (tao->setupcalled) {
1116eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1117eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1118eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
111909164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
112009164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
112109164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
112209164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
112362675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
112462675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1125c4b75bccSAlp Dener   }
1126ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_lower);CHKERRQ(ierr);
1127ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_upper);CHKERRQ(ierr);
1128ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_fixed);CHKERRQ(ierr);
1129ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
1130ca964c49SAlp Dener   ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
1131c4b75bccSAlp Dener   ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
1132c4b75bccSAlp Dener   ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
1133ca964c49SAlp Dener   ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1134eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1135eb910715SAlp Dener   PetscFunctionReturn(0);
1136eb910715SAlp Dener }
1137eb910715SAlp Dener 
1138eb910715SAlp Dener /*------------------------------------------------------------*/
1139df278d8fSAlp Dener 
1140e0ed867bSAlp Dener PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1141eb910715SAlp Dener {
1142eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1143eb910715SAlp Dener   PetscErrorCode ierr;
1144e0ed867bSAlp Dener   KSPType        ksp_type;
1145eb910715SAlp Dener 
1146eb910715SAlp Dener   PetscFunctionBegin;
11474f4fdda4SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton-Krylov method for bound constrained optimization");CHKERRQ(ierr);
11488d5ead36SAlp 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);
11498d5ead36SAlp 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);
11502f75a4aaSAlp 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);
1151748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "(developer) Hessian perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
1152748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "(developer) minimum initial Hessian perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
1153748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "(developer) maximum initial Hessian perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
1154748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "(developer) initial merit factor for Hessian perturbation", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
1155748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "(developer) minimum Hessian perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
1156748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "(developer) maximum Hessian perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
1157748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "(developer) Hessian perturbation growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
1158748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "(developer) Hessian perturbation shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
1159748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "(developer) merit growth factor for Hessian perturbation", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
1160748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "(developer) merit shrink factor for Hessian perturbation", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
1161748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "(developer) threshold for rejecting step (-tao_bnk_update_type reduction)", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
1162748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "(developer) threshold for accepting marginal step (-tao_bnk_update_type reduction)", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
1163748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "(developer) threshold for accepting reasonable step (-tao_bnk_update_type reduction)", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
1164748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "(developer) threshold for accepting good step (-tao_bnk_update_type reduction)", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
1165748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha1", "(developer) radius reduction factor for rejected step (-tao_bnk_update_type reduction)", "", bnk->alpha1, &bnk->alpha1,NULL);CHKERRQ(ierr);
1166748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha2", "(developer) radius reduction factor for marginally accepted bad step (-tao_bnk_update_type reduction)", "", bnk->alpha2, &bnk->alpha2,NULL);CHKERRQ(ierr);
1167748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha3", "(developer) radius increase factor for reasonable accepted step (-tao_bnk_update_type reduction)", "", bnk->alpha3, &bnk->alpha3,NULL);CHKERRQ(ierr);
1168748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha4", "(developer) radius increase factor for good accepted step (-tao_bnk_update_type reduction)", "", bnk->alpha4, &bnk->alpha4,NULL);CHKERRQ(ierr);
1169748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha5", "(developer) radius increase factor for very good accepted step (-tao_bnk_update_type reduction)", "", bnk->alpha5, &bnk->alpha5,NULL);CHKERRQ(ierr);
1170748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu1", "(developer) threshold for small line-search step length (-tao_bnk_update_type step)", "", bnk->nu1, &bnk->nu1,NULL);CHKERRQ(ierr);
1171748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu2", "(developer) threshold for reasonable line-search step length (-tao_bnk_update_type step)", "", bnk->nu2, &bnk->nu2,NULL);CHKERRQ(ierr);
1172748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu3", "(developer) threshold for large line-search step length (-tao_bnk_update_type step)", "", bnk->nu3, &bnk->nu3,NULL);CHKERRQ(ierr);
1173748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu4", "(developer) threshold for very large line-search step length (-tao_bnk_update_type step)", "", bnk->nu4, &bnk->nu4,NULL);CHKERRQ(ierr);
1174748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega1", "(developer) radius reduction factor for very small line-search step length (-tao_bnk_update_type step)", "", bnk->omega1, &bnk->omega1,NULL);CHKERRQ(ierr);
1175748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega2", "(developer) radius reduction factor for small line-search step length (-tao_bnk_update_type step)", "", bnk->omega2, &bnk->omega2,NULL);CHKERRQ(ierr);
1176748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega3", "(developer) radius factor for decent line-search step length (-tao_bnk_update_type step)", "", bnk->omega3, &bnk->omega3,NULL);CHKERRQ(ierr);
1177748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega4", "(developer) radius increase factor for large line-search step length (-tao_bnk_update_type step)", "", bnk->omega4, &bnk->omega4,NULL);CHKERRQ(ierr);
1178748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega5", "(developer) radius increase factor for very large line-search step length (-tao_bnk_update_type step)", "", bnk->omega5, &bnk->omega5,NULL);CHKERRQ(ierr);
1179748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1_i", "(developer) threshold for accepting very good step (-tao_bnk_init_type interpolation)", "", bnk->mu1_i, &bnk->mu1_i,NULL);CHKERRQ(ierr);
1180748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2_i", "(developer) threshold for accepting good step (-tao_bnk_init_type interpolation)", "", bnk->mu2_i, &bnk->mu2_i,NULL);CHKERRQ(ierr);
1181748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1_i", "(developer) radius reduction factor for rejected very bad step (-tao_bnk_init_type interpolation)", "", bnk->gamma1_i, &bnk->gamma1_i,NULL);CHKERRQ(ierr);
1182748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2_i", "(developer) radius reduction factor for rejected bad step (-tao_bnk_init_type interpolation)", "", bnk->gamma2_i, &bnk->gamma2_i,NULL);CHKERRQ(ierr);
1183748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3_i", "(developer) radius increase factor for accepted good step (-tao_bnk_init_type interpolation)", "", bnk->gamma3_i, &bnk->gamma3_i,NULL);CHKERRQ(ierr);
1184748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4_i", "(developer) radius increase factor for accepted very good step (-tao_bnk_init_type interpolation)", "", bnk->gamma4_i, &bnk->gamma4_i,NULL);CHKERRQ(ierr);
1185748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta_i", "(developer) trust region interpolation factor (-tao_bnk_init_type interpolation)", "", bnk->theta_i, &bnk->theta_i,NULL);CHKERRQ(ierr);
1186748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1", "(developer) threshold for accepting very good step (-tao_bnk_update_type interpolation)", "", bnk->mu1, &bnk->mu1,NULL);CHKERRQ(ierr);
1187748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "(developer) threshold for accepting good step (-tao_bnk_update_type interpolation)", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
1188748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1", "(developer) radius reduction factor for rejected very bad step (-tao_bnk_update_type interpolation)", "", bnk->gamma1, &bnk->gamma1,NULL);CHKERRQ(ierr);
1189748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2", "(developer) radius reduction factor for rejected bad step (-tao_bnk_update_type interpolation)", "", bnk->gamma2, &bnk->gamma2,NULL);CHKERRQ(ierr);
1190748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3", "(developer) radius increase factor for accepted good step (-tao_bnk_update_type interpolation)", "", bnk->gamma3, &bnk->gamma3,NULL);CHKERRQ(ierr);
1191748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4", "(developer) radius increase factor for accepted very good step (-tao_bnk_update_type interpolation)", "", bnk->gamma4, &bnk->gamma4,NULL);CHKERRQ(ierr);
1192748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "(developer) trust region interpolation factor (-tao_bnk_update_type interpolation)", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
1193748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "(developer) lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
1194748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "(developer) upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
1195748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "(developer) tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
1196748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_tol", "(developer) initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol,NULL);CHKERRQ(ierr);
1197748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_step", "(developer) step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step,NULL);CHKERRQ(ierr);
1198c0f10754SAlp 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);
1199eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
120033c78596SAlp Dener   ierr = TaoSetFromOptions(bnk->bncg);CHKERRQ(ierr);
1201eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1202eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1203e0ed867bSAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
1204e0ed867bSAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
1205e0ed867bSAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
1206e0ed867bSAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1207eb910715SAlp Dener   PetscFunctionReturn(0);
1208eb910715SAlp Dener }
1209eb910715SAlp Dener 
1210eb910715SAlp Dener /*------------------------------------------------------------*/
1211df278d8fSAlp Dener 
1212e0ed867bSAlp Dener PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1213eb910715SAlp Dener {
1214eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1215eb910715SAlp Dener   PetscInt       nrejects;
1216eb910715SAlp Dener   PetscBool      isascii;
1217eb910715SAlp Dener   PetscErrorCode ierr;
1218eb910715SAlp Dener 
1219eb910715SAlp Dener   PetscFunctionBegin;
1220eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1221eb910715SAlp Dener   if (isascii) {
1222eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1223b9ac7092SAlp Dener     if (bnk->M) {
1224cd929ea3SAlp Dener       ierr = MatLMVMGetRejectCount(bnk->M,&nrejects);CHKERRQ(ierr);
1225b9ac7092SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected BFGS updates: %D\n",nrejects);CHKERRQ(ierr);
1226eb910715SAlp Dener     }
1227e031d6f5SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr);
1228eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1229b9ac7092SAlp Dener     if (bnk->M) {
1230eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1231b9ac7092SAlp Dener     }
1232eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1233eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1234eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1235eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1236eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1237eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1238eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1239eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1240eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1241eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1242eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1243eb910715SAlp Dener   }
1244eb910715SAlp Dener   PetscFunctionReturn(0);
1245eb910715SAlp Dener }
1246eb910715SAlp Dener 
1247eb910715SAlp Dener /* ---------------------------------------------------------- */
1248df278d8fSAlp Dener 
1249eb910715SAlp Dener /*MC
1250eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
125166ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1252eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1253eb910715SAlp Dener               Hk dk = -gk
12542b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12552b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1256eb910715SAlp Dener 
1257eb910715SAlp Dener     Options Database Keys:
1258e0ed867bSAlp Dener + -max_cg_its - maximum number of bounded conjugate-gradient iterations taken in each Newton loop
1259e0ed867bSAlp Dener . -init_type - trust radius initialization method ("constant", "direction", "interpolation")
1260e0ed867bSAlp Dener . -update_type - trust radius update method ("step", "direction", "interpolation")
1261e0ed867bSAlp Dener . -as_type - active-set estimation method ("none", "bertsekas")
1262e0ed867bSAlp Dener . -as_tol - (developer) initial tolerance used in estimating bounded active variables (-as_type bertsekas)
1263e0ed867bSAlp Dener . -as_step - (developer) trial step length used in estimating bounded active variables (-as_type bertsekas)
1264e0ed867bSAlp Dener . -sval - (developer) Hessian perturbation starting value
1265e0ed867bSAlp Dener . -imin - (developer) minimum initial Hessian perturbation
1266e0ed867bSAlp Dener . -imax - (developer) maximum initial Hessian perturbation
1267e0ed867bSAlp Dener . -pmin - (developer) minimum Hessian perturbation
1268e0ed867bSAlp Dener . -pmax - (developer) aximum Hessian perturbation
1269e0ed867bSAlp Dener . -pgfac - (developer) Hessian perturbation growth factor
1270e0ed867bSAlp Dener . -psfac - (developer) Hessian perturbation shrink factor
1271e0ed867bSAlp Dener . -imfac - (developer) initial merit factor for Hessian perturbation
1272e0ed867bSAlp Dener . -pmgfac - (developer) merit growth factor for Hessian perturbation
1273e0ed867bSAlp Dener . -pmsfac - (developer) merit shrink factor for Hessian perturbation
1274e0ed867bSAlp Dener . -eta1 - (developer) threshold for rejecting step (-update_type reduction)
1275e0ed867bSAlp Dener . -eta2 - (developer) threshold for accepting marginal step (-update_type reduction)
1276e0ed867bSAlp Dener . -eta3 - (developer) threshold for accepting reasonable step (-update_type reduction)
1277e0ed867bSAlp Dener . -eta4 - (developer) threshold for accepting good step (-update_type reduction)
1278e0ed867bSAlp Dener . -alpha1 - (developer) radius reduction factor for rejected step (-update_type reduction)
1279e0ed867bSAlp Dener . -alpha2 - (developer) radius reduction factor for marginally accepted bad step (-update_type reduction)
1280e0ed867bSAlp Dener . -alpha3 - (developer) radius increase factor for reasonable accepted step (-update_type reduction)
1281e0ed867bSAlp Dener . -alpha4 - (developer) radius increase factor for good accepted step (-update_type reduction)
1282e0ed867bSAlp Dener . -alpha5 - (developer) radius increase factor for very good accepted step (-update_type reduction)
1283e0ed867bSAlp Dener . -epsilon - (developer) tolerance for small pred/actual ratios that trigger automatic step acceptance (-update_type reduction)
1284e0ed867bSAlp Dener . -mu1 - (developer) threshold for accepting very good step (-update_type interpolation)
1285e0ed867bSAlp Dener . -mu2 - (developer) threshold for accepting good step (-update_type interpolation)
1286e0ed867bSAlp Dener . -gamma1 - (developer) radius reduction factor for rejected very bad step (-update_type interpolation)
1287e0ed867bSAlp Dener . -gamma2 - (developer) radius reduction factor for rejected bad step (-update_type interpolation)
1288e0ed867bSAlp Dener . -gamma3 - (developer) radius increase factor for accepted good step (-update_type interpolation)
1289e0ed867bSAlp Dener . -gamma4 - (developer) radius increase factor for accepted very good step (-update_type interpolation)
1290e0ed867bSAlp Dener . -theta - (developer) trust region interpolation factor (-update_type interpolation)
1291e0ed867bSAlp Dener . -nu1 - (developer) threshold for small line-search step length (-update_type step)
1292e0ed867bSAlp Dener . -nu2 - (developer) threshold for reasonable line-search step length (-update_type step)
1293e0ed867bSAlp Dener . -nu3 - (developer) threshold for large line-search step length (-update_type step)
1294e0ed867bSAlp Dener . -nu4 - (developer) threshold for very large line-search step length (-update_type step)
1295e0ed867bSAlp Dener . -omega1 - (developer) radius reduction factor for very small line-search step length (-update_type step)
1296e0ed867bSAlp Dener . -omega2 - (developer) radius reduction factor for small line-search step length (-update_type step)
1297e0ed867bSAlp Dener . -omega3 - (developer) radius factor for decent line-search step length (-update_type step)
1298e0ed867bSAlp Dener . -omega4 - (developer) radius increase factor for large line-search step length (-update_type step)
1299e0ed867bSAlp Dener . -omega5 - (developer) radius increase factor for very large line-search step length (-update_type step)
1300e0ed867bSAlp Dener . -mu1_i -  (developer) threshold for accepting very good step (-init_type interpolation)
1301e0ed867bSAlp Dener . -mu2_i -  (developer) threshold for accepting good step (-init_type interpolation)
1302e0ed867bSAlp Dener . -gamma1_i - (developer) radius reduction factor for rejected very bad step (-init_type interpolation)
1303e0ed867bSAlp Dener . -gamma2_i - (developer) radius reduction factor for rejected bad step (-init_type interpolation)
1304e0ed867bSAlp Dener . -gamma3_i - (developer) radius increase factor for accepted good step (-init_type interpolation)
1305e0ed867bSAlp Dener . -gamma4_i - (developer) radius increase factor for accepted very good step (-init_type interpolation)
1306e0ed867bSAlp Dener - -theta_i - (developer) trust region interpolation factor (-init_type interpolation)
1307eb910715SAlp Dener 
1308eb910715SAlp Dener   Level: beginner
1309eb910715SAlp Dener M*/
1310eb910715SAlp Dener 
1311eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1312eb910715SAlp Dener {
1313eb910715SAlp Dener   TAO_BNK        *bnk;
1314eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1315eb910715SAlp Dener   PetscErrorCode ierr;
1316b9ac7092SAlp Dener   PC             pc;
1317eb910715SAlp Dener 
1318eb910715SAlp Dener   PetscFunctionBegin;
1319eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1320eb910715SAlp Dener 
1321eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1322eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1323eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1324eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1325eb910715SAlp Dener 
1326eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1327eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1328eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1329eb910715SAlp Dener 
1330eb910715SAlp Dener   tao->data = (void*)bnk;
1331eb910715SAlp Dener 
133266ed3702SAlp Dener   /*  Hessian shifting parameters */
1333e0ed867bSAlp Dener   bnk->computehessian = TaoBNKComputeHessian;
1334e0ed867bSAlp Dener   bnk->computestep = TaoBNKComputeStep;
1335e0ed867bSAlp Dener 
1336eb910715SAlp Dener   bnk->sval   = 0.0;
1337eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1338eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1339eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1340eb910715SAlp Dener 
1341eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1342eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1343eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1344eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1345eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1346eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1347eb910715SAlp Dener 
1348eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1349eb910715SAlp Dener   bnk->nu1 = 0.25;
1350eb910715SAlp Dener   bnk->nu2 = 0.50;
1351eb910715SAlp Dener   bnk->nu3 = 1.00;
1352eb910715SAlp Dener   bnk->nu4 = 1.25;
1353eb910715SAlp Dener 
1354eb910715SAlp Dener   bnk->omega1 = 0.25;
1355eb910715SAlp Dener   bnk->omega2 = 0.50;
1356eb910715SAlp Dener   bnk->omega3 = 1.00;
1357eb910715SAlp Dener   bnk->omega4 = 2.00;
1358eb910715SAlp Dener   bnk->omega5 = 4.00;
1359eb910715SAlp Dener 
1360eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1361eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1362eb910715SAlp Dener   bnk->eta2 = 0.25;
1363eb910715SAlp Dener   bnk->eta3 = 0.50;
1364eb910715SAlp Dener   bnk->eta4 = 0.90;
1365eb910715SAlp Dener 
1366eb910715SAlp Dener   bnk->alpha1 = 0.25;
1367eb910715SAlp Dener   bnk->alpha2 = 0.50;
1368eb910715SAlp Dener   bnk->alpha3 = 1.00;
1369eb910715SAlp Dener   bnk->alpha4 = 2.00;
1370eb910715SAlp Dener   bnk->alpha5 = 4.00;
1371eb910715SAlp Dener 
1372eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1373eb910715SAlp Dener   bnk->mu1 = 0.10;
1374eb910715SAlp Dener   bnk->mu2 = 0.50;
1375eb910715SAlp Dener 
1376eb910715SAlp Dener   bnk->gamma1 = 0.25;
1377eb910715SAlp Dener   bnk->gamma2 = 0.50;
1378eb910715SAlp Dener   bnk->gamma3 = 2.00;
1379eb910715SAlp Dener   bnk->gamma4 = 4.00;
1380eb910715SAlp Dener 
1381eb910715SAlp Dener   bnk->theta = 0.05;
1382eb910715SAlp Dener 
1383eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1384eb910715SAlp Dener   bnk->mu1_i = 0.35;
1385eb910715SAlp Dener   bnk->mu2_i = 0.50;
1386eb910715SAlp Dener 
1387eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1388eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1389eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1390eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1391eb910715SAlp Dener 
1392eb910715SAlp Dener   bnk->theta_i = 0.25;
1393eb910715SAlp Dener 
1394eb910715SAlp Dener   /*  Remaining parameters */
1395c0f10754SAlp Dener   bnk->max_cg_its = 0;
1396eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1397eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1398770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
13990a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
14000a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
140162675beeSAlp Dener   bnk->dmin = 1.0e-6;
140262675beeSAlp Dener   bnk->dmax = 1.0e6;
1403eb910715SAlp Dener 
1404b9ac7092SAlp Dener   bnk->M               = 0;
1405b9ac7092SAlp Dener   bnk->bfgs_pre        = 0;
1406eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
14077b1c7716SAlp Dener   bnk->update_type     = BNK_UPDATE_REDUCTION;
14082f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1409eb910715SAlp Dener 
1410e031d6f5SAlp Dener   /* Create the embedded BNCG solver */
1411e031d6f5SAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
1412e031d6f5SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
1413e031d6f5SAlp Dener   ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr);
1414e031d6f5SAlp Dener   ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
1415e031d6f5SAlp Dener 
1416c0f10754SAlp Dener   /* Create the line search */
1417eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1418eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1419e031d6f5SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1420eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1421eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1422eb910715SAlp Dener 
1423eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1424eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1425eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1426e0ed867bSAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,"tao_bnk_");CHKERRQ(ierr);
1427eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1428b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);
1429b9ac7092SAlp Dener   ierr = PCSetType(pc, PCLMVM);CHKERRQ(ierr);
1430eb910715SAlp Dener   PetscFunctionReturn(0);
1431eb910715SAlp Dener }
1432