xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision f5766c097db85df4ee62e2acb750cb76ef9efd11)
1eb910715SAlp Dener #include <petsctaolinesearch.h>
2eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h>
3eb910715SAlp Dener 
4eb910715SAlp Dener #include <petscksp.h>
5eb910715SAlp Dener 
6e031d6f5SAlp Dener /*------------------------------------------------------------*/
7e031d6f5SAlp Dener 
8df278d8fSAlp Dener /* Routine for initializing the KSP solver, the BFGS preconditioner, and the initial trust radius estimation */
9df278d8fSAlp Dener 
10c0f10754SAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType, PetscBool *needH)
11eb910715SAlp Dener {
12eb910715SAlp Dener   PetscErrorCode               ierr;
13eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
14eb910715SAlp Dener   PC                           pc;
15eb910715SAlp Dener 
1689da521bSAlp Dener   PetscReal                    f_min, ftrial, prered, actred, kappa, sigma, resnorm;
17eb910715SAlp Dener   PetscReal                    tau, tau_1, tau_2, tau_max, tau_min, max_radius;
180ad3a497SAlp Dener   PetscBool                    is_bfgs, is_jacobi, is_symmetric, sym_set;
19c4b75bccSAlp Dener   PetscInt                     n, N, nDiff;
20eb910715SAlp Dener   PetscInt                     i_max = 5;
21eb910715SAlp Dener   PetscInt                     j_max = 1;
22eb910715SAlp Dener   PetscInt                     i, j;
23eb910715SAlp Dener 
24eb910715SAlp Dener   PetscFunctionBegin;
2528017e9fSAlp Dener   /* Project the current point onto the feasible set */
2628017e9fSAlp Dener   ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr);
27e031d6f5SAlp Dener   ierr = TaoSetVariableBounds(bnk->bncg, tao->XL, tao->XU);CHKERRQ(ierr);
28b9ac7092SAlp Dener   if (tao->bounded) {
2928017e9fSAlp Dener     ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr);
30cd929ea3SAlp Dener   }
3128017e9fSAlp Dener 
3228017e9fSAlp Dener   /* Project the initial point onto the feasible region */
333b063059SAlp Dener   ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
3428017e9fSAlp Dener 
3528017e9fSAlp Dener   /* Check convergence criteria */
3628017e9fSAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr);
3761be54a6SAlp Dener   ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
3861be54a6SAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
3961be54a6SAlp Dener   ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
40*f5766c09SAlp Dener   ierr = TaoGradientNorm(tao, tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr);
4128017e9fSAlp Dener 
42c0f10754SAlp Dener   /* Test the initial point for convergence */
4389da521bSAlp Dener   ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
4489da521bSAlp Dener   ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
45b4a30f08SAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
46e031d6f5SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
47e031d6f5SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
48c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
49c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
50c0f10754SAlp Dener 
51e031d6f5SAlp Dener   /* Reset KSP stopping reason counters */
52eb910715SAlp Dener   bnk->ksp_atol = 0;
53eb910715SAlp Dener   bnk->ksp_rtol = 0;
54eb910715SAlp Dener   bnk->ksp_dtol = 0;
55eb910715SAlp Dener   bnk->ksp_ctol = 0;
56eb910715SAlp Dener   bnk->ksp_negc = 0;
57eb910715SAlp Dener   bnk->ksp_iter = 0;
58eb910715SAlp Dener   bnk->ksp_othr = 0;
59eb910715SAlp Dener 
60e031d6f5SAlp Dener   /* Reset accepted step type counters */
61e031d6f5SAlp Dener   bnk->tot_cg_its = 0;
62e031d6f5SAlp Dener   bnk->newt = 0;
63e031d6f5SAlp Dener   bnk->bfgs = 0;
64e031d6f5SAlp Dener   bnk->sgrad = 0;
65e031d6f5SAlp Dener   bnk->grad = 0;
66e031d6f5SAlp Dener 
67fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
68fed79b8eSAlp Dener   bnk->pert = bnk->sval;
69fed79b8eSAlp Dener 
70937a31a1SAlp Dener   /* Reset initial steplength to zero (this helps BNCG reset its direction internally) */
71937a31a1SAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
72937a31a1SAlp Dener 
73e031d6f5SAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
74b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
75b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &is_bfgs);CHKERRQ(ierr);
76b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCJACOBI, &is_jacobi);CHKERRQ(ierr);
77b9ac7092SAlp Dener   if (is_bfgs) {
78b9ac7092SAlp Dener     bnk->bfgs_pre = pc;
79b9ac7092SAlp Dener     ierr = PCLMVMGetMatLMVM(bnk->bfgs_pre, &bnk->M);CHKERRQ(ierr);
80eb910715SAlp Dener     ierr = VecGetLocalSize(tao->solution, &n);CHKERRQ(ierr);
81eb910715SAlp Dener     ierr = VecGetSize(tao->solution, &N);CHKERRQ(ierr);
82b9ac7092SAlp Dener     ierr = MatSetSizes(bnk->M, n, n, N, N);CHKERRQ(ierr);
83cd929ea3SAlp Dener     ierr = MatLMVMAllocate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
840ad3a497SAlp Dener     ierr = MatIsSymmetricKnown(bnk->M, &sym_set, &is_symmetric);CHKERRQ(ierr);
850ad3a497SAlp Dener     if (!sym_set || !is_symmetric) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix in the LMVM preconditioner must be symmetric.");
86b9ac7092SAlp Dener   } else if (is_jacobi) {
87b9ac7092SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
88e031d6f5SAlp Dener   }
89e031d6f5SAlp Dener 
90e031d6f5SAlp Dener   /* Prepare the min/max vectors for safeguarding diagonal scales */
9162675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
9262675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
93eb910715SAlp Dener 
94eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
95eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
96c0f10754SAlp Dener   *needH = PETSC_TRUE;
97eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
9862675beeSAlp Dener     switch(initType) {
99eb910715SAlp Dener     case BNK_INIT_CONSTANT:
100eb910715SAlp Dener       /* Use the initial radius specified */
101c0f10754SAlp Dener       tao->trust = tao->trust0;
102eb910715SAlp Dener       break;
103eb910715SAlp Dener 
104eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
105c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
106eb910715SAlp Dener       max_radius = 0.0;
10708752603SAlp Dener       tao->trust = tao->trust0;
108eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1090a4511e9SAlp Dener         f_min = bnk->f;
110eb910715SAlp Dener         sigma = 0.0;
111eb910715SAlp Dener 
112c0f10754SAlp Dener         if (*needH) {
11362602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
114e0ed867bSAlp Dener           ierr = bnk->computehessian(tao);CHKERRQ(ierr);
11508752603SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, BNK_AS_NONE);CHKERRQ(ierr);
11689da521bSAlp Dener           ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
11789da521bSAlp Dener           if (bnk->active_idx) {
1182ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
11928017e9fSAlp Dener           } else {
12008752603SAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
12128017e9fSAlp Dener           }
122c0f10754SAlp Dener           *needH = PETSC_FALSE;
123eb910715SAlp Dener         }
124eb910715SAlp Dener 
125eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
12662602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
12762602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
12862602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
1293b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
13089da521bSAlp Dener           /* Compute the step we actually accepted */
131eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
13262602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
13362602cfbSAlp Dener           /* Compute the objective at the trial */
13462602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
135b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(bnk->f)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
13662602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
137eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
138eb910715SAlp Dener             tau = bnk->gamma1_i;
139eb910715SAlp Dener           } else {
1400a4511e9SAlp Dener             if (ftrial < f_min) {
1410a4511e9SAlp Dener               f_min = ftrial;
142eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
143eb910715SAlp Dener             }
14408752603SAlp Dener 
145770b7498SAlp Dener             /* Compute the predicted and actual reduction */
14689da521bSAlp Dener             if (bnk->active_idx) {
14708752603SAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
14808752603SAlp Dener               ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1492ab2a32cSAlp Dener             } else {
15008752603SAlp Dener               bnk->X_inactive = bnk->W;
15108752603SAlp Dener               bnk->inactive_work = bnk->Xwork;
1522ab2a32cSAlp Dener             }
15308752603SAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
15408752603SAlp Dener             ierr = VecDot(bnk->X_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
15589da521bSAlp Dener             if (bnk->active_idx) {
15608752603SAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
15708752603SAlp Dener               ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1582ab2a32cSAlp Dener             }
159eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
160eb910715SAlp Dener             actred = bnk->f - ftrial;
1613105154fSTodd Munson             if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
162eb910715SAlp Dener               kappa = 1.0;
1633105154fSTodd Munson             } else {
164eb910715SAlp Dener               kappa = actred / prered;
165eb910715SAlp Dener             }
166eb910715SAlp Dener 
167eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
168eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
169eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
170eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
171eb910715SAlp Dener 
172eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
173eb910715SAlp Dener               /*  Great agreement */
174eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
175eb910715SAlp Dener 
176eb910715SAlp Dener               if (tau_max < 1.0) {
177eb910715SAlp Dener                 tau = bnk->gamma3_i;
1783105154fSTodd Munson               } else if (tau_max > bnk->gamma4_i) {
179eb910715SAlp Dener                 tau = bnk->gamma4_i;
1803105154fSTodd Munson               } else {
181eb910715SAlp Dener                 tau = tau_max;
182eb910715SAlp Dener               }
1838f8a4e06SAlp Dener             } else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
184eb910715SAlp Dener               /*  Good agreement */
185eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
186eb910715SAlp Dener 
187eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
188eb910715SAlp Dener                 tau = bnk->gamma2_i;
189eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
190eb910715SAlp Dener                 tau = bnk->gamma3_i;
191eb910715SAlp Dener               } else {
192eb910715SAlp Dener                 tau = tau_max;
193eb910715SAlp Dener               }
1948f8a4e06SAlp Dener             } else {
195eb910715SAlp Dener               /*  Not good agreement */
196eb910715SAlp Dener               if (tau_min > 1.0) {
197eb910715SAlp Dener                 tau = bnk->gamma2_i;
198eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
199eb910715SAlp Dener                 tau = bnk->gamma1_i;
200eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
201eb910715SAlp Dener                 tau = bnk->gamma1_i;
2023105154fSTodd Munson               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
203eb910715SAlp Dener                 tau = tau_1;
2043105154fSTodd Munson               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
205eb910715SAlp Dener                 tau = tau_2;
206eb910715SAlp Dener               } else {
207eb910715SAlp Dener                 tau = tau_max;
208eb910715SAlp Dener               }
209eb910715SAlp Dener             }
210eb910715SAlp Dener           }
211eb910715SAlp Dener           tao->trust = tau * tao->trust;
212eb910715SAlp Dener         }
213eb910715SAlp Dener 
2140a4511e9SAlp Dener         if (f_min < bnk->f) {
215937a31a1SAlp Dener           /* We accidentally found a solution better than the initial, so accept it */
2160a4511e9SAlp Dener           bnk->f = f_min;
217937a31a1SAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
218eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
2193b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
220937a31a1SAlp Dener           ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr);
221937a31a1SAlp Dener           ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr);
22209164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
22361be54a6SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
22461be54a6SAlp Dener           ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
22561be54a6SAlp Dener           ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
226937a31a1SAlp Dener           /* Compute gradient at the new iterate and flip switch to compute the Hessian later */
227*f5766c09SAlp Dener           ierr = TaoGradientNorm(tao, tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr);
228c0f10754SAlp Dener           *needH = PETSC_TRUE;
229937a31a1SAlp Dener           /* Test the new step for convergence */
23089da521bSAlp Dener           ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
23189da521bSAlp Dener           ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
232b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
233e031d6f5SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
234e031d6f5SAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
235eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
236eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
237937a31a1SAlp Dener           /* active BNCG recycling early because we have a stepdirection computed */
238937a31a1SAlp Dener           ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
239eb910715SAlp Dener         }
240eb910715SAlp Dener       }
241eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
242e031d6f5SAlp Dener 
243e031d6f5SAlp Dener       /* Ensure that the trust radius is within the limits */
244e031d6f5SAlp Dener       tao->trust = PetscMax(tao->trust, bnk->min_radius);
245e031d6f5SAlp Dener       tao->trust = PetscMin(tao->trust, bnk->max_radius);
246eb910715SAlp Dener       break;
247eb910715SAlp Dener 
248eb910715SAlp Dener     default:
249eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
250eb910715SAlp Dener       tao->trust = 0.0;
251eb910715SAlp Dener       break;
252eb910715SAlp Dener     }
253eb910715SAlp Dener   }
254eb910715SAlp Dener   PetscFunctionReturn(0);
255eb910715SAlp Dener }
256eb910715SAlp Dener 
257df278d8fSAlp Dener /*------------------------------------------------------------*/
258df278d8fSAlp Dener 
259e0ed867bSAlp Dener /* Routine for computing the exact Hessian and preparing the preconditioner at the new iterate */
26062675beeSAlp Dener 
26162675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
26262675beeSAlp Dener {
26362675beeSAlp Dener   PetscErrorCode               ierr;
26462675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
26562675beeSAlp Dener 
26662675beeSAlp Dener   PetscFunctionBegin;
26762675beeSAlp Dener   /* Compute the Hessian */
26862675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
26962675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
270b9ac7092SAlp Dener   if (bnk->M) {
27162675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
27262675beeSAlp Dener   }
273e0ed867bSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
274*f5766c09SAlp Dener   if (bnk->Hpre_inactive) {
275*f5766c09SAlp Dener     ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
276*f5766c09SAlp Dener   }
277*f5766c09SAlp Dener   if (bnk->H_inactive) {
278e0ed867bSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
279*f5766c09SAlp Dener   }
280*f5766c09SAlp Dener   if (bnk->active_idx) {
281e0ed867bSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
282e0ed867bSAlp Dener     if (tao->hessian == tao->hessian_pre) {
283*f5766c09SAlp Dener       ierr = PetscObjectReference((PetscObject)bnk->H_inactive);CHKERRQ(ierr);
284e0ed867bSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
285e0ed867bSAlp Dener     } else {
286e0ed867bSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
287e0ed867bSAlp Dener     }
288e0ed867bSAlp Dener     if (bnk->bfgs_pre) {
289e0ed867bSAlp Dener       ierr = PCLMVMSetIS(bnk->bfgs_pre, bnk->inactive_idx);CHKERRQ(ierr);
290e0ed867bSAlp Dener     }
291e0ed867bSAlp Dener   } else {
292e0ed867bSAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
293e0ed867bSAlp Dener     if (tao->hessian == tao->hessian_pre) {
294*f5766c09SAlp Dener       ierr = PetscObjectReference((PetscObject)bnk->H_inactive);CHKERRQ(ierr);
295e0ed867bSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
296e0ed867bSAlp Dener     } else {
297e0ed867bSAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);CHKERRQ(ierr);
298e0ed867bSAlp Dener     }
299e0ed867bSAlp Dener     if (bnk->bfgs_pre) {
300e0ed867bSAlp Dener       ierr = PCLMVMClearIS(bnk->bfgs_pre);CHKERRQ(ierr);
301e0ed867bSAlp Dener     }
302e0ed867bSAlp Dener   }
30362675beeSAlp Dener   PetscFunctionReturn(0);
30462675beeSAlp Dener }
30562675beeSAlp Dener 
30662675beeSAlp Dener /*------------------------------------------------------------*/
30762675beeSAlp Dener 
3082f75a4aaSAlp Dener /* Routine for estimating the active set */
3092f75a4aaSAlp Dener 
31008752603SAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao, PetscInt asType)
3112f75a4aaSAlp Dener {
3122f75a4aaSAlp Dener   PetscErrorCode               ierr;
3132f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
314c4b75bccSAlp Dener   PetscBool                    hessComputed, diagExists;
3152f75a4aaSAlp Dener 
3162f75a4aaSAlp Dener   PetscFunctionBegin;
31708752603SAlp Dener   switch (asType) {
3182f75a4aaSAlp Dener   case BNK_AS_NONE:
3192f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
3202f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
3212f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
3222f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
3232f75a4aaSAlp Dener     break;
3242f75a4aaSAlp Dener 
3252f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3262f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
327b9ac7092SAlp Dener     if (bnk->M) {
3282f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
329cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3302f75a4aaSAlp Dener     } else {
331*f5766c09SAlp Dener       if (tao->hessian) {
33261be54a6SAlp Dener         ierr = MatAssembled(tao->hessian, &hessComputed);CHKERRQ(ierr);
333c4b75bccSAlp Dener         ierr = MatHasOperation(tao->hessian, MATOP_GET_DIAGONAL, &diagExists);CHKERRQ(ierr);
334*f5766c09SAlp Dener       } else {
335*f5766c09SAlp Dener         hessComputed = diagExists = PETSC_FALSE;
336*f5766c09SAlp Dener       }
337c4b75bccSAlp Dener       if (hessComputed && diagExists) {
3389b6ef848SAlp Dener         /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3392f75a4aaSAlp Dener         ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3409b6ef848SAlp Dener         ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3419b6ef848SAlp Dener         ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3422f75a4aaSAlp Dener         ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3432f75a4aaSAlp Dener         ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
34461be54a6SAlp Dener       } else {
345c4b75bccSAlp Dener         /* If the Hessian or its diagonal does not exist, we will simply use gradient step */
34661be54a6SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
34761be54a6SAlp Dener       }
3482f75a4aaSAlp Dener     }
3492f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
35089da521bSAlp Dener     ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, bnk->unprojected_gradient, bnk->W, bnk->Xwork, bnk->as_step, &bnk->as_tol,
35189da521bSAlp Dener                                    &bnk->active_lower, &bnk->active_upper, &bnk->active_fixed, &bnk->active_idx, &bnk->inactive_idx);CHKERRQ(ierr);
352c4b75bccSAlp Dener     break;
3532f75a4aaSAlp Dener 
3542f75a4aaSAlp Dener   default:
3552f75a4aaSAlp Dener     break;
3562f75a4aaSAlp Dener   }
3572f75a4aaSAlp Dener   PetscFunctionReturn(0);
3582f75a4aaSAlp Dener }
3592f75a4aaSAlp Dener 
3602f75a4aaSAlp Dener /*------------------------------------------------------------*/
3612f75a4aaSAlp Dener 
3622f75a4aaSAlp Dener /* Routine for bounding the step direction */
3632f75a4aaSAlp Dener 
364a1318120SAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, PetscInt asType, Vec step)
3652f75a4aaSAlp Dener {
3662f75a4aaSAlp Dener   PetscErrorCode               ierr;
3672f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3682f75a4aaSAlp Dener 
3692f75a4aaSAlp Dener   PetscFunctionBegin;
370a1318120SAlp Dener   switch (asType) {
3712f75a4aaSAlp Dener   case BNK_AS_NONE:
372c4b75bccSAlp Dener     ierr = VecISSet(step, bnk->active_idx, 0.0);CHKERRQ(ierr);
3732f75a4aaSAlp Dener     break;
3742f75a4aaSAlp Dener 
3752f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
376c4b75bccSAlp Dener     ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, 1.0, step);CHKERRQ(ierr);
3772f75a4aaSAlp Dener     break;
3782f75a4aaSAlp Dener 
3792f75a4aaSAlp Dener   default:
3802f75a4aaSAlp Dener     break;
3812f75a4aaSAlp Dener   }
3822f75a4aaSAlp Dener   PetscFunctionReturn(0);
3832f75a4aaSAlp Dener }
3842f75a4aaSAlp Dener 
385e031d6f5SAlp Dener /*------------------------------------------------------------*/
386e031d6f5SAlp Dener 
387e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to
388e031d6f5SAlp Dener    accelerate Newton convergence.
389e031d6f5SAlp Dener 
390e031d6f5SAlp Dener    In practice, this approach simply trades off Hessian evaluations
391e031d6f5SAlp Dener    for more gradient evaluations.
392e031d6f5SAlp Dener */
393e031d6f5SAlp Dener 
394c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
395c0f10754SAlp Dener {
396c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
397c0f10754SAlp Dener   PetscErrorCode               ierr;
398c0f10754SAlp Dener 
399c0f10754SAlp Dener   PetscFunctionBegin;
400c0f10754SAlp Dener   *terminate = PETSC_FALSE;
401c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
402c4b75bccSAlp Dener     /* Copy the current function value (important vectors are already shared) */
403c0f10754SAlp Dener     bnk->bncg_ctx->f = bnk->f;
404c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
405c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
406c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
407c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
408c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
409c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
410c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
411e031d6f5SAlp Dener     bnk->tot_cg_its += bnk->bncg->niter;
412c4b75bccSAlp Dener     /* Extract the BNCG function value out and save it into BNK */
413c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
414c0f10754SAlp 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) {
415c0f10754SAlp Dener       *terminate = PETSC_TRUE;
41661be54a6SAlp Dener     } else {
41733c78596SAlp Dener       ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
418c0f10754SAlp Dener     }
419c0f10754SAlp Dener   }
420c0f10754SAlp Dener   PetscFunctionReturn(0);
421c0f10754SAlp Dener }
422c0f10754SAlp Dener 
4232f75a4aaSAlp Dener /*------------------------------------------------------------*/
4242f75a4aaSAlp Dener 
425c0f10754SAlp Dener /* Routine for computing the Newton step. */
426df278d8fSAlp Dener 
4276b591159SAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason, PetscInt *step_type)
428eb910715SAlp Dener {
429eb910715SAlp Dener   PetscErrorCode               ierr;
430eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
431eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
432eb910715SAlp Dener   PetscInt                     kspits;
433eb910715SAlp Dener 
434eb910715SAlp Dener   PetscFunctionBegin;
43589da521bSAlp Dener   /* If there are no inactive variables left, save some computation and return an adjusted zero step
43689da521bSAlp Dener      that has (l-x) and (u-x) for lower and upper bounded variables. */
43789da521bSAlp Dener   if (!bnk->inactive_idx) {
43889da521bSAlp Dener     ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
439a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
44089da521bSAlp Dener     PetscFunctionReturn(0);
44189da521bSAlp Dener   }
44289da521bSAlp Dener 
44362675beeSAlp Dener   /* Shift the reduced Hessian matrix */
44462675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
44562675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
44662675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
44762675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
44862675beeSAlp Dener     }
44962675beeSAlp Dener   }
45062675beeSAlp Dener 
451eb910715SAlp Dener   /* Solve the Newton system of equations */
452937a31a1SAlp Dener   tao->ksp_its = 0;
4532f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
4545e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
45509164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
4565e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
45789da521bSAlp Dener   if (bnk->active_idx) {
4585e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
4595e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
4605e9b73cbSAlp Dener   } else {
4615e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
4625e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
46328017e9fSAlp Dener   }
464eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
465fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
4665e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
467eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
468eb910715SAlp Dener     tao->ksp_its+=kspits;
469eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
470080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
471eb910715SAlp Dener 
472eb910715SAlp Dener     if (0.0 == tao->trust) {
473eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
474080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
475080d2917SAlp Dener         tao->trust = bnk->dnorm;
476eb910715SAlp Dener 
477eb910715SAlp Dener         /* Modify the radius if it is too large or small */
478eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
479eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
480eb910715SAlp Dener       } else {
481eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
482eb910715SAlp Dener            the trust-region subproblem to get a direction */
483eb910715SAlp Dener         tao->trust = tao->trust0;
484eb910715SAlp Dener 
485eb910715SAlp Dener         /* Modify the radius if it is too large or small */
486eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
487eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
488eb910715SAlp Dener 
489fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
4905e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
491eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
492eb910715SAlp Dener         tao->ksp_its+=kspits;
493eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
494080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
495eb910715SAlp Dener 
496080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
497eb910715SAlp Dener       }
498eb910715SAlp Dener     }
499eb910715SAlp Dener   } else {
5005e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
501eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
502eb910715SAlp Dener     tao->ksp_its += kspits;
503eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
504eb910715SAlp Dener   }
5055e9b73cbSAlp Dener   /* Restore sub vectors back */
50689da521bSAlp Dener   if (bnk->active_idx) {
5075e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5085e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5095e9b73cbSAlp Dener   }
510770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
511fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
512a1318120SAlp Dener   ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
513770b7498SAlp Dener 
514770b7498SAlp Dener   /* Record convergence reasons */
515e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
516e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
517770b7498SAlp Dener     ++bnk->ksp_atol;
518e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
519770b7498SAlp Dener     ++bnk->ksp_rtol;
520e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
521770b7498SAlp Dener     ++bnk->ksp_ctol;
522e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
523770b7498SAlp Dener     ++bnk->ksp_negc;
524e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
525770b7498SAlp Dener     ++bnk->ksp_dtol;
526e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
527770b7498SAlp Dener     ++bnk->ksp_iter;
528770b7498SAlp Dener   } else {
529770b7498SAlp Dener     ++bnk->ksp_othr;
530770b7498SAlp Dener   }
531fed79b8eSAlp Dener 
532fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
533b9ac7092SAlp Dener   if (bnk->M) {
534cd929ea3SAlp Dener     ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
535b2d8c577SAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 0)) {
536fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
537cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
53809164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
539eb910715SAlp Dener     }
540fed79b8eSAlp Dener   }
5416b591159SAlp Dener   *step_type = BNK_NEWTON;
542e465cd6fSAlp Dener   PetscFunctionReturn(0);
543e465cd6fSAlp Dener }
544eb910715SAlp Dener 
54562675beeSAlp Dener /*------------------------------------------------------------*/
54662675beeSAlp Dener 
5475e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
5485e9b73cbSAlp Dener 
5495e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
5505e9b73cbSAlp Dener {
5515e9b73cbSAlp Dener   PetscErrorCode               ierr;
5525e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
5535e9b73cbSAlp Dener 
5545e9b73cbSAlp Dener   PetscFunctionBegin;
5555e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
55689da521bSAlp Dener   if (bnk->active_idx){
5575e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5585e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5595e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5605e9b73cbSAlp Dener   } else {
5615e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
5625e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
5635e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
5645e9b73cbSAlp Dener   }
5655e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
5665e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
5675e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
56833c78596SAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);CHKERRQ(ierr);
5695e9b73cbSAlp Dener   /* Restore the sub vectors */
57089da521bSAlp Dener   if (bnk->active_idx){
5715e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5725e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5735e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5745e9b73cbSAlp Dener   }
5755e9b73cbSAlp Dener   PetscFunctionReturn(0);
5765e9b73cbSAlp Dener }
5775e9b73cbSAlp Dener 
5785e9b73cbSAlp Dener /*------------------------------------------------------------*/
5795e9b73cbSAlp Dener 
58062675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
58162675beeSAlp Dener 
58262675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
58362675beeSAlp Dener    in the event that the Newton step fails the test.
58462675beeSAlp Dener */
58562675beeSAlp Dener 
586e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
587e465cd6fSAlp Dener {
588e465cd6fSAlp Dener   PetscErrorCode               ierr;
589e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
590e465cd6fSAlp Dener 
591b2d8c577SAlp Dener   PetscReal                    gdx, e_min;
592e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
593e465cd6fSAlp Dener 
594e465cd6fSAlp Dener   PetscFunctionBegin;
5956b591159SAlp Dener   switch (*stepType) {
5966b591159SAlp Dener   case BNK_NEWTON:
597080d2917SAlp Dener     ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
598eb910715SAlp Dener     if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
599eb910715SAlp Dener       /* Newton step is not descent or direction produced Inf or NaN
600eb910715SAlp Dener         Update the perturbation for next time */
601eb910715SAlp Dener       if (bnk->pert <= 0.0) {
602eb910715SAlp Dener         /* Initialize the perturbation */
603eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
604eb910715SAlp Dener         if (bnk->is_gltr) {
605eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
606eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
607eb910715SAlp Dener         }
608eb910715SAlp Dener       } else {
609eb910715SAlp Dener         /* Increase the perturbation */
610eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
611eb910715SAlp Dener       }
612eb910715SAlp Dener 
6130ad3a497SAlp Dener       if (!bnk->M) {
614eb910715SAlp Dener         /* We don't have the bfgs matrix around and updated
615eb910715SAlp Dener           Must use gradient direction in this case */
616080d2917SAlp Dener         ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
617eb910715SAlp Dener         *stepType = BNK_GRADIENT;
618eb910715SAlp Dener       } else {
619eb910715SAlp Dener         /* Attempt to use the BFGS direction */
620cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
621eb910715SAlp Dener 
6228d5ead36SAlp Dener         /* Check for success (descent direction)
6238d5ead36SAlp Dener           NOTE: Negative gdx here means not a descent direction because
6248d5ead36SAlp Dener           the fall-back step is missing a negative sign. */
625080d2917SAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
6263105154fSTodd Munson         if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
627eb910715SAlp Dener           /* BFGS direction is not descent or direction produced not a number
628eb910715SAlp Dener             We can assert bfgsUpdates > 1 in this case because
629eb910715SAlp Dener             the first solve produces the scaled gradient direction,
630eb910715SAlp Dener             which is guaranteed to be descent */
631eb910715SAlp Dener 
632eb910715SAlp Dener           /* Use steepest descent direction (scaled) */
633cd929ea3SAlp Dener           ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
63409164190SAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
635cd929ea3SAlp Dener           ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
636eb910715SAlp Dener 
637eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
638eb910715SAlp Dener         } else {
639cd929ea3SAlp Dener           ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
640eb910715SAlp Dener           if (1 == bfgsUpdates) {
641eb910715SAlp Dener             /* The first BFGS direction is always the scaled gradient */
642eb910715SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
643eb910715SAlp Dener           } else {
644eb910715SAlp Dener             *stepType = BNK_BFGS;
645eb910715SAlp Dener           }
646eb910715SAlp Dener         }
647eb910715SAlp Dener       }
6488d5ead36SAlp Dener       /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
6498d5ead36SAlp Dener       ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
650a1318120SAlp Dener       ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
651eb910715SAlp Dener     } else {
652eb910715SAlp Dener       /* Computed Newton step is descent */
653eb910715SAlp Dener       switch (ksp_reason) {
654eb910715SAlp Dener       case KSP_DIVERGED_NANORINF:
655eb910715SAlp Dener       case KSP_DIVERGED_BREAKDOWN:
656eb910715SAlp Dener       case KSP_DIVERGED_INDEFINITE_MAT:
657eb910715SAlp Dener       case KSP_DIVERGED_INDEFINITE_PC:
658eb910715SAlp Dener       case KSP_CONVERGED_CG_NEG_CURVE:
659eb910715SAlp Dener         /* Matrix or preconditioner is indefinite; increase perturbation */
660eb910715SAlp Dener         if (bnk->pert <= 0.0) {
661eb910715SAlp Dener           /* Initialize the perturbation */
662eb910715SAlp Dener           bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
663eb910715SAlp Dener           if (bnk->is_gltr) {
664eb910715SAlp Dener             ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
665eb910715SAlp Dener             bnk->pert = PetscMax(bnk->pert, -e_min);
666eb910715SAlp Dener           }
667eb910715SAlp Dener         } else {
668eb910715SAlp Dener           /* Increase the perturbation */
669eb910715SAlp Dener           bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
670eb910715SAlp Dener         }
671eb910715SAlp Dener         break;
672eb910715SAlp Dener 
673eb910715SAlp Dener       default:
674eb910715SAlp Dener         /* Newton step computation is good; decrease perturbation */
675eb910715SAlp Dener         bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
676eb910715SAlp Dener         if (bnk->pert < bnk->pmin) {
677eb910715SAlp Dener           bnk->pert = 0.0;
678eb910715SAlp Dener         }
679eb910715SAlp Dener         break;
680eb910715SAlp Dener       }
681fed79b8eSAlp Dener       *stepType = BNK_NEWTON;
682eb910715SAlp Dener     }
6836b591159SAlp Dener     break;
6846b591159SAlp Dener 
6856b591159SAlp Dener   case BNK_BFGS:
6866b591159SAlp Dener     /* Check for success (descent direction) */
6876b591159SAlp Dener     ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
6886b591159SAlp Dener     if (gdx >= 0 || PetscIsInfOrNanReal(gdx)) {
6896b591159SAlp Dener       /* Step is not descent or solve was not successful
6906b591159SAlp Dener          Use steepest descent direction (scaled) */
6916b591159SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
6926b591159SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
6936b591159SAlp Dener       ierr = MatSolve(bnk->M, tao->gradient, tao->stepdirection);CHKERRQ(ierr);
6946b591159SAlp Dener       ierr = VecScale(tao->stepdirection,-1.0);CHKERRQ(ierr);
6956b591159SAlp Dener       ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
6966b591159SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
6976b591159SAlp Dener     } else {
6986b591159SAlp Dener       *stepType = BNK_BFGS;
6996b591159SAlp Dener     }
7006b591159SAlp Dener     break;
7016b591159SAlp Dener 
7026b591159SAlp Dener   case BNK_SCALED_GRADIENT:
7036b591159SAlp Dener     break;
7046b591159SAlp Dener 
7056b591159SAlp Dener   default:
7066b591159SAlp Dener     break;
7076b591159SAlp Dener   }
7086b591159SAlp Dener 
709eb910715SAlp Dener   PetscFunctionReturn(0);
710eb910715SAlp Dener }
711eb910715SAlp Dener 
712df278d8fSAlp Dener /*------------------------------------------------------------*/
713df278d8fSAlp Dener 
714df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
715df278d8fSAlp Dener 
716df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
717df278d8fSAlp Dener   Newton step does not produce a valid step length.
718df278d8fSAlp Dener */
719df278d8fSAlp Dener 
720937a31a1SAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt *stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
721c14b763aSAlp Dener {
722c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
723c14b763aSAlp Dener   PetscErrorCode ierr;
724c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
725c14b763aSAlp Dener 
726b2d8c577SAlp Dener   PetscReal      e_min, gdx;
727c14b763aSAlp Dener   PetscInt       bfgsUpdates;
728c14b763aSAlp Dener 
729c14b763aSAlp Dener   PetscFunctionBegin;
730c14b763aSAlp Dener   /* Perform the linesearch */
731c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
732c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
733c14b763aSAlp Dener 
734b2d8c577SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && *stepType != BNK_SCALED_GRADIENT && *stepType != BNK_GRADIENT) {
735c14b763aSAlp Dener     /* Linesearch failed, revert solution */
736c14b763aSAlp Dener     bnk->f = bnk->fold;
737c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
738c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
739c14b763aSAlp Dener 
740937a31a1SAlp Dener     switch(*stepType) {
741c14b763aSAlp Dener     case BNK_NEWTON:
7428d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
743c14b763aSAlp Dener          Update the perturbation for next time */
744c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
745c14b763aSAlp Dener         /* Initialize the perturbation */
746c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
747c14b763aSAlp Dener         if (bnk->is_gltr) {
748c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
749c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
750c14b763aSAlp Dener         }
751c14b763aSAlp Dener       } else {
752c14b763aSAlp Dener         /* Increase the perturbation */
753c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
754c14b763aSAlp Dener       }
755c14b763aSAlp Dener 
7560ad3a497SAlp Dener       if (!bnk->M) {
757c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
758c14b763aSAlp Dener            Must use gradient direction in this case */
759937a31a1SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
760937a31a1SAlp Dener         *stepType = BNK_GRADIENT;
761c14b763aSAlp Dener       } else {
762c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
763cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
7648d5ead36SAlp Dener         /* Check for success (descent direction)
7658d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
766c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
7673105154fSTodd Munson         if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
768c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
769c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
770c14b763aSAlp Dener              Use steepest descent direction (scaled) */
771cd929ea3SAlp Dener           ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
772c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
773cd929ea3SAlp Dener           ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
774c14b763aSAlp Dener 
775c14b763aSAlp Dener           bfgsUpdates = 1;
776937a31a1SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
777c14b763aSAlp Dener         } else {
778cd929ea3SAlp Dener           ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
779c14b763aSAlp Dener           if (1 == bfgsUpdates) {
780c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
781937a31a1SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
782c14b763aSAlp Dener           } else {
783937a31a1SAlp Dener             *stepType = BNK_BFGS;
784c14b763aSAlp Dener           }
785c14b763aSAlp Dener         }
786c14b763aSAlp Dener       }
787c14b763aSAlp Dener       break;
788c14b763aSAlp Dener 
789c14b763aSAlp Dener     case BNK_BFGS:
790c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
791c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
792c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
793cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
794c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
795cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
796c14b763aSAlp Dener 
797c14b763aSAlp Dener       bfgsUpdates = 1;
798937a31a1SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
799c14b763aSAlp Dener       break;
800c14b763aSAlp Dener     }
8018d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
8028d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
803a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
804c14b763aSAlp Dener 
8058d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
806c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
807c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
808c14b763aSAlp Dener   }
809c14b763aSAlp Dener   *reason = ls_reason;
810c14b763aSAlp Dener   PetscFunctionReturn(0);
811c14b763aSAlp Dener }
812c14b763aSAlp Dener 
813df278d8fSAlp Dener /*------------------------------------------------------------*/
814df278d8fSAlp Dener 
815df278d8fSAlp Dener /* Routine for updating the trust radius.
816df278d8fSAlp Dener 
817df278d8fSAlp Dener   Function features three different update methods:
818df278d8fSAlp Dener   1) Line-search step length based
819df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
820df278d8fSAlp Dener   3) Interpolation
821df278d8fSAlp Dener */
822df278d8fSAlp Dener 
82328017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
824080d2917SAlp Dener {
825080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
826080d2917SAlp Dener   PetscErrorCode ierr;
827080d2917SAlp Dener 
828b1c2d0e3SAlp Dener   PetscReal      step, kappa;
829080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
830080d2917SAlp Dener 
831080d2917SAlp Dener   PetscFunctionBegin;
832080d2917SAlp Dener   /* Update trust region radius */
833080d2917SAlp Dener   *accept = PETSC_FALSE;
83428017e9fSAlp Dener   switch(updateType) {
835080d2917SAlp Dener   case BNK_UPDATE_STEP:
836c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
837080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
838080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
839080d2917SAlp Dener       if (step < bnk->nu1) {
840080d2917SAlp Dener         /* Very bad step taken; reduce radius */
841080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
842080d2917SAlp Dener       } else if (step < bnk->nu2) {
843080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
844080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
845080d2917SAlp Dener       } else if (step < bnk->nu3) {
846080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
847080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
848080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
849080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
850080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
851080d2917SAlp Dener         }
852080d2917SAlp Dener       } else if (step < bnk->nu4) {
853080d2917SAlp Dener         /*  Full step taken; increase the radius */
854080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
855080d2917SAlp Dener       } else {
856080d2917SAlp Dener         /*  More than full step taken; increase the radius */
857080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
858080d2917SAlp Dener       }
859080d2917SAlp Dener     } else {
860080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
861080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
862080d2917SAlp Dener     }
863080d2917SAlp Dener     break;
864080d2917SAlp Dener 
865080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
866080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
867e0ed867bSAlp Dener       if ((prered < 0.0) || PetscIsInfOrNanReal(prered)) {
868fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
869fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
870fed79b8eSAlp Dener            be rejected! */
871080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
8723105154fSTodd Munson       } else {
873b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
874080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
875080d2917SAlp Dener         } else {
8763105154fSTodd Munson           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) && (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
877080d2917SAlp Dener             kappa = 1.0;
8783105154fSTodd Munson           } else {
879080d2917SAlp Dener             kappa = actred / prered;
880080d2917SAlp Dener           }
881fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
882080d2917SAlp Dener           if (kappa < bnk->eta1) {
883fed79b8eSAlp Dener             /* Reject the step */
884080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
8853105154fSTodd Munson           } else {
886fed79b8eSAlp Dener             /* Accept the step */
887c133c014SAlp Dener             *accept = PETSC_TRUE;
888c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
8898d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
890080d2917SAlp Dener               if (kappa < bnk->eta2) {
891080d2917SAlp Dener                 /* Marginal bad step */
892c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
8933105154fSTodd Munson               } else if (kappa < bnk->eta3) {
894fed79b8eSAlp Dener                 /* Reasonable step */
895fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
8963105154fSTodd Munson               } else if (kappa < bnk->eta4) {
897080d2917SAlp Dener                 /* Good step */
898c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
8993105154fSTodd Munson               } else {
900080d2917SAlp Dener                 /* Very good step */
901c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
902080d2917SAlp Dener               }
903c133c014SAlp Dener             }
904080d2917SAlp Dener           }
905080d2917SAlp Dener         }
906080d2917SAlp Dener       }
907080d2917SAlp Dener     } else {
908080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
909080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
910080d2917SAlp Dener     }
911080d2917SAlp Dener     break;
912080d2917SAlp Dener 
913080d2917SAlp Dener   default:
914080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
915b1c2d0e3SAlp Dener       if (prered < 0.0) {
916080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
917080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
918080d2917SAlp Dener         /*  be rejected! */
919080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
920080d2917SAlp Dener       } else {
921b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
922080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
923080d2917SAlp Dener         } else {
924080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
925080d2917SAlp Dener             kappa = 1.0;
926080d2917SAlp Dener           } else {
927080d2917SAlp Dener             kappa = actred / prered;
928080d2917SAlp Dener           }
929080d2917SAlp Dener 
930080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
931080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
932080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
933080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
934080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
935080d2917SAlp Dener 
936080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
937080d2917SAlp Dener             /*  Great agreement */
938080d2917SAlp Dener             *accept = PETSC_TRUE;
939080d2917SAlp Dener             if (tau_max < 1.0) {
940080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
941080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
942080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
943080d2917SAlp Dener             } else {
944080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
945080d2917SAlp Dener             }
946080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
947080d2917SAlp Dener             /*  Good agreement */
948080d2917SAlp Dener             *accept = PETSC_TRUE;
949080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
950080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
951080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
952080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
953080d2917SAlp Dener             } else if (tau_max < 1.0) {
954080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
955080d2917SAlp Dener             } else {
956080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
957080d2917SAlp Dener             }
958080d2917SAlp Dener           } else {
959080d2917SAlp Dener             /*  Not good agreement */
960080d2917SAlp Dener             if (tau_min > 1.0) {
961080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
962080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
963080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
964080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
965080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
966080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
967080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
968080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
969080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
970080d2917SAlp Dener             } else {
971080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
972080d2917SAlp Dener             }
973080d2917SAlp Dener           }
974080d2917SAlp Dener         }
975080d2917SAlp Dener       }
976080d2917SAlp Dener     } else {
977080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
978080d2917SAlp Dener       tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust);
979080d2917SAlp Dener     }
98028017e9fSAlp Dener     break;
981080d2917SAlp Dener   }
982c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
983c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
984fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
985080d2917SAlp Dener   PetscFunctionReturn(0);
986080d2917SAlp Dener }
987080d2917SAlp Dener 
988eb910715SAlp Dener /* ---------------------------------------------------------- */
989df278d8fSAlp Dener 
99062675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
99162675beeSAlp Dener {
99262675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
99362675beeSAlp Dener 
99462675beeSAlp Dener   PetscFunctionBegin;
99562675beeSAlp Dener   switch (stepType) {
99662675beeSAlp Dener   case BNK_NEWTON:
99762675beeSAlp Dener     ++bnk->newt;
99862675beeSAlp Dener     break;
99962675beeSAlp Dener   case BNK_BFGS:
100062675beeSAlp Dener     ++bnk->bfgs;
100162675beeSAlp Dener     break;
100262675beeSAlp Dener   case BNK_SCALED_GRADIENT:
100362675beeSAlp Dener     ++bnk->sgrad;
100462675beeSAlp Dener     break;
100562675beeSAlp Dener   case BNK_GRADIENT:
100662675beeSAlp Dener     ++bnk->grad;
100762675beeSAlp Dener     break;
100862675beeSAlp Dener   default:
100962675beeSAlp Dener     break;
101062675beeSAlp Dener   }
101162675beeSAlp Dener   PetscFunctionReturn(0);
101262675beeSAlp Dener }
101362675beeSAlp Dener 
101462675beeSAlp Dener /* ---------------------------------------------------------- */
101562675beeSAlp Dener 
10169b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
1017eb910715SAlp Dener {
1018eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1019eb910715SAlp Dener   PetscErrorCode ierr;
1020e031d6f5SAlp Dener   PetscInt       i;
1021eb910715SAlp Dener 
1022eb910715SAlp Dener   PetscFunctionBegin;
1023c4b75bccSAlp Dener   if (!tao->gradient) {
1024c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);
1025c4b75bccSAlp Dener   }
1026c4b75bccSAlp Dener   if (!tao->stepdirection) {
1027c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);
1028c4b75bccSAlp Dener   }
1029c4b75bccSAlp Dener   if (!bnk->W) {
1030c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);
1031c4b75bccSAlp Dener   }
1032c4b75bccSAlp Dener   if (!bnk->Xold) {
1033c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);
1034c4b75bccSAlp Dener   }
1035c4b75bccSAlp Dener   if (!bnk->Gold) {
1036c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);
1037c4b75bccSAlp Dener   }
1038c4b75bccSAlp Dener   if (!bnk->Xwork) {
1039c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);
1040c4b75bccSAlp Dener   }
1041c4b75bccSAlp Dener   if (!bnk->Gwork) {
1042c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);
1043c4b75bccSAlp Dener   }
1044c4b75bccSAlp Dener   if (!bnk->unprojected_gradient) {
1045c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);
1046c4b75bccSAlp Dener   }
1047c4b75bccSAlp Dener   if (!bnk->unprojected_gradient_old) {
1048c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);
1049c4b75bccSAlp Dener   }
1050c4b75bccSAlp Dener   if (!bnk->Diag_min) {
1051c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);
1052c4b75bccSAlp Dener   }
1053c4b75bccSAlp Dener   if (!bnk->Diag_max) {
1054c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);
1055c4b75bccSAlp Dener   }
1056e031d6f5SAlp Dener   if (bnk->max_cg_its > 0) {
1057c4b75bccSAlp Dener     /* Ensure that the important common vectors are shared between BNK and embedded BNCG */
1058c4b75bccSAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
105989da521bSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient_old));CHKERRQ(ierr);
106089da521bSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient_old);CHKERRQ(ierr);
106189da521bSAlp Dener     bnk->bncg_ctx->unprojected_gradient_old = bnk->unprojected_gradient_old;
1062c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient));CHKERRQ(ierr);
1063c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
1064c4b75bccSAlp Dener     bnk->bncg_ctx->unprojected_gradient = bnk->unprojected_gradient;
1065c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->Gold));CHKERRQ(ierr);
1066c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->G_old);CHKERRQ(ierr);
1067c4b75bccSAlp Dener     bnk->bncg_ctx->G_old = bnk->Gold;
1068c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->gradient));CHKERRQ(ierr);
1069c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->gradient);CHKERRQ(ierr);
1070c4b75bccSAlp Dener     bnk->bncg->gradient = tao->gradient;
1071c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->stepdirection));CHKERRQ(ierr);
1072c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->stepdirection);CHKERRQ(ierr);
1073c4b75bccSAlp Dener     bnk->bncg->stepdirection = tao->stepdirection;
1074c4b75bccSAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, tao->solution);CHKERRQ(ierr);
1075c4b75bccSAlp Dener     /* Copy over some settings from BNK into BNCG */
1076e031d6f5SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
1077e031d6f5SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
1078e031d6f5SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
1079937a31a1SAlp Dener     ierr = TaoSetConvergenceTest(bnk->bncg, tao->ops->convergencetest, tao->cnvP);CHKERRQ(ierr);
1080e031d6f5SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
1081e031d6f5SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
1082e031d6f5SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
1083e031d6f5SAlp Dener     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr);
1084c4b75bccSAlp Dener     for (i=0; i<tao->numbermonitors; ++i) {
1085e031d6f5SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
1086e031d6f5SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
1087e031d6f5SAlp Dener     }
1088e031d6f5SAlp Dener   }
1089c0f10754SAlp Dener   bnk->X_inactive = 0;
1090c0f10754SAlp Dener   bnk->G_inactive = 0;
109162675beeSAlp Dener   bnk->inactive_work = 0;
109262675beeSAlp Dener   bnk->active_work = 0;
109362675beeSAlp Dener   bnk->inactive_idx = 0;
109462675beeSAlp Dener   bnk->active_idx = 0;
109562675beeSAlp Dener   bnk->active_lower = 0;
109662675beeSAlp Dener   bnk->active_upper = 0;
109762675beeSAlp Dener   bnk->active_fixed = 0;
1098eb910715SAlp Dener   bnk->M = 0;
109909164190SAlp Dener   bnk->H_inactive = 0;
110009164190SAlp Dener   bnk->Hpre_inactive = 0;
1101eb910715SAlp Dener   PetscFunctionReturn(0);
1102eb910715SAlp Dener }
1103eb910715SAlp Dener 
1104eb910715SAlp Dener /*------------------------------------------------------------*/
1105df278d8fSAlp Dener 
1106e0ed867bSAlp Dener PetscErrorCode TaoDestroy_BNK(Tao tao)
1107eb910715SAlp Dener {
1108eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1109eb910715SAlp Dener   PetscErrorCode ierr;
1110eb910715SAlp Dener 
1111eb910715SAlp Dener   PetscFunctionBegin;
1112eb910715SAlp Dener   if (tao->setupcalled) {
1113eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1114eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1115eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
111609164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
111709164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
111809164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
111909164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
112062675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
112162675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1122c4b75bccSAlp Dener   }
1123ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_lower);CHKERRQ(ierr);
1124ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_upper);CHKERRQ(ierr);
1125ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_fixed);CHKERRQ(ierr);
1126ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
1127ca964c49SAlp Dener   ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
1128c4b75bccSAlp Dener   ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
1129c4b75bccSAlp Dener   ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
1130ca964c49SAlp Dener   ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1131eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1132eb910715SAlp Dener   PetscFunctionReturn(0);
1133eb910715SAlp Dener }
1134eb910715SAlp Dener 
1135eb910715SAlp Dener /*------------------------------------------------------------*/
1136df278d8fSAlp Dener 
1137e0ed867bSAlp Dener PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1138eb910715SAlp Dener {
1139eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1140eb910715SAlp Dener   PetscErrorCode ierr;
1141e0ed867bSAlp Dener   KSPType        ksp_type;
1142eb910715SAlp Dener 
1143eb910715SAlp Dener   PetscFunctionBegin;
11444f4fdda4SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton-Krylov method for bound constrained optimization");CHKERRQ(ierr);
11458d5ead36SAlp 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);
11468d5ead36SAlp 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);
11472f75a4aaSAlp 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);
1148748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "(developer) Hessian perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
1149748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "(developer) minimum initial Hessian perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
1150748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "(developer) maximum initial Hessian perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
1151748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "(developer) initial merit factor for Hessian perturbation", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
1152748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "(developer) minimum Hessian perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
1153748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "(developer) maximum Hessian perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
1154748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "(developer) Hessian perturbation growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
1155748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "(developer) Hessian perturbation shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
1156748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "(developer) merit growth factor for Hessian perturbation", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
1157748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "(developer) merit shrink factor for Hessian perturbation", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
1158748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "(developer) threshold for rejecting step (-tao_bnk_update_type reduction)", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
1159748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "(developer) threshold for accepting marginal step (-tao_bnk_update_type reduction)", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
1160748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "(developer) threshold for accepting reasonable step (-tao_bnk_update_type reduction)", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
1161748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "(developer) threshold for accepting good step (-tao_bnk_update_type reduction)", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
1162748696b1SAlp 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);
1163748696b1SAlp 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);
1164748696b1SAlp 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);
1165748696b1SAlp 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);
1166748696b1SAlp 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);
1167748696b1SAlp 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);
1168748696b1SAlp 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);
1169748696b1SAlp 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);
1170748696b1SAlp 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);
1171748696b1SAlp 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);
1172748696b1SAlp 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);
1173748696b1SAlp 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);
1174748696b1SAlp 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);
1175748696b1SAlp 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);
1176748696b1SAlp 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);
1177748696b1SAlp 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);
1178748696b1SAlp 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);
1179748696b1SAlp 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);
1180748696b1SAlp 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);
1181748696b1SAlp 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);
1182748696b1SAlp 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);
1183748696b1SAlp 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);
1184748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "(developer) threshold for accepting good step (-tao_bnk_update_type interpolation)", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
1185748696b1SAlp 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);
1186748696b1SAlp 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);
1187748696b1SAlp 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);
1188748696b1SAlp 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);
1189748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "(developer) trust region interpolation factor (-tao_bnk_update_type interpolation)", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
1190748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "(developer) lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
1191748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "(developer) upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
1192748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "(developer) tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
1193748696b1SAlp 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);
1194748696b1SAlp 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);
1195c0f10754SAlp 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);
1196eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
119733c78596SAlp Dener   ierr = TaoSetFromOptions(bnk->bncg);CHKERRQ(ierr);
1198eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1199eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1200e0ed867bSAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
1201e0ed867bSAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
1202e0ed867bSAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
1203e0ed867bSAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1204eb910715SAlp Dener   PetscFunctionReturn(0);
1205eb910715SAlp Dener }
1206eb910715SAlp Dener 
1207eb910715SAlp Dener /*------------------------------------------------------------*/
1208df278d8fSAlp Dener 
1209e0ed867bSAlp Dener PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1210eb910715SAlp Dener {
1211eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1212eb910715SAlp Dener   PetscInt       nrejects;
1213eb910715SAlp Dener   PetscBool      isascii;
1214eb910715SAlp Dener   PetscErrorCode ierr;
1215eb910715SAlp Dener 
1216eb910715SAlp Dener   PetscFunctionBegin;
1217eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1218eb910715SAlp Dener   if (isascii) {
1219eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1220b9ac7092SAlp Dener     if (bnk->M) {
1221cd929ea3SAlp Dener       ierr = MatLMVMGetRejectCount(bnk->M,&nrejects);CHKERRQ(ierr);
1222b9ac7092SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected BFGS updates: %D\n",nrejects);CHKERRQ(ierr);
1223eb910715SAlp Dener     }
1224e031d6f5SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr);
1225eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1226b9ac7092SAlp Dener     if (bnk->M) {
1227eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1228b9ac7092SAlp Dener     }
1229eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1230eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1231eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1232eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1233eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1234eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1235eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1236eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1237eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1238eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1239eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1240eb910715SAlp Dener   }
1241eb910715SAlp Dener   PetscFunctionReturn(0);
1242eb910715SAlp Dener }
1243eb910715SAlp Dener 
1244eb910715SAlp Dener /* ---------------------------------------------------------- */
1245df278d8fSAlp Dener 
1246eb910715SAlp Dener /*MC
1247eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
124866ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1249eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1250eb910715SAlp Dener               Hk dk = -gk
12512b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12522b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1253eb910715SAlp Dener 
1254eb910715SAlp Dener     Options Database Keys:
1255e0ed867bSAlp Dener + -max_cg_its - maximum number of bounded conjugate-gradient iterations taken in each Newton loop
1256e0ed867bSAlp Dener . -init_type - trust radius initialization method ("constant", "direction", "interpolation")
1257e0ed867bSAlp Dener . -update_type - trust radius update method ("step", "direction", "interpolation")
1258e0ed867bSAlp Dener . -as_type - active-set estimation method ("none", "bertsekas")
1259e0ed867bSAlp Dener . -as_tol - (developer) initial tolerance used in estimating bounded active variables (-as_type bertsekas)
1260e0ed867bSAlp Dener . -as_step - (developer) trial step length used in estimating bounded active variables (-as_type bertsekas)
1261e0ed867bSAlp Dener . -sval - (developer) Hessian perturbation starting value
1262e0ed867bSAlp Dener . -imin - (developer) minimum initial Hessian perturbation
1263e0ed867bSAlp Dener . -imax - (developer) maximum initial Hessian perturbation
1264e0ed867bSAlp Dener . -pmin - (developer) minimum Hessian perturbation
1265e0ed867bSAlp Dener . -pmax - (developer) aximum Hessian perturbation
1266e0ed867bSAlp Dener . -pgfac - (developer) Hessian perturbation growth factor
1267e0ed867bSAlp Dener . -psfac - (developer) Hessian perturbation shrink factor
1268e0ed867bSAlp Dener . -imfac - (developer) initial merit factor for Hessian perturbation
1269e0ed867bSAlp Dener . -pmgfac - (developer) merit growth factor for Hessian perturbation
1270e0ed867bSAlp Dener . -pmsfac - (developer) merit shrink factor for Hessian perturbation
1271e0ed867bSAlp Dener . -eta1 - (developer) threshold for rejecting step (-update_type reduction)
1272e0ed867bSAlp Dener . -eta2 - (developer) threshold for accepting marginal step (-update_type reduction)
1273e0ed867bSAlp Dener . -eta3 - (developer) threshold for accepting reasonable step (-update_type reduction)
1274e0ed867bSAlp Dener . -eta4 - (developer) threshold for accepting good step (-update_type reduction)
1275e0ed867bSAlp Dener . -alpha1 - (developer) radius reduction factor for rejected step (-update_type reduction)
1276e0ed867bSAlp Dener . -alpha2 - (developer) radius reduction factor for marginally accepted bad step (-update_type reduction)
1277e0ed867bSAlp Dener . -alpha3 - (developer) radius increase factor for reasonable accepted step (-update_type reduction)
1278e0ed867bSAlp Dener . -alpha4 - (developer) radius increase factor for good accepted step (-update_type reduction)
1279e0ed867bSAlp Dener . -alpha5 - (developer) radius increase factor for very good accepted step (-update_type reduction)
1280e0ed867bSAlp Dener . -epsilon - (developer) tolerance for small pred/actual ratios that trigger automatic step acceptance (-update_type reduction)
1281e0ed867bSAlp Dener . -mu1 - (developer) threshold for accepting very good step (-update_type interpolation)
1282e0ed867bSAlp Dener . -mu2 - (developer) threshold for accepting good step (-update_type interpolation)
1283e0ed867bSAlp Dener . -gamma1 - (developer) radius reduction factor for rejected very bad step (-update_type interpolation)
1284e0ed867bSAlp Dener . -gamma2 - (developer) radius reduction factor for rejected bad step (-update_type interpolation)
1285e0ed867bSAlp Dener . -gamma3 - (developer) radius increase factor for accepted good step (-update_type interpolation)
1286e0ed867bSAlp Dener . -gamma4 - (developer) radius increase factor for accepted very good step (-update_type interpolation)
1287e0ed867bSAlp Dener . -theta - (developer) trust region interpolation factor (-update_type interpolation)
1288e0ed867bSAlp Dener . -nu1 - (developer) threshold for small line-search step length (-update_type step)
1289e0ed867bSAlp Dener . -nu2 - (developer) threshold for reasonable line-search step length (-update_type step)
1290e0ed867bSAlp Dener . -nu3 - (developer) threshold for large line-search step length (-update_type step)
1291e0ed867bSAlp Dener . -nu4 - (developer) threshold for very large line-search step length (-update_type step)
1292e0ed867bSAlp Dener . -omega1 - (developer) radius reduction factor for very small line-search step length (-update_type step)
1293e0ed867bSAlp Dener . -omega2 - (developer) radius reduction factor for small line-search step length (-update_type step)
1294e0ed867bSAlp Dener . -omega3 - (developer) radius factor for decent line-search step length (-update_type step)
1295e0ed867bSAlp Dener . -omega4 - (developer) radius increase factor for large line-search step length (-update_type step)
1296e0ed867bSAlp Dener . -omega5 - (developer) radius increase factor for very large line-search step length (-update_type step)
1297e0ed867bSAlp Dener . -mu1_i -  (developer) threshold for accepting very good step (-init_type interpolation)
1298e0ed867bSAlp Dener . -mu2_i -  (developer) threshold for accepting good step (-init_type interpolation)
1299e0ed867bSAlp Dener . -gamma1_i - (developer) radius reduction factor for rejected very bad step (-init_type interpolation)
1300e0ed867bSAlp Dener . -gamma2_i - (developer) radius reduction factor for rejected bad step (-init_type interpolation)
1301e0ed867bSAlp Dener . -gamma3_i - (developer) radius increase factor for accepted good step (-init_type interpolation)
1302e0ed867bSAlp Dener . -gamma4_i - (developer) radius increase factor for accepted very good step (-init_type interpolation)
1303e0ed867bSAlp Dener - -theta_i - (developer) trust region interpolation factor (-init_type interpolation)
1304eb910715SAlp Dener 
1305eb910715SAlp Dener   Level: beginner
1306eb910715SAlp Dener M*/
1307eb910715SAlp Dener 
1308eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1309eb910715SAlp Dener {
1310eb910715SAlp Dener   TAO_BNK        *bnk;
1311eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1312eb910715SAlp Dener   PetscErrorCode ierr;
1313b9ac7092SAlp Dener   PC             pc;
1314eb910715SAlp Dener 
1315eb910715SAlp Dener   PetscFunctionBegin;
1316eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1317eb910715SAlp Dener 
1318eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1319eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1320eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1321eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1322eb910715SAlp Dener 
1323eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1324eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1325eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1326eb910715SAlp Dener 
1327eb910715SAlp Dener   tao->data = (void*)bnk;
1328eb910715SAlp Dener 
132966ed3702SAlp Dener   /*  Hessian shifting parameters */
1330e0ed867bSAlp Dener   bnk->computehessian = TaoBNKComputeHessian;
1331e0ed867bSAlp Dener   bnk->computestep = TaoBNKComputeStep;
1332e0ed867bSAlp Dener 
1333eb910715SAlp Dener   bnk->sval   = 0.0;
1334eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1335eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1336eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1337eb910715SAlp Dener 
1338eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1339eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1340eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1341eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1342eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1343eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1344eb910715SAlp Dener 
1345eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1346eb910715SAlp Dener   bnk->nu1 = 0.25;
1347eb910715SAlp Dener   bnk->nu2 = 0.50;
1348eb910715SAlp Dener   bnk->nu3 = 1.00;
1349eb910715SAlp Dener   bnk->nu4 = 1.25;
1350eb910715SAlp Dener 
1351eb910715SAlp Dener   bnk->omega1 = 0.25;
1352eb910715SAlp Dener   bnk->omega2 = 0.50;
1353eb910715SAlp Dener   bnk->omega3 = 1.00;
1354eb910715SAlp Dener   bnk->omega4 = 2.00;
1355eb910715SAlp Dener   bnk->omega5 = 4.00;
1356eb910715SAlp Dener 
1357eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1358eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1359eb910715SAlp Dener   bnk->eta2 = 0.25;
1360eb910715SAlp Dener   bnk->eta3 = 0.50;
1361eb910715SAlp Dener   bnk->eta4 = 0.90;
1362eb910715SAlp Dener 
1363eb910715SAlp Dener   bnk->alpha1 = 0.25;
1364eb910715SAlp Dener   bnk->alpha2 = 0.50;
1365eb910715SAlp Dener   bnk->alpha3 = 1.00;
1366eb910715SAlp Dener   bnk->alpha4 = 2.00;
1367eb910715SAlp Dener   bnk->alpha5 = 4.00;
1368eb910715SAlp Dener 
1369eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1370eb910715SAlp Dener   bnk->mu1 = 0.10;
1371eb910715SAlp Dener   bnk->mu2 = 0.50;
1372eb910715SAlp Dener 
1373eb910715SAlp Dener   bnk->gamma1 = 0.25;
1374eb910715SAlp Dener   bnk->gamma2 = 0.50;
1375eb910715SAlp Dener   bnk->gamma3 = 2.00;
1376eb910715SAlp Dener   bnk->gamma4 = 4.00;
1377eb910715SAlp Dener 
1378eb910715SAlp Dener   bnk->theta = 0.05;
1379eb910715SAlp Dener 
1380eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1381eb910715SAlp Dener   bnk->mu1_i = 0.35;
1382eb910715SAlp Dener   bnk->mu2_i = 0.50;
1383eb910715SAlp Dener 
1384eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1385eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1386eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1387eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1388eb910715SAlp Dener 
1389eb910715SAlp Dener   bnk->theta_i = 0.25;
1390eb910715SAlp Dener 
1391eb910715SAlp Dener   /*  Remaining parameters */
1392c0f10754SAlp Dener   bnk->max_cg_its = 0;
1393eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1394eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1395770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
13960a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
13970a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
139862675beeSAlp Dener   bnk->dmin = 1.0e-6;
139962675beeSAlp Dener   bnk->dmax = 1.0e6;
1400eb910715SAlp Dener 
1401b9ac7092SAlp Dener   bnk->M               = 0;
1402b9ac7092SAlp Dener   bnk->bfgs_pre        = 0;
1403eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
14047b1c7716SAlp Dener   bnk->update_type     = BNK_UPDATE_REDUCTION;
14052f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1406eb910715SAlp Dener 
1407e031d6f5SAlp Dener   /* Create the embedded BNCG solver */
1408e031d6f5SAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
1409e031d6f5SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
1410e031d6f5SAlp Dener   ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr);
1411e031d6f5SAlp Dener   ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
1412e031d6f5SAlp Dener 
1413c0f10754SAlp Dener   /* Create the line search */
1414eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1415eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1416e031d6f5SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1417eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1418eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1419eb910715SAlp Dener 
1420eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1421eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1422eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1423e0ed867bSAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,"tao_bnk_");CHKERRQ(ierr);
1424eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1425b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);
1426b9ac7092SAlp Dener   ierr = PCSetType(pc, PCLMVM);CHKERRQ(ierr);
1427eb910715SAlp Dener   PetscFunctionReturn(0);
1428eb910715SAlp Dener }
1429