xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision 7b1c77167952b0557943a232cdd64e09e7c985ed)
1eb910715SAlp Dener #include <petsctaolinesearch.h>
2eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h>
3eb910715SAlp Dener 
4eb910715SAlp Dener #include <petscksp.h>
5eb910715SAlp Dener 
6e031d6f5SAlp Dener static const char *BNK_INIT[64] = {"constant", "direction", "interpolation"};
7e031d6f5SAlp Dener static const char *BNK_UPDATE[64] = {"step", "reduction", "interpolation"};
8e031d6f5SAlp Dener static const char *BNK_AS[64] = {"none", "bertsekas"};
9e031d6f5SAlp Dener 
10e031d6f5SAlp Dener /*------------------------------------------------------------*/
11e031d6f5SAlp Dener 
12df278d8fSAlp Dener /* Routine for initializing the KSP solver, the BFGS preconditioner, and the initial trust radius estimation */
13df278d8fSAlp Dener 
14c0f10754SAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType, PetscBool *needH)
15eb910715SAlp Dener {
16eb910715SAlp Dener   PetscErrorCode               ierr;
17eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
18eb910715SAlp Dener   PC                           pc;
19eb910715SAlp Dener 
2089da521bSAlp Dener   PetscReal                    f_min, ftrial, prered, actred, kappa, sigma, resnorm;
21eb910715SAlp Dener   PetscReal                    tau, tau_1, tau_2, tau_max, tau_min, max_radius;
220ad3a497SAlp Dener   PetscBool                    is_bfgs, is_jacobi, is_symmetric, sym_set;
23c4b75bccSAlp Dener   PetscInt                     n, N, nDiff;
24eb910715SAlp Dener   PetscInt                     i_max = 5;
25eb910715SAlp Dener   PetscInt                     j_max = 1;
26eb910715SAlp Dener   PetscInt                     i, j;
27eb910715SAlp Dener 
28eb910715SAlp Dener   PetscFunctionBegin;
2928017e9fSAlp Dener   /* Project the current point onto the feasible set */
3028017e9fSAlp Dener   ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr);
31e031d6f5SAlp Dener   ierr = TaoSetVariableBounds(bnk->bncg, tao->XL, tao->XU);CHKERRQ(ierr);
32b9ac7092SAlp Dener   if (tao->bounded) {
3328017e9fSAlp Dener     ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr);
34cd929ea3SAlp Dener   }
3528017e9fSAlp Dener 
3628017e9fSAlp Dener   /* Project the initial point onto the feasible region */
373b063059SAlp Dener   ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
3828017e9fSAlp Dener 
3928017e9fSAlp Dener   /* Check convergence criteria */
4028017e9fSAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr);
4161be54a6SAlp Dener   ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
4261be54a6SAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
4361be54a6SAlp Dener   ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
4408752603SAlp Dener   ierr = VecNorm(tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
4528017e9fSAlp Dener 
46c0f10754SAlp Dener   /* Test the initial point for convergence */
4789da521bSAlp Dener   ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
4889da521bSAlp Dener   ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
49b4a30f08SAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
50e031d6f5SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
51e031d6f5SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
52c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
53c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
54c0f10754SAlp Dener 
55e031d6f5SAlp Dener   /* Reset KSP stopping reason counters */
56eb910715SAlp Dener   bnk->ksp_atol = 0;
57eb910715SAlp Dener   bnk->ksp_rtol = 0;
58eb910715SAlp Dener   bnk->ksp_dtol = 0;
59eb910715SAlp Dener   bnk->ksp_ctol = 0;
60eb910715SAlp Dener   bnk->ksp_negc = 0;
61eb910715SAlp Dener   bnk->ksp_iter = 0;
62eb910715SAlp Dener   bnk->ksp_othr = 0;
63eb910715SAlp Dener 
64e031d6f5SAlp Dener   /* Reset accepted step type counters */
65e031d6f5SAlp Dener   bnk->tot_cg_its = 0;
66e031d6f5SAlp Dener   bnk->newt = 0;
67e031d6f5SAlp Dener   bnk->bfgs = 0;
68e031d6f5SAlp Dener   bnk->sgrad = 0;
69e031d6f5SAlp Dener   bnk->grad = 0;
70e031d6f5SAlp Dener 
71fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
72fed79b8eSAlp Dener   bnk->pert = bnk->sval;
73fed79b8eSAlp Dener 
74937a31a1SAlp Dener   /* Reset initial steplength to zero (this helps BNCG reset its direction internally) */
75937a31a1SAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
76937a31a1SAlp Dener 
77e031d6f5SAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
78b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
79b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &is_bfgs);CHKERRQ(ierr);
80b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCJACOBI, &is_jacobi);CHKERRQ(ierr);
81b9ac7092SAlp Dener   if (is_bfgs) {
82b9ac7092SAlp Dener     bnk->bfgs_pre = pc;
83b9ac7092SAlp Dener     ierr = PCLMVMGetMatLMVM(bnk->bfgs_pre, &bnk->M);CHKERRQ(ierr);
84eb910715SAlp Dener     ierr = VecGetLocalSize(tao->solution, &n);CHKERRQ(ierr);
85eb910715SAlp Dener     ierr = VecGetSize(tao->solution, &N);CHKERRQ(ierr);
86b9ac7092SAlp Dener     ierr = MatSetSizes(bnk->M, n, n, N, N);CHKERRQ(ierr);
87cd929ea3SAlp Dener     ierr = MatLMVMAllocate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
880ad3a497SAlp Dener     ierr = MatIsSymmetricKnown(bnk->M, &sym_set, &is_symmetric);CHKERRQ(ierr);
890ad3a497SAlp Dener     if (!sym_set || !is_symmetric) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix in the LMVM preconditioner must be symmetric.");
90b9ac7092SAlp Dener   } else if (is_jacobi) {
91b9ac7092SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
92e031d6f5SAlp Dener   }
93e031d6f5SAlp Dener 
94e031d6f5SAlp Dener   /* Prepare the min/max vectors for safeguarding diagonal scales */
9562675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
9662675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
97eb910715SAlp Dener 
98eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
99eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
100c0f10754SAlp Dener   *needH = PETSC_TRUE;
101eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
10262675beeSAlp Dener     switch(initType) {
103eb910715SAlp Dener     case BNK_INIT_CONSTANT:
104eb910715SAlp Dener       /* Use the initial radius specified */
105c0f10754SAlp Dener       tao->trust = tao->trust0;
106eb910715SAlp Dener       break;
107eb910715SAlp Dener 
108eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
109c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
110eb910715SAlp Dener       max_radius = 0.0;
11108752603SAlp Dener       tao->trust = tao->trust0;
112eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1130a4511e9SAlp Dener         f_min = bnk->f;
114eb910715SAlp Dener         sigma = 0.0;
115eb910715SAlp Dener 
116c0f10754SAlp Dener         if (*needH) {
11762602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
118e031d6f5SAlp Dener           ierr = TaoBNKComputeHessian(tao);CHKERRQ(ierr);
11908752603SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, BNK_AS_NONE);CHKERRQ(ierr);
12089da521bSAlp Dener           ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
12189da521bSAlp Dener           if (bnk->active_idx) {
1222ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
12328017e9fSAlp Dener           } else {
12408752603SAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
12528017e9fSAlp Dener           }
126c0f10754SAlp Dener           *needH = PETSC_FALSE;
127eb910715SAlp Dener         }
128eb910715SAlp Dener 
129eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
13062602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
13162602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
13262602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
1333b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
13489da521bSAlp Dener           /* Compute the step we actually accepted */
135eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
13662602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
13762602cfbSAlp Dener           /* Compute the objective at the trial */
13862602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
139b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(bnk->f)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
14062602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
141eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
142eb910715SAlp Dener             tau = bnk->gamma1_i;
143eb910715SAlp Dener           } else {
1440a4511e9SAlp Dener             if (ftrial < f_min) {
1450a4511e9SAlp Dener               f_min = ftrial;
146eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
147eb910715SAlp Dener             }
14808752603SAlp Dener 
149770b7498SAlp Dener             /* Compute the predicted and actual reduction */
15089da521bSAlp Dener             if (bnk->active_idx) {
15108752603SAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
15208752603SAlp Dener               ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1532ab2a32cSAlp Dener             } else {
15408752603SAlp Dener               bnk->X_inactive = bnk->W;
15508752603SAlp Dener               bnk->inactive_work = bnk->Xwork;
1562ab2a32cSAlp Dener             }
15708752603SAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
15808752603SAlp Dener             ierr = VecDot(bnk->X_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
15989da521bSAlp Dener             if (bnk->active_idx) {
16008752603SAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
16108752603SAlp Dener               ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1622ab2a32cSAlp Dener             }
163eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
164eb910715SAlp Dener             actred = bnk->f - ftrial;
1653105154fSTodd Munson             if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
166eb910715SAlp Dener               kappa = 1.0;
1673105154fSTodd Munson             } else {
168eb910715SAlp Dener               kappa = actred / prered;
169eb910715SAlp Dener             }
170eb910715SAlp Dener 
171eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
172eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
173eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
174eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
175eb910715SAlp Dener 
176eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
177eb910715SAlp Dener               /*  Great agreement */
178eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
179eb910715SAlp Dener 
180eb910715SAlp Dener               if (tau_max < 1.0) {
181eb910715SAlp Dener                 tau = bnk->gamma3_i;
1823105154fSTodd Munson               } else if (tau_max > bnk->gamma4_i) {
183eb910715SAlp Dener                 tau = bnk->gamma4_i;
1843105154fSTodd Munson               } else {
185eb910715SAlp Dener                 tau = tau_max;
186eb910715SAlp Dener               }
1878f8a4e06SAlp Dener             } else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
188eb910715SAlp Dener               /*  Good agreement */
189eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
190eb910715SAlp Dener 
191eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
192eb910715SAlp Dener                 tau = bnk->gamma2_i;
193eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
194eb910715SAlp Dener                 tau = bnk->gamma3_i;
195eb910715SAlp Dener               } else {
196eb910715SAlp Dener                 tau = tau_max;
197eb910715SAlp Dener               }
1988f8a4e06SAlp Dener             } else {
199eb910715SAlp Dener               /*  Not good agreement */
200eb910715SAlp Dener               if (tau_min > 1.0) {
201eb910715SAlp Dener                 tau = bnk->gamma2_i;
202eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
203eb910715SAlp Dener                 tau = bnk->gamma1_i;
204eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
205eb910715SAlp Dener                 tau = bnk->gamma1_i;
2063105154fSTodd Munson               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
207eb910715SAlp Dener                 tau = tau_1;
2083105154fSTodd Munson               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
209eb910715SAlp Dener                 tau = tau_2;
210eb910715SAlp Dener               } else {
211eb910715SAlp Dener                 tau = tau_max;
212eb910715SAlp Dener               }
213eb910715SAlp Dener             }
214eb910715SAlp Dener           }
215eb910715SAlp Dener           tao->trust = tau * tao->trust;
216eb910715SAlp Dener         }
217eb910715SAlp Dener 
2180a4511e9SAlp Dener         if (f_min < bnk->f) {
219937a31a1SAlp Dener           /* We accidentally found a solution better than the initial, so accept it */
2200a4511e9SAlp Dener           bnk->f = f_min;
221937a31a1SAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
222eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
2233b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
224937a31a1SAlp Dener           ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr);
225937a31a1SAlp Dener           ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr);
22609164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
22761be54a6SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
22861be54a6SAlp Dener           ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
22961be54a6SAlp Dener           ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
230937a31a1SAlp Dener           /* Compute gradient at the new iterate and flip switch to compute the Hessian later */
231c4b75bccSAlp Dener           ierr = VecNorm(tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr);
232c0f10754SAlp Dener           *needH = PETSC_TRUE;
233937a31a1SAlp Dener           /* Test the new step for convergence */
23489da521bSAlp Dener           ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
23589da521bSAlp Dener           ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
236b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
237e031d6f5SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
238e031d6f5SAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
239eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
240eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
241937a31a1SAlp Dener           /* active BNCG recycling early because we have a stepdirection computed */
242937a31a1SAlp Dener           ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
243eb910715SAlp Dener         }
244eb910715SAlp Dener       }
245eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
246e031d6f5SAlp Dener 
247e031d6f5SAlp Dener       /* Ensure that the trust radius is within the limits */
248e031d6f5SAlp Dener       tao->trust = PetscMax(tao->trust, bnk->min_radius);
249e031d6f5SAlp Dener       tao->trust = PetscMin(tao->trust, bnk->max_radius);
250eb910715SAlp Dener       break;
251eb910715SAlp Dener 
252eb910715SAlp Dener     default:
253eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
254eb910715SAlp Dener       tao->trust = 0.0;
255eb910715SAlp Dener       break;
256eb910715SAlp Dener     }
257eb910715SAlp Dener   }
258eb910715SAlp Dener   PetscFunctionReturn(0);
259eb910715SAlp Dener }
260eb910715SAlp Dener 
261df278d8fSAlp Dener /*------------------------------------------------------------*/
262df278d8fSAlp Dener 
26362675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */
26462675beeSAlp Dener 
26562675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
26662675beeSAlp Dener {
26762675beeSAlp Dener   PetscErrorCode               ierr;
26862675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
26962675beeSAlp Dener 
27062675beeSAlp Dener   PetscFunctionBegin;
27162675beeSAlp Dener   /* Compute the Hessian */
27262675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
27362675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
274b9ac7092SAlp Dener   if (bnk->M) {
27562675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
27662675beeSAlp Dener   }
27762675beeSAlp Dener   PetscFunctionReturn(0);
27862675beeSAlp Dener }
27962675beeSAlp Dener 
28062675beeSAlp Dener /*------------------------------------------------------------*/
28162675beeSAlp Dener 
2822f75a4aaSAlp Dener /* Routine for estimating the active set */
2832f75a4aaSAlp Dener 
28408752603SAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao, PetscInt asType)
2852f75a4aaSAlp Dener {
2862f75a4aaSAlp Dener   PetscErrorCode               ierr;
2872f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
288c4b75bccSAlp Dener   PetscBool                    hessComputed, diagExists;
2892f75a4aaSAlp Dener 
2902f75a4aaSAlp Dener   PetscFunctionBegin;
29108752603SAlp Dener   switch (asType) {
2922f75a4aaSAlp Dener   case BNK_AS_NONE:
2932f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
2942f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
2952f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
2962f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
2972f75a4aaSAlp Dener     break;
2982f75a4aaSAlp Dener 
2992f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3002f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
301b9ac7092SAlp Dener     if (bnk->M) {
3022f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
303cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3042f75a4aaSAlp Dener     } else {
30561be54a6SAlp Dener       ierr = MatAssembled(tao->hessian, &hessComputed);CHKERRQ(ierr);
306c4b75bccSAlp Dener       ierr = MatHasOperation(tao->hessian, MATOP_GET_DIAGONAL, &diagExists);CHKERRQ(ierr);
307c4b75bccSAlp Dener       if (hessComputed && diagExists) {
3089b6ef848SAlp Dener         /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3092f75a4aaSAlp Dener         ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3109b6ef848SAlp Dener         ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3119b6ef848SAlp Dener         ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3122f75a4aaSAlp Dener         ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3132f75a4aaSAlp Dener         ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
31461be54a6SAlp Dener       } else {
315c4b75bccSAlp Dener         /* If the Hessian or its diagonal does not exist, we will simply use gradient step */
31661be54a6SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
31761be54a6SAlp Dener       }
3182f75a4aaSAlp Dener     }
3192f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
32089da521bSAlp Dener     ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, bnk->unprojected_gradient, bnk->W, bnk->Xwork, bnk->as_step, &bnk->as_tol,
32189da521bSAlp Dener                                    &bnk->active_lower, &bnk->active_upper, &bnk->active_fixed, &bnk->active_idx, &bnk->inactive_idx);CHKERRQ(ierr);
322c4b75bccSAlp Dener     break;
3232f75a4aaSAlp Dener 
3242f75a4aaSAlp Dener   default:
3252f75a4aaSAlp Dener     break;
3262f75a4aaSAlp Dener   }
3272f75a4aaSAlp Dener   PetscFunctionReturn(0);
3282f75a4aaSAlp Dener }
3292f75a4aaSAlp Dener 
3302f75a4aaSAlp Dener /*------------------------------------------------------------*/
3312f75a4aaSAlp Dener 
3322f75a4aaSAlp Dener /* Routine for bounding the step direction */
3332f75a4aaSAlp Dener 
334a1318120SAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, PetscInt asType, Vec step)
3352f75a4aaSAlp Dener {
3362f75a4aaSAlp Dener   PetscErrorCode               ierr;
3372f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3382f75a4aaSAlp Dener 
3392f75a4aaSAlp Dener   PetscFunctionBegin;
340a1318120SAlp Dener   switch (asType) {
3412f75a4aaSAlp Dener   case BNK_AS_NONE:
342c4b75bccSAlp Dener     ierr = VecISSet(step, bnk->active_idx, 0.0);CHKERRQ(ierr);
3432f75a4aaSAlp Dener     break;
3442f75a4aaSAlp Dener 
3452f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
346c4b75bccSAlp Dener     ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, 1.0, step);CHKERRQ(ierr);
3472f75a4aaSAlp Dener     break;
3482f75a4aaSAlp Dener 
3492f75a4aaSAlp Dener   default:
3502f75a4aaSAlp Dener     break;
3512f75a4aaSAlp Dener   }
3522f75a4aaSAlp Dener   PetscFunctionReturn(0);
3532f75a4aaSAlp Dener }
3542f75a4aaSAlp Dener 
355e031d6f5SAlp Dener /*------------------------------------------------------------*/
356e031d6f5SAlp Dener 
357e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to
358e031d6f5SAlp Dener    accelerate Newton convergence.
359e031d6f5SAlp Dener 
360e031d6f5SAlp Dener    In practice, this approach simply trades off Hessian evaluations
361e031d6f5SAlp Dener    for more gradient evaluations.
362e031d6f5SAlp Dener */
363e031d6f5SAlp Dener 
364c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
365c0f10754SAlp Dener {
366c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
367c0f10754SAlp Dener   PetscErrorCode               ierr;
368c0f10754SAlp Dener 
369c0f10754SAlp Dener   PetscFunctionBegin;
370c0f10754SAlp Dener   *terminate = PETSC_FALSE;
371c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
372c4b75bccSAlp Dener     /* Copy the current function value (important vectors are already shared) */
373c0f10754SAlp Dener     bnk->bncg_ctx->f = bnk->f;
374c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
375c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
376c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
377c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
378c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
379c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
380c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
381e031d6f5SAlp Dener     bnk->tot_cg_its += bnk->bncg->niter;
382c4b75bccSAlp Dener     /* Extract the BNCG function value out and save it into BNK */
383c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
384c0f10754SAlp 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) {
385c0f10754SAlp Dener       *terminate = PETSC_TRUE;
38661be54a6SAlp Dener     } else {
38733c78596SAlp Dener       ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
388c0f10754SAlp Dener     }
389c0f10754SAlp Dener   }
390c0f10754SAlp Dener   PetscFunctionReturn(0);
391c0f10754SAlp Dener }
392c0f10754SAlp Dener 
3932f75a4aaSAlp Dener /*------------------------------------------------------------*/
3942f75a4aaSAlp Dener 
395c0f10754SAlp Dener /* Routine for computing the Newton step. */
396df278d8fSAlp Dener 
39762675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason)
398eb910715SAlp Dener {
399eb910715SAlp Dener   PetscErrorCode               ierr;
400eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
401eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
402eb910715SAlp Dener   PetscInt                     kspits;
403eb910715SAlp Dener 
404eb910715SAlp Dener   PetscFunctionBegin;
40589da521bSAlp Dener   /* If there are no inactive variables left, save some computation and return an adjusted zero step
40689da521bSAlp Dener      that has (l-x) and (u-x) for lower and upper bounded variables. */
40789da521bSAlp Dener   if (!bnk->inactive_idx) {
40889da521bSAlp Dener     ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
409a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
41089da521bSAlp Dener     PetscFunctionReturn(0);
41189da521bSAlp Dener   }
41289da521bSAlp Dener 
4135e9b73cbSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
41489da521bSAlp Dener   if (bnk->active_idx) {
41533c78596SAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
4165e9b73cbSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
417eb3ba6a7SAlp Dener     if (tao->hessian == tao->hessian_pre) {
418eb3ba6a7SAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
419eb3ba6a7SAlp Dener     } else {
42033c78596SAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
4215e9b73cbSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
422eb3ba6a7SAlp Dener     }
423b9ac7092SAlp Dener     if (bnk->bfgs_pre) {
424b9ac7092SAlp Dener       ierr = PCLMVMSetIS(bnk->bfgs_pre, bnk->inactive_idx);CHKERRQ(ierr);
425b9ac7092SAlp Dener     }
4262f75a4aaSAlp Dener   } else {
42733c78596SAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
42833c78596SAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
42962675beeSAlp Dener     if (tao->hessian == tao->hessian_pre) {
43062675beeSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
43162675beeSAlp Dener     } else {
43233c78596SAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
43333c78596SAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);CHKERRQ(ierr);
43462675beeSAlp Dener     }
435b9ac7092SAlp Dener     if (bnk->bfgs_pre) {
436b9ac7092SAlp Dener       ierr = PCLMVMClearIS(bnk->bfgs_pre);CHKERRQ(ierr);
437b9ac7092SAlp Dener     }
43862675beeSAlp Dener   }
43962675beeSAlp Dener 
44062675beeSAlp Dener   /* Shift the reduced Hessian matrix */
44162675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
44262675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
44362675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
44462675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
44562675beeSAlp Dener     }
44662675beeSAlp Dener   }
44762675beeSAlp Dener 
448eb910715SAlp Dener   /* Solve the Newton system of equations */
449937a31a1SAlp Dener   tao->ksp_its = 0;
4502f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
4515e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
45209164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
4535e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
45489da521bSAlp Dener   if (bnk->active_idx) {
4555e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
4565e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
4575e9b73cbSAlp Dener   } else {
4585e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
4595e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
46028017e9fSAlp Dener   }
461eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
462fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
4635e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
464eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
465eb910715SAlp Dener     tao->ksp_its+=kspits;
466eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
467080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
468eb910715SAlp Dener 
469eb910715SAlp Dener     if (0.0 == tao->trust) {
470eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
471080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
472080d2917SAlp Dener         tao->trust = bnk->dnorm;
473eb910715SAlp Dener 
474eb910715SAlp Dener         /* Modify the radius if it is too large or small */
475eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
476eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
477eb910715SAlp Dener       } else {
478eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
479eb910715SAlp Dener            the trust-region subproblem to get a direction */
480eb910715SAlp Dener         tao->trust = tao->trust0;
481eb910715SAlp Dener 
482eb910715SAlp Dener         /* Modify the radius if it is too large or small */
483eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
484eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
485eb910715SAlp Dener 
486fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
4875e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
488eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
489eb910715SAlp Dener         tao->ksp_its+=kspits;
490eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
491080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
492eb910715SAlp Dener 
493080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
494eb910715SAlp Dener       }
495eb910715SAlp Dener     }
496eb910715SAlp Dener   } else {
4975e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
498eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
499eb910715SAlp Dener     tao->ksp_its += kspits;
500eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
501eb910715SAlp Dener   }
5025e9b73cbSAlp Dener   /* Restore sub vectors back */
50389da521bSAlp Dener   if (bnk->active_idx) {
5045e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5055e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5065e9b73cbSAlp Dener   }
507770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
508fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
509a1318120SAlp Dener   ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
510770b7498SAlp Dener 
511770b7498SAlp Dener   /* Record convergence reasons */
512e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
513e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
514770b7498SAlp Dener     ++bnk->ksp_atol;
515e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
516770b7498SAlp Dener     ++bnk->ksp_rtol;
517e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
518770b7498SAlp Dener     ++bnk->ksp_ctol;
519e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
520770b7498SAlp Dener     ++bnk->ksp_negc;
521e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
522770b7498SAlp Dener     ++bnk->ksp_dtol;
523e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
524770b7498SAlp Dener     ++bnk->ksp_iter;
525770b7498SAlp Dener   } else {
526770b7498SAlp Dener     ++bnk->ksp_othr;
527770b7498SAlp Dener   }
528fed79b8eSAlp Dener 
529fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
530b9ac7092SAlp Dener   if (bnk->M) {
531cd929ea3SAlp Dener     ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
532b2d8c577SAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 0)) {
533fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
534cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
53509164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
536eb910715SAlp Dener     }
537fed79b8eSAlp Dener   }
538e465cd6fSAlp Dener   PetscFunctionReturn(0);
539e465cd6fSAlp Dener }
540eb910715SAlp Dener 
54162675beeSAlp Dener /*------------------------------------------------------------*/
54262675beeSAlp Dener 
5435e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
5445e9b73cbSAlp Dener 
5455e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
5465e9b73cbSAlp Dener {
5475e9b73cbSAlp Dener   PetscErrorCode               ierr;
5485e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
5495e9b73cbSAlp Dener 
5505e9b73cbSAlp Dener   PetscFunctionBegin;
5515e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
55289da521bSAlp Dener   if (bnk->active_idx){
5535e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5545e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5555e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5565e9b73cbSAlp Dener   } else {
5575e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
5585e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
5595e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
5605e9b73cbSAlp Dener   }
5615e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
5625e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
5635e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
56433c78596SAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);CHKERRQ(ierr);
5655e9b73cbSAlp Dener   /* Restore the sub vectors */
56689da521bSAlp Dener   if (bnk->active_idx){
5675e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5685e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5695e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5705e9b73cbSAlp Dener   }
5715e9b73cbSAlp Dener   PetscFunctionReturn(0);
5725e9b73cbSAlp Dener }
5735e9b73cbSAlp Dener 
5745e9b73cbSAlp Dener /*------------------------------------------------------------*/
5755e9b73cbSAlp Dener 
57662675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
57762675beeSAlp Dener 
57862675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
57962675beeSAlp Dener    in the event that the Newton step fails the test.
58062675beeSAlp Dener */
58162675beeSAlp Dener 
582e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
583e465cd6fSAlp Dener {
584e465cd6fSAlp Dener   PetscErrorCode               ierr;
585e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
586e465cd6fSAlp Dener 
587b2d8c577SAlp Dener   PetscReal                    gdx, e_min;
588e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
589e465cd6fSAlp Dener 
590e465cd6fSAlp Dener   PetscFunctionBegin;
591080d2917SAlp Dener   ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
592eb910715SAlp Dener   if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
593eb910715SAlp Dener     /* Newton step is not descent or direction produced Inf or NaN
594eb910715SAlp Dener        Update the perturbation for next time */
595eb910715SAlp Dener     if (bnk->pert <= 0.0) {
596eb910715SAlp Dener       /* Initialize the perturbation */
597eb910715SAlp Dener       bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
598eb910715SAlp Dener       if (bnk->is_gltr) {
599eb910715SAlp Dener         ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
600eb910715SAlp Dener         bnk->pert = PetscMax(bnk->pert, -e_min);
601eb910715SAlp Dener       }
602eb910715SAlp Dener     } else {
603eb910715SAlp Dener       /* Increase the perturbation */
604eb910715SAlp Dener       bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
605eb910715SAlp Dener     }
606eb910715SAlp Dener 
6070ad3a497SAlp Dener     if (!bnk->M) {
608eb910715SAlp Dener       /* We don't have the bfgs matrix around and updated
609eb910715SAlp Dener          Must use gradient direction in this case */
610080d2917SAlp Dener       ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
611eb910715SAlp Dener       *stepType = BNK_GRADIENT;
612eb910715SAlp Dener     } else {
613eb910715SAlp Dener       /* Attempt to use the BFGS direction */
614cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
615eb910715SAlp Dener 
6168d5ead36SAlp Dener       /* Check for success (descent direction)
6178d5ead36SAlp Dener          NOTE: Negative gdx here means not a descent direction because
6188d5ead36SAlp Dener          the fall-back step is missing a negative sign. */
619080d2917SAlp Dener       ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
6203105154fSTodd Munson       if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
621eb910715SAlp Dener         /* BFGS direction is not descent or direction produced not a number
622eb910715SAlp Dener            We can assert bfgsUpdates > 1 in this case because
623eb910715SAlp Dener            the first solve produces the scaled gradient direction,
624eb910715SAlp Dener            which is guaranteed to be descent */
625eb910715SAlp Dener 
626eb910715SAlp Dener         /* Use steepest descent direction (scaled) */
627cd929ea3SAlp Dener         ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
62809164190SAlp Dener         ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
629cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
630eb910715SAlp Dener 
631eb910715SAlp Dener         *stepType = BNK_SCALED_GRADIENT;
632eb910715SAlp Dener       } else {
633cd929ea3SAlp Dener         ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
634eb910715SAlp Dener         if (1 == bfgsUpdates) {
635eb910715SAlp Dener           /* The first BFGS direction is always the scaled gradient */
636eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
637eb910715SAlp Dener         } else {
638eb910715SAlp Dener           *stepType = BNK_BFGS;
639eb910715SAlp Dener         }
640eb910715SAlp Dener       }
641eb910715SAlp Dener     }
6428d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
6438d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
644a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
645eb910715SAlp Dener   } else {
646eb910715SAlp Dener     /* Computed Newton step is descent */
647eb910715SAlp Dener     switch (ksp_reason) {
648eb910715SAlp Dener     case KSP_DIVERGED_NANORINF:
649eb910715SAlp Dener     case KSP_DIVERGED_BREAKDOWN:
650eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_MAT:
651eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_PC:
652eb910715SAlp Dener     case KSP_CONVERGED_CG_NEG_CURVE:
653eb910715SAlp Dener       /* Matrix or preconditioner is indefinite; increase perturbation */
654eb910715SAlp Dener       if (bnk->pert <= 0.0) {
655eb910715SAlp Dener         /* Initialize the perturbation */
656eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
657eb910715SAlp Dener         if (bnk->is_gltr) {
658eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
659eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
660eb910715SAlp Dener         }
661eb910715SAlp Dener       } else {
662eb910715SAlp Dener         /* Increase the perturbation */
663eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
664eb910715SAlp Dener       }
665eb910715SAlp Dener       break;
666eb910715SAlp Dener 
667eb910715SAlp Dener     default:
668eb910715SAlp Dener       /* Newton step computation is good; decrease perturbation */
669eb910715SAlp Dener       bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
670eb910715SAlp Dener       if (bnk->pert < bnk->pmin) {
671eb910715SAlp Dener         bnk->pert = 0.0;
672eb910715SAlp Dener       }
673eb910715SAlp Dener       break;
674eb910715SAlp Dener     }
675fed79b8eSAlp Dener     *stepType = BNK_NEWTON;
676eb910715SAlp Dener   }
677eb910715SAlp Dener   PetscFunctionReturn(0);
678eb910715SAlp Dener }
679eb910715SAlp Dener 
680df278d8fSAlp Dener /*------------------------------------------------------------*/
681df278d8fSAlp Dener 
682df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
683df278d8fSAlp Dener 
684df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
685df278d8fSAlp Dener   Newton step does not produce a valid step length.
686df278d8fSAlp Dener */
687df278d8fSAlp Dener 
688937a31a1SAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt *stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
689c14b763aSAlp Dener {
690c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
691c14b763aSAlp Dener   PetscErrorCode ierr;
692c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
693c14b763aSAlp Dener 
694b2d8c577SAlp Dener   PetscReal      e_min, gdx;
695c14b763aSAlp Dener   PetscInt       bfgsUpdates;
696c14b763aSAlp Dener 
697c14b763aSAlp Dener   PetscFunctionBegin;
698c14b763aSAlp Dener   /* Perform the linesearch */
699c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
700c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
701c14b763aSAlp Dener 
702b2d8c577SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && *stepType != BNK_SCALED_GRADIENT && *stepType != BNK_GRADIENT) {
703c14b763aSAlp Dener     /* Linesearch failed, revert solution */
704c14b763aSAlp Dener     bnk->f = bnk->fold;
705c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
706c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
707c14b763aSAlp Dener 
708937a31a1SAlp Dener     switch(*stepType) {
709c14b763aSAlp Dener     case BNK_NEWTON:
7108d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
711c14b763aSAlp Dener          Update the perturbation for next time */
712c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
713c14b763aSAlp Dener         /* Initialize the perturbation */
714c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
715c14b763aSAlp Dener         if (bnk->is_gltr) {
716c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
717c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
718c14b763aSAlp Dener         }
719c14b763aSAlp Dener       } else {
720c14b763aSAlp Dener         /* Increase the perturbation */
721c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
722c14b763aSAlp Dener       }
723c14b763aSAlp Dener 
7240ad3a497SAlp Dener       if (!bnk->M) {
725c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
726c14b763aSAlp Dener            Must use gradient direction in this case */
727937a31a1SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
728937a31a1SAlp Dener         *stepType = BNK_GRADIENT;
729c14b763aSAlp Dener       } else {
730c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
731cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
7328d5ead36SAlp Dener         /* Check for success (descent direction)
7338d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
734c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
7353105154fSTodd Munson         if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
736c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
737c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
738c14b763aSAlp Dener              Use steepest descent direction (scaled) */
739cd929ea3SAlp Dener           ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
740c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
741cd929ea3SAlp Dener           ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
742c14b763aSAlp Dener 
743c14b763aSAlp Dener           bfgsUpdates = 1;
744937a31a1SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
745c14b763aSAlp Dener         } else {
746cd929ea3SAlp Dener           ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
747c14b763aSAlp Dener           if (1 == bfgsUpdates) {
748c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
749937a31a1SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
750c14b763aSAlp Dener           } else {
751937a31a1SAlp Dener             *stepType = BNK_BFGS;
752c14b763aSAlp Dener           }
753c14b763aSAlp Dener         }
754c14b763aSAlp Dener       }
755c14b763aSAlp Dener       break;
756c14b763aSAlp Dener 
757c14b763aSAlp Dener     case BNK_BFGS:
758c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
759c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
760c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
761cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
762c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
763cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
764c14b763aSAlp Dener 
765c14b763aSAlp Dener       bfgsUpdates = 1;
766937a31a1SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
767c14b763aSAlp Dener       break;
768c14b763aSAlp Dener     }
7698d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
7708d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
771a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
772c14b763aSAlp Dener 
7738d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
774c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
775c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
776c14b763aSAlp Dener   }
777c14b763aSAlp Dener   *reason = ls_reason;
778c14b763aSAlp Dener   PetscFunctionReturn(0);
779c14b763aSAlp Dener }
780c14b763aSAlp Dener 
781df278d8fSAlp Dener /*------------------------------------------------------------*/
782df278d8fSAlp Dener 
783df278d8fSAlp Dener /* Routine for updating the trust radius.
784df278d8fSAlp Dener 
785df278d8fSAlp Dener   Function features three different update methods:
786df278d8fSAlp Dener   1) Line-search step length based
787df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
788df278d8fSAlp Dener   3) Interpolation
789df278d8fSAlp Dener */
790df278d8fSAlp Dener 
79128017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
792080d2917SAlp Dener {
793080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
794080d2917SAlp Dener   PetscErrorCode ierr;
795080d2917SAlp Dener 
796b1c2d0e3SAlp Dener   PetscReal      step, kappa;
797080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
798080d2917SAlp Dener 
799080d2917SAlp Dener   PetscFunctionBegin;
800080d2917SAlp Dener   /* Update trust region radius */
801080d2917SAlp Dener   *accept = PETSC_FALSE;
80228017e9fSAlp Dener   switch(updateType) {
803080d2917SAlp Dener   case BNK_UPDATE_STEP:
804c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
805080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
806080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
807080d2917SAlp Dener       if (step < bnk->nu1) {
808080d2917SAlp Dener         /* Very bad step taken; reduce radius */
809080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
810080d2917SAlp Dener       } else if (step < bnk->nu2) {
811080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
812080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
813080d2917SAlp Dener       } else if (step < bnk->nu3) {
814080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
815080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
816080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
817080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
818080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
819080d2917SAlp Dener         }
820080d2917SAlp Dener       } else if (step < bnk->nu4) {
821080d2917SAlp Dener         /*  Full step taken; increase the radius */
822080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
823080d2917SAlp Dener       } else {
824080d2917SAlp Dener         /*  More than full step taken; increase the radius */
825080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
826080d2917SAlp Dener       }
827080d2917SAlp Dener     } else {
828080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
829080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
830080d2917SAlp Dener     }
831080d2917SAlp Dener     break;
832080d2917SAlp Dener 
833080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
834080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
835b1c2d0e3SAlp Dener       if (prered < 0.0) {
836fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
837fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
838fed79b8eSAlp Dener            be rejected! */
839080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
8403105154fSTodd Munson       } else {
841b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
842080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
843080d2917SAlp Dener         } else {
8443105154fSTodd Munson           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) && (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
845080d2917SAlp Dener             kappa = 1.0;
8463105154fSTodd Munson           } else {
847080d2917SAlp Dener             kappa = actred / prered;
848080d2917SAlp Dener           }
849fed79b8eSAlp Dener 
850fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
851080d2917SAlp Dener           if (kappa < bnk->eta1) {
852fed79b8eSAlp Dener             /* Reject the step */
853080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
8543105154fSTodd Munson           } else {
855fed79b8eSAlp Dener             /* Accept the step */
856c133c014SAlp Dener             *accept = PETSC_TRUE;
857c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
8588d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
859080d2917SAlp Dener               if (kappa < bnk->eta2) {
860080d2917SAlp Dener                 /* Marginal bad step */
861c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
8623105154fSTodd Munson               } else if (kappa < bnk->eta3) {
863fed79b8eSAlp Dener                 /* Reasonable step */
864fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
8653105154fSTodd Munson               } else if (kappa < bnk->eta4) {
866080d2917SAlp Dener                 /* Good step */
867c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
8683105154fSTodd Munson               } else {
869080d2917SAlp Dener                 /* Very good step */
870c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
871080d2917SAlp Dener               }
872c133c014SAlp Dener             }
873080d2917SAlp Dener           }
874080d2917SAlp Dener         }
875080d2917SAlp Dener       }
876080d2917SAlp Dener     } else {
877080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
878080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
879080d2917SAlp Dener     }
880080d2917SAlp Dener     break;
881080d2917SAlp Dener 
882080d2917SAlp Dener   default:
883080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
884b1c2d0e3SAlp Dener       if (prered < 0.0) {
885080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
886080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
887080d2917SAlp Dener         /*  be rejected! */
888080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
889080d2917SAlp Dener       } else {
890b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
891080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
892080d2917SAlp Dener         } else {
893080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
894080d2917SAlp Dener             kappa = 1.0;
895080d2917SAlp Dener           } else {
896080d2917SAlp Dener             kappa = actred / prered;
897080d2917SAlp Dener           }
898080d2917SAlp Dener 
899080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
900080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
901080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
902080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
903080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
904080d2917SAlp Dener 
905080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
906080d2917SAlp Dener             /*  Great agreement */
907080d2917SAlp Dener             *accept = PETSC_TRUE;
908080d2917SAlp Dener             if (tau_max < 1.0) {
909080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
910080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
911080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
912080d2917SAlp Dener             } else {
913080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
914080d2917SAlp Dener             }
915080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
916080d2917SAlp Dener             /*  Good agreement */
917080d2917SAlp Dener             *accept = PETSC_TRUE;
918080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
919080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
920080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
921080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
922080d2917SAlp Dener             } else if (tau_max < 1.0) {
923080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
924080d2917SAlp Dener             } else {
925080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
926080d2917SAlp Dener             }
927080d2917SAlp Dener           } else {
928080d2917SAlp Dener             /*  Not good agreement */
929080d2917SAlp Dener             if (tau_min > 1.0) {
930080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
931080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
932080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
933080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
934080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
935080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
936080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
937080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
938080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
939080d2917SAlp Dener             } else {
940080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
941080d2917SAlp Dener             }
942080d2917SAlp Dener           }
943080d2917SAlp Dener         }
944080d2917SAlp Dener       }
945080d2917SAlp Dener     } else {
946080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
947080d2917SAlp Dener       tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust);
948080d2917SAlp Dener     }
94928017e9fSAlp Dener     break;
950080d2917SAlp Dener   }
951c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
952c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
953fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
954080d2917SAlp Dener   PetscFunctionReturn(0);
955080d2917SAlp Dener }
956080d2917SAlp Dener 
957eb910715SAlp Dener /* ---------------------------------------------------------- */
958df278d8fSAlp Dener 
95962675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
96062675beeSAlp Dener {
96162675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
96262675beeSAlp Dener 
96362675beeSAlp Dener   PetscFunctionBegin;
96462675beeSAlp Dener   switch (stepType) {
96562675beeSAlp Dener   case BNK_NEWTON:
96662675beeSAlp Dener     ++bnk->newt;
96762675beeSAlp Dener     break;
96862675beeSAlp Dener   case BNK_BFGS:
96962675beeSAlp Dener     ++bnk->bfgs;
97062675beeSAlp Dener     break;
97162675beeSAlp Dener   case BNK_SCALED_GRADIENT:
97262675beeSAlp Dener     ++bnk->sgrad;
97362675beeSAlp Dener     break;
97462675beeSAlp Dener   case BNK_GRADIENT:
97562675beeSAlp Dener     ++bnk->grad;
97662675beeSAlp Dener     break;
97762675beeSAlp Dener   default:
97862675beeSAlp Dener     break;
97962675beeSAlp Dener   }
98062675beeSAlp Dener   PetscFunctionReturn(0);
98162675beeSAlp Dener }
98262675beeSAlp Dener 
98362675beeSAlp Dener /* ---------------------------------------------------------- */
98462675beeSAlp Dener 
9859b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
986eb910715SAlp Dener {
987eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
988eb910715SAlp Dener   PetscErrorCode ierr;
9899b6ef848SAlp Dener   KSPType        ksp_type;
990e031d6f5SAlp Dener   PetscInt       i;
991eb910715SAlp Dener 
992eb910715SAlp Dener   PetscFunctionBegin;
993c4b75bccSAlp Dener   if (!tao->gradient) {
994c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);
995c4b75bccSAlp Dener   }
996c4b75bccSAlp Dener   if (!tao->stepdirection) {
997c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);
998c4b75bccSAlp Dener   }
999c4b75bccSAlp Dener   if (!bnk->W) {
1000c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);
1001c4b75bccSAlp Dener   }
1002c4b75bccSAlp Dener   if (!bnk->Xold) {
1003c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);
1004c4b75bccSAlp Dener   }
1005c4b75bccSAlp Dener   if (!bnk->Gold) {
1006c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);
1007c4b75bccSAlp Dener   }
1008c4b75bccSAlp Dener   if (!bnk->Xwork) {
1009c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);
1010c4b75bccSAlp Dener   }
1011c4b75bccSAlp Dener   if (!bnk->Gwork) {
1012c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);
1013c4b75bccSAlp Dener   }
1014c4b75bccSAlp Dener   if (!bnk->unprojected_gradient) {
1015c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);
1016c4b75bccSAlp Dener   }
1017c4b75bccSAlp Dener   if (!bnk->unprojected_gradient_old) {
1018c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);
1019c4b75bccSAlp Dener   }
1020c4b75bccSAlp Dener   if (!bnk->Diag_min) {
1021c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);
1022c4b75bccSAlp Dener   }
1023c4b75bccSAlp Dener   if (!bnk->Diag_max) {
1024c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);
1025c4b75bccSAlp Dener   }
1026e031d6f5SAlp Dener   if (bnk->max_cg_its > 0) {
1027c4b75bccSAlp Dener     /* Ensure that the important common vectors are shared between BNK and embedded BNCG */
1028c4b75bccSAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
102989da521bSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient_old));CHKERRQ(ierr);
103089da521bSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient_old);CHKERRQ(ierr);
103189da521bSAlp Dener     bnk->bncg_ctx->unprojected_gradient_old = bnk->unprojected_gradient_old;
1032c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient));CHKERRQ(ierr);
1033c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
1034c4b75bccSAlp Dener     bnk->bncg_ctx->unprojected_gradient = bnk->unprojected_gradient;
1035c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->Gold));CHKERRQ(ierr);
1036c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->G_old);CHKERRQ(ierr);
1037c4b75bccSAlp Dener     bnk->bncg_ctx->G_old = bnk->Gold;
1038c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->gradient));CHKERRQ(ierr);
1039c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->gradient);CHKERRQ(ierr);
1040c4b75bccSAlp Dener     bnk->bncg->gradient = tao->gradient;
1041c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->stepdirection));CHKERRQ(ierr);
1042c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->stepdirection);CHKERRQ(ierr);
1043c4b75bccSAlp Dener     bnk->bncg->stepdirection = tao->stepdirection;
1044c4b75bccSAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, tao->solution);CHKERRQ(ierr);
1045c4b75bccSAlp Dener     /* Copy over some settings from BNK into BNCG */
1046e031d6f5SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
1047e031d6f5SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
1048e031d6f5SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
1049937a31a1SAlp Dener     ierr = TaoSetConvergenceTest(bnk->bncg, tao->ops->convergencetest, tao->cnvP);CHKERRQ(ierr);
1050e031d6f5SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
1051e031d6f5SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
1052e031d6f5SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
1053e031d6f5SAlp Dener     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr);
1054c4b75bccSAlp Dener     for (i=0; i<tao->numbermonitors; ++i) {
1055e031d6f5SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
1056e031d6f5SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
1057e031d6f5SAlp Dener     }
1058e031d6f5SAlp Dener   }
1059c0f10754SAlp Dener   bnk->X_inactive = 0;
1060c0f10754SAlp Dener   bnk->G_inactive = 0;
106162675beeSAlp Dener   bnk->inactive_work = 0;
106262675beeSAlp Dener   bnk->active_work = 0;
106362675beeSAlp Dener   bnk->inactive_idx = 0;
106462675beeSAlp Dener   bnk->active_idx = 0;
106562675beeSAlp Dener   bnk->active_lower = 0;
106662675beeSAlp Dener   bnk->active_upper = 0;
106762675beeSAlp Dener   bnk->active_fixed = 0;
1068eb910715SAlp Dener   bnk->M = 0;
106909164190SAlp Dener   bnk->H_inactive = 0;
107009164190SAlp Dener   bnk->Hpre_inactive = 0;
10719b6ef848SAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
10729b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
10739b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
10749b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1075eb910715SAlp Dener   PetscFunctionReturn(0);
1076eb910715SAlp Dener }
1077eb910715SAlp Dener 
1078eb910715SAlp Dener /*------------------------------------------------------------*/
1079df278d8fSAlp Dener 
1080eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao)
1081eb910715SAlp Dener {
1082eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1083eb910715SAlp Dener   PetscErrorCode ierr;
1084eb910715SAlp Dener 
1085eb910715SAlp Dener   PetscFunctionBegin;
1086eb910715SAlp Dener   if (tao->setupcalled) {
1087eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1088eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1089eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
109009164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
109109164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
109209164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
109309164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
109462675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
109562675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1096c4b75bccSAlp Dener   }
1097ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_lower);CHKERRQ(ierr);
1098ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_upper);CHKERRQ(ierr);
1099ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_fixed);CHKERRQ(ierr);
1100ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
1101ca964c49SAlp Dener   ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
1102c4b75bccSAlp Dener   if (bnk->Hpre_inactive != tao->hessian_pre && bnk->Hpre_inactive != bnk->H_inactive) {
1103c4b75bccSAlp Dener     ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
1104c4b75bccSAlp Dener   }
1105c4b75bccSAlp Dener   if (bnk->H_inactive != tao->hessian) {
1106c4b75bccSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
1107c4b75bccSAlp Dener   }
1108ca964c49SAlp Dener   ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1109eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1110eb910715SAlp Dener   PetscFunctionReturn(0);
1111eb910715SAlp Dener }
1112eb910715SAlp Dener 
1113eb910715SAlp Dener /*------------------------------------------------------------*/
1114df278d8fSAlp Dener 
1115eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1116eb910715SAlp Dener {
1117eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1118eb910715SAlp Dener   PetscErrorCode ierr;
1119eb910715SAlp Dener 
1120eb910715SAlp Dener   PetscFunctionBegin;
1121eb910715SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr);
11228d5ead36SAlp 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);
11238d5ead36SAlp 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);
11242f75a4aaSAlp 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);
1125748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "(developer) Hessian perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
1126748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "(developer) minimum initial Hessian perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
1127748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "(developer) maximum initial Hessian perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
1128748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "(developer) initial merit factor for Hessian perturbation", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
1129748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "(developer) minimum Hessian perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
1130748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "(developer) maximum Hessian perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
1131748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "(developer) Hessian perturbation growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
1132748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "(developer) Hessian perturbation shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
1133748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "(developer) merit growth factor for Hessian perturbation", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
1134748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "(developer) merit shrink factor for Hessian perturbation", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
1135748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "(developer) threshold for rejecting step (-tao_bnk_update_type reduction)", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
1136748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "(developer) threshold for accepting marginal step (-tao_bnk_update_type reduction)", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
1137748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "(developer) threshold for accepting reasonable step (-tao_bnk_update_type reduction)", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
1138748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "(developer) threshold for accepting good step (-tao_bnk_update_type reduction)", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
1139748696b1SAlp 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);
1140748696b1SAlp 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);
1141748696b1SAlp 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);
1142748696b1SAlp 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);
1143748696b1SAlp 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);
1144748696b1SAlp 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);
1145748696b1SAlp 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);
1146748696b1SAlp 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);
1147748696b1SAlp 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);
1148748696b1SAlp 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);
1149748696b1SAlp 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);
1150748696b1SAlp 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);
1151748696b1SAlp 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);
1152748696b1SAlp 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);
1153748696b1SAlp 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);
1154748696b1SAlp 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);
1155748696b1SAlp 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);
1156748696b1SAlp 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);
1157748696b1SAlp 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);
1158748696b1SAlp 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);
1159748696b1SAlp 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);
1160748696b1SAlp 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);
1161748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "(developer) threshold for accepting good step (-tao_bnk_update_type interpolation)", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
1162748696b1SAlp 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);
1163748696b1SAlp 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);
1164748696b1SAlp 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);
1165748696b1SAlp 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);
1166748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "(developer) trust region interpolation factor (-tao_bnk_update_type interpolation)", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
1167748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "(developer) lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
1168748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "(developer) upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
1169748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "(developer) tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
1170748696b1SAlp 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);
1171748696b1SAlp 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);
1172c0f10754SAlp 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);
1173eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
117433c78596SAlp Dener   ierr = TaoSetFromOptions(bnk->bncg);CHKERRQ(ierr);
1175eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1176eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1177eb910715SAlp Dener   PetscFunctionReturn(0);
1178eb910715SAlp Dener }
1179eb910715SAlp Dener 
1180eb910715SAlp Dener /*------------------------------------------------------------*/
1181df278d8fSAlp Dener 
1182eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1183eb910715SAlp Dener {
1184eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1185eb910715SAlp Dener   PetscInt       nrejects;
1186eb910715SAlp Dener   PetscBool      isascii;
1187eb910715SAlp Dener   PetscErrorCode ierr;
1188eb910715SAlp Dener 
1189eb910715SAlp Dener   PetscFunctionBegin;
1190eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1191eb910715SAlp Dener   if (isascii) {
1192eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1193b9ac7092SAlp Dener     if (bnk->M) {
1194cd929ea3SAlp Dener       ierr = MatLMVMGetRejectCount(bnk->M,&nrejects);CHKERRQ(ierr);
1195b9ac7092SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected BFGS updates: %D\n",nrejects);CHKERRQ(ierr);
1196eb910715SAlp Dener     }
1197e031d6f5SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr);
1198eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1199b9ac7092SAlp Dener     if (bnk->M) {
1200eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1201b9ac7092SAlp Dener     }
1202eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1203eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1204eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1205eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1206eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1207eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1208eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1209eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1210eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1211eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1212eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1213eb910715SAlp Dener   }
1214eb910715SAlp Dener   PetscFunctionReturn(0);
1215eb910715SAlp Dener }
1216eb910715SAlp Dener 
1217eb910715SAlp Dener /* ---------------------------------------------------------- */
1218df278d8fSAlp Dener 
1219eb910715SAlp Dener /*MC
1220eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
122166ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1222eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1223eb910715SAlp Dener               Hk dk = -gk
12242b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12252b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1226eb910715SAlp Dener 
1227eb910715SAlp Dener     Options Database Keys:
1228b2d8c577SAlp Dener + -tao_bnk_max_cg_its - maximum number of bounded conjugate-gradient iterations taken in each Newton loop
12293cb832f1SAlp Dener . -tao_bnk_init_type - trust radius initialization method ("constant", "direction", "interpolation")
12303cb832f1SAlp Dener . -tao_bnk_update_type - trust radius update method ("step", "direction", "interpolation")
12313cb832f1SAlp Dener . -tao_bnk_as_type - active-set estimation method ("none", "bertsekas")
1232748696b1SAlp Dener . -tao_bnk_as_tol - (developer) initial tolerance used in estimating bounded active variables (-tao_bnk_as_type bertsekas)
1233748696b1SAlp Dener . -tao_bnk_as_step - (developer) trial step length used in estimating bounded active variables (-tao_bnk_as_type bertsekas)
1234748696b1SAlp Dener . -tao_bnk_sval - (developer) Hessian perturbation starting value
1235748696b1SAlp Dener . -tao_bnk_imin - (developer) minimum initial Hessian perturbation
1236748696b1SAlp Dener . -tao_bnk_imax - (developer) maximum initial Hessian perturbation
1237748696b1SAlp Dener . -tao_bnk_pmin - (developer) minimum Hessian perturbation
1238748696b1SAlp Dener . -tao_bnk_pmax - (developer) aximum Hessian perturbation
1239748696b1SAlp Dener . -tao_bnk_pgfac - (developer) Hessian perturbation growth factor
1240748696b1SAlp Dener . -tao_bnk_psfac - (developer) Hessian perturbation shrink factor
1241748696b1SAlp Dener . -tao_bnk_imfac - (developer) initial merit factor for Hessian perturbation
1242748696b1SAlp Dener . -tao_bnk_pmgfac - (developer) merit growth factor for Hessian perturbation
1243748696b1SAlp Dener . -tao_bnk_pmsfac - (developer) merit shrink factor for Hessian perturbation
1244748696b1SAlp Dener . -tao_bnk_eta1 - (developer) threshold for rejecting step (-tao_bnk_update_type reduction)
1245748696b1SAlp Dener . -tao_bnk_eta2 - (developer) threshold for accepting marginal step (-tao_bnk_update_type reduction)
1246748696b1SAlp Dener . -tao_bnk_eta3 - (developer) threshold for accepting reasonable step (-tao_bnk_update_type reduction)
1247748696b1SAlp Dener . -tao_bnk_eta4 - (developer) threshold for accepting good step (-tao_bnk_update_type reduction)
1248748696b1SAlp Dener . -tao_bnk_alpha1 - (developer) radius reduction factor for rejected step (-tao_bnk_update_type reduction)
1249748696b1SAlp Dener . -tao_bnk_alpha2 - (developer) radius reduction factor for marginally accepted bad step (-tao_bnk_update_type reduction)
1250748696b1SAlp Dener . -tao_bnk_alpha3 - (developer) radius increase factor for reasonable accepted step (-tao_bnk_update_type reduction)
1251748696b1SAlp Dener . -tao_bnk_alpha4 - (developer) radius increase factor for good accepted step (-tao_bnk_update_type reduction)
1252748696b1SAlp Dener . -tao_bnk_alpha5 - (developer) radius increase factor for very good accepted step (-tao_bnk_update_type reduction)
1253748696b1SAlp Dener . -tao_bnk_epsilon - (developer) tolerance for small pred/actual ratios that trigger automatic step acceptance (-tao_bnk_update_type reduction)
1254748696b1SAlp Dener . -tao_bnk_mu1 - (developer) threshold for accepting very good step (-tao_bnk_update_type interpolation)
1255748696b1SAlp Dener . -tao_bnk_mu2 - (developer) threshold for accepting good step (-tao_bnk_update_type interpolation)
1256748696b1SAlp Dener . -tao_bnk_gamma1 - (developer) radius reduction factor for rejected very bad step (-tao_bnk_update_type interpolation)
1257748696b1SAlp Dener . -tao_bnk_gamma2 - (developer) radius reduction factor for rejected bad step (-tao_bnk_update_type interpolation)
1258748696b1SAlp Dener . -tao_bnk_gamma3 - (developer) radius increase factor for accepted good step (-tao_bnk_update_type interpolation)
1259748696b1SAlp Dener . -tao_bnk_gamma4 - (developer) radius increase factor for accepted very good step (-tao_bnk_update_type interpolation)
1260748696b1SAlp Dener . -tao_bnk_theta - (developer) trust region interpolation factor (-tao_bnk_update_type interpolation)
1261748696b1SAlp Dener . -tao_bnk_nu1 - (developer) threshold for small line-search step length (-tao_bnk_update_type step)
1262748696b1SAlp Dener . -tao_bnk_nu2 - (developer) threshold for reasonable line-search step length (-tao_bnk_update_type step)
1263748696b1SAlp Dener . -tao_bnk_nu3 - (developer) threshold for large line-search step length (-tao_bnk_update_type step)
1264748696b1SAlp Dener . -tao_bnk_nu4 - (developer) threshold for very large line-search step length (-tao_bnk_update_type step)
1265748696b1SAlp Dener . -tao_bnk_omega1 - (developer) radius reduction factor for very small line-search step length (-tao_bnk_update_type step)
1266748696b1SAlp Dener . -tao_bnk_omega2 - (developer) radius reduction factor for small line-search step length (-tao_bnk_update_type step)
1267748696b1SAlp Dener . -tao_bnk_omega3 - (developer) radius factor for decent line-search step length (-tao_bnk_update_type step)
1268748696b1SAlp Dener . -tao_bnk_omega4 - (developer) radius increase factor for large line-search step length (-tao_bnk_update_type step)
1269748696b1SAlp Dener . -tao_bnk_omega5 - (developer) radius increase factor for very large line-search step length (-tao_bnk_update_type step)
1270748696b1SAlp Dener . -tao_bnk_mu1_i -  (developer) threshold for accepting very good step (-tao_bnk_init_type interpolation)
1271748696b1SAlp Dener . -tao_bnk_mu2_i -  (developer) threshold for accepting good step (-tao_bnk_init_type interpolation)
1272748696b1SAlp Dener . -tao_bnk_gamma1_i - (developer) radius reduction factor for rejected very bad step (-tao_bnk_init_type interpolation)
1273748696b1SAlp Dener . -tao_bnk_gamma2_i - (developer) radius reduction factor for rejected bad step (-tao_bnk_init_type interpolation)
1274748696b1SAlp Dener . -tao_bnk_gamma3_i - (developer) radius increase factor for accepted good step (-tao_bnk_init_type interpolation)
1275748696b1SAlp Dener . -tao_bnk_gamma4_i - (developer) radius increase factor for accepted very good step (-tao_bnk_init_type interpolation)
1276748696b1SAlp Dener - -tao_bnk_theta_i - (developer) trust region interpolation factor (-tao_bnk_init_type interpolation)
1277eb910715SAlp Dener 
1278eb910715SAlp Dener   Level: beginner
1279eb910715SAlp Dener M*/
1280eb910715SAlp Dener 
1281eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1282eb910715SAlp Dener {
1283eb910715SAlp Dener   TAO_BNK        *bnk;
1284eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1285eb910715SAlp Dener   PetscErrorCode ierr;
1286b9ac7092SAlp Dener   PC             pc;
1287eb910715SAlp Dener 
1288eb910715SAlp Dener   PetscFunctionBegin;
1289eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1290eb910715SAlp Dener 
1291eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1292eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1293eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1294eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1295eb910715SAlp Dener 
1296eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1297eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1298eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1299eb910715SAlp Dener 
1300eb910715SAlp Dener   tao->data = (void*)bnk;
1301eb910715SAlp Dener 
130266ed3702SAlp Dener   /*  Hessian shifting parameters */
1303eb910715SAlp Dener   bnk->sval   = 0.0;
1304eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1305eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1306eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1307eb910715SAlp Dener 
1308eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1309eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1310eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1311eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1312eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1313eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1314eb910715SAlp Dener 
1315eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1316eb910715SAlp Dener   bnk->nu1 = 0.25;
1317eb910715SAlp Dener   bnk->nu2 = 0.50;
1318eb910715SAlp Dener   bnk->nu3 = 1.00;
1319eb910715SAlp Dener   bnk->nu4 = 1.25;
1320eb910715SAlp Dener 
1321eb910715SAlp Dener   bnk->omega1 = 0.25;
1322eb910715SAlp Dener   bnk->omega2 = 0.50;
1323eb910715SAlp Dener   bnk->omega3 = 1.00;
1324eb910715SAlp Dener   bnk->omega4 = 2.00;
1325eb910715SAlp Dener   bnk->omega5 = 4.00;
1326eb910715SAlp Dener 
1327eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1328eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1329eb910715SAlp Dener   bnk->eta2 = 0.25;
1330eb910715SAlp Dener   bnk->eta3 = 0.50;
1331eb910715SAlp Dener   bnk->eta4 = 0.90;
1332eb910715SAlp Dener 
1333eb910715SAlp Dener   bnk->alpha1 = 0.25;
1334eb910715SAlp Dener   bnk->alpha2 = 0.50;
1335eb910715SAlp Dener   bnk->alpha3 = 1.00;
1336eb910715SAlp Dener   bnk->alpha4 = 2.00;
1337eb910715SAlp Dener   bnk->alpha5 = 4.00;
1338eb910715SAlp Dener 
1339eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1340eb910715SAlp Dener   bnk->mu1 = 0.10;
1341eb910715SAlp Dener   bnk->mu2 = 0.50;
1342eb910715SAlp Dener 
1343eb910715SAlp Dener   bnk->gamma1 = 0.25;
1344eb910715SAlp Dener   bnk->gamma2 = 0.50;
1345eb910715SAlp Dener   bnk->gamma3 = 2.00;
1346eb910715SAlp Dener   bnk->gamma4 = 4.00;
1347eb910715SAlp Dener 
1348eb910715SAlp Dener   bnk->theta = 0.05;
1349eb910715SAlp Dener 
1350eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1351eb910715SAlp Dener   bnk->mu1_i = 0.35;
1352eb910715SAlp Dener   bnk->mu2_i = 0.50;
1353eb910715SAlp Dener 
1354eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1355eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1356eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1357eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1358eb910715SAlp Dener 
1359eb910715SAlp Dener   bnk->theta_i = 0.25;
1360eb910715SAlp Dener 
1361eb910715SAlp Dener   /*  Remaining parameters */
1362c0f10754SAlp Dener   bnk->max_cg_its = 0;
1363eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1364eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1365770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
13660a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
13670a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
136862675beeSAlp Dener   bnk->dmin = 1.0e-6;
136962675beeSAlp Dener   bnk->dmax = 1.0e6;
1370eb910715SAlp Dener 
1371b9ac7092SAlp Dener   bnk->M               = 0;
1372b9ac7092SAlp Dener   bnk->bfgs_pre        = 0;
1373eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
1374*7b1c7716SAlp Dener   bnk->update_type     = BNK_UPDATE_REDUCTION;
13752f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1376eb910715SAlp Dener 
1377e031d6f5SAlp Dener   /* Create the embedded BNCG solver */
1378e031d6f5SAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
1379e031d6f5SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
1380e031d6f5SAlp Dener   ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr);
1381e031d6f5SAlp Dener   ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
1382e031d6f5SAlp Dener 
1383c0f10754SAlp Dener   /* Create the line search */
1384eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1385eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1386e031d6f5SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1387eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1388eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1389eb910715SAlp Dener 
1390eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1391eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1392eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1393eb910715SAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr);
1394eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1395b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);
1396b9ac7092SAlp Dener   ierr = PCSetType(pc, PCLMVM);CHKERRQ(ierr);
1397eb910715SAlp Dener   PetscFunctionReturn(0);
1398eb910715SAlp Dener }
1399