xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision b9ac7092a680e1d80a71621a7a51ada5b40c61d6)
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 
12cd929ea3SAlp Dener PetscErrorCode TaoBNKPreconBFGS(PC BFGSpc, Vec X, Vec Y)
13eb910715SAlp Dener {
14eb910715SAlp Dener   PetscErrorCode ierr;
15cd929ea3SAlp Dener   Mat *M;
16eb910715SAlp Dener 
17eb910715SAlp Dener   PetscFunctionBegin;
18cd929ea3SAlp Dener   ierr = PCShellGetContext(BFGSpc, (void**)&M);CHKERRQ(ierr);
19cd929ea3SAlp Dener   ierr = MatSolve(*M, X, Y);CHKERRQ(ierr);
20eb910715SAlp Dener   PetscFunctionReturn(0);
21eb910715SAlp Dener }
22eb910715SAlp Dener 
23df278d8fSAlp Dener /*------------------------------------------------------------*/
24df278d8fSAlp Dener 
25df278d8fSAlp Dener /* Routine for initializing the KSP solver, the BFGS preconditioner, and the initial trust radius estimation */
26df278d8fSAlp Dener 
27c0f10754SAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType, PetscBool *needH)
28eb910715SAlp Dener {
29eb910715SAlp Dener   PetscErrorCode               ierr;
30eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
31eb910715SAlp Dener   PC                           pc;
32eb910715SAlp Dener 
3389da521bSAlp Dener   PetscReal                    f_min, ftrial, prered, actred, kappa, sigma, resnorm;
34eb910715SAlp Dener   PetscReal                    tau, tau_1, tau_2, tau_max, tau_min, max_radius;
3589da521bSAlp Dener   PetscReal                    delta;
36*b9ac7092SAlp Dener   PetscBool                    is_bfgs, is_jacobi;
37c4b75bccSAlp Dener   PetscInt                     n, N, nDiff;
38eb910715SAlp Dener   PetscInt                     i_max = 5;
39eb910715SAlp Dener   PetscInt                     j_max = 1;
40eb910715SAlp Dener   PetscInt                     i, j;
41eb910715SAlp Dener 
42eb910715SAlp Dener   PetscFunctionBegin;
4328017e9fSAlp Dener   /* Project the current point onto the feasible set */
4428017e9fSAlp Dener   ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr);
45e031d6f5SAlp Dener   ierr = TaoSetVariableBounds(bnk->bncg, tao->XL, tao->XU);CHKERRQ(ierr);
46*b9ac7092SAlp Dener   if (tao->bounded) {
4728017e9fSAlp Dener     ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr);
48cd929ea3SAlp Dener   }
4928017e9fSAlp Dener 
5028017e9fSAlp Dener   /* Project the initial point onto the feasible region */
513b063059SAlp Dener   ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
5228017e9fSAlp Dener 
5328017e9fSAlp Dener   /* Check convergence criteria */
5428017e9fSAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr);
5561be54a6SAlp Dener   ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
5661be54a6SAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
5761be54a6SAlp Dener   ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
5808752603SAlp Dener   ierr = VecNorm(tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
5928017e9fSAlp Dener 
60c0f10754SAlp Dener   /* Test the initial point for convergence */
6189da521bSAlp Dener   ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
6289da521bSAlp Dener   ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
63b4a30f08SAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
64e031d6f5SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
65e031d6f5SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
66c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
67c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
68c0f10754SAlp Dener 
69e031d6f5SAlp Dener   /* Reset KSP stopping reason counters */
70eb910715SAlp Dener   bnk->ksp_atol = 0;
71eb910715SAlp Dener   bnk->ksp_rtol = 0;
72eb910715SAlp Dener   bnk->ksp_dtol = 0;
73eb910715SAlp Dener   bnk->ksp_ctol = 0;
74eb910715SAlp Dener   bnk->ksp_negc = 0;
75eb910715SAlp Dener   bnk->ksp_iter = 0;
76eb910715SAlp Dener   bnk->ksp_othr = 0;
77eb910715SAlp Dener 
78e031d6f5SAlp Dener   /* Reset accepted step type counters */
79e031d6f5SAlp Dener   bnk->tot_cg_its = 0;
80e031d6f5SAlp Dener   bnk->newt = 0;
81e031d6f5SAlp Dener   bnk->bfgs = 0;
82e031d6f5SAlp Dener   bnk->sgrad = 0;
83e031d6f5SAlp Dener   bnk->grad = 0;
84e031d6f5SAlp Dener 
85fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
86fed79b8eSAlp Dener   bnk->pert = bnk->sval;
87fed79b8eSAlp Dener 
88937a31a1SAlp Dener   /* Reset initial steplength to zero (this helps BNCG reset its direction internally) */
89937a31a1SAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
90937a31a1SAlp Dener 
91e031d6f5SAlp Dener   /* Allocate the vectors needed for the BFGS approximation */
92*b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
93*b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCLMVM, &is_bfgs);CHKERRQ(ierr);
94*b9ac7092SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)pc, PCJACOBI, &is_jacobi);CHKERRQ(ierr);
95*b9ac7092SAlp Dener   if (is_bfgs) {
96*b9ac7092SAlp Dener     bnk->bfgs_pre = pc;
97*b9ac7092SAlp Dener     ierr = PCLMVMGetMatLMVM(bnk->bfgs_pre, &bnk->M);CHKERRQ(ierr);
98eb910715SAlp Dener     ierr = VecGetLocalSize(tao->solution, &n);CHKERRQ(ierr);
99eb910715SAlp Dener     ierr = VecGetSize(tao->solution, &N);CHKERRQ(ierr);
100*b9ac7092SAlp Dener     ierr = MatSetSizes(bnk->M, n, n, N, N);CHKERRQ(ierr);
101cd929ea3SAlp Dener     ierr = MatLMVMAllocate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
102*b9ac7092SAlp Dener   } else if (is_jacobi) {
103*b9ac7092SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
104e031d6f5SAlp Dener   }
105e031d6f5SAlp Dener 
106e031d6f5SAlp Dener   /* Prepare the min/max vectors for safeguarding diagonal scales */
10762675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
10862675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
109eb910715SAlp Dener 
110eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
111eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
112c0f10754SAlp Dener   *needH = PETSC_TRUE;
113eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
11462675beeSAlp Dener     switch(initType) {
115eb910715SAlp Dener     case BNK_INIT_CONSTANT:
116eb910715SAlp Dener       /* Use the initial radius specified */
117c0f10754SAlp Dener       tao->trust = tao->trust0;
118eb910715SAlp Dener       break;
119eb910715SAlp Dener 
120eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
121c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
122eb910715SAlp Dener       max_radius = 0.0;
12308752603SAlp Dener       tao->trust = tao->trust0;
124eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1250a4511e9SAlp Dener         f_min = bnk->f;
126eb910715SAlp Dener         sigma = 0.0;
127eb910715SAlp Dener 
128c0f10754SAlp Dener         if (*needH) {
12962602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
130e031d6f5SAlp Dener           ierr = TaoBNKComputeHessian(tao);CHKERRQ(ierr);
13108752603SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, BNK_AS_NONE);CHKERRQ(ierr);
13289da521bSAlp Dener           ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
13389da521bSAlp Dener           if (bnk->active_idx) {
1342ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
13528017e9fSAlp Dener           } else {
13608752603SAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
13728017e9fSAlp Dener           }
138c0f10754SAlp Dener           *needH = PETSC_FALSE;
139eb910715SAlp Dener         }
140eb910715SAlp Dener 
141eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
14262602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
14362602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
14462602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
1453b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
14689da521bSAlp Dener           /* Compute the step we actually accepted */
147eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
14862602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
14962602cfbSAlp Dener           /* Compute the objective at the trial */
15062602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
151b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(bnk->f)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
15262602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
153eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
154eb910715SAlp Dener             tau = bnk->gamma1_i;
155eb910715SAlp Dener           } else {
1560a4511e9SAlp Dener             if (ftrial < f_min) {
1570a4511e9SAlp Dener               f_min = ftrial;
158eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
159eb910715SAlp Dener             }
16008752603SAlp Dener 
161770b7498SAlp Dener             /* Compute the predicted and actual reduction */
16289da521bSAlp Dener             if (bnk->active_idx) {
16308752603SAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
16408752603SAlp Dener               ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1652ab2a32cSAlp Dener             } else {
16608752603SAlp Dener               bnk->X_inactive = bnk->W;
16708752603SAlp Dener               bnk->inactive_work = bnk->Xwork;
1682ab2a32cSAlp Dener             }
16908752603SAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
17008752603SAlp Dener             ierr = VecDot(bnk->X_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
17189da521bSAlp Dener             if (bnk->active_idx) {
17208752603SAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
17308752603SAlp Dener               ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1742ab2a32cSAlp Dener             }
175eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
176eb910715SAlp Dener             actred = bnk->f - ftrial;
1773105154fSTodd Munson             if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
178eb910715SAlp Dener               kappa = 1.0;
1793105154fSTodd Munson             } else {
180eb910715SAlp Dener               kappa = actred / prered;
181eb910715SAlp Dener             }
182eb910715SAlp Dener 
183eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
184eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
185eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
186eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
187eb910715SAlp Dener 
188eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
189eb910715SAlp Dener               /*  Great agreement */
190eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
191eb910715SAlp Dener 
192eb910715SAlp Dener               if (tau_max < 1.0) {
193eb910715SAlp Dener                 tau = bnk->gamma3_i;
1943105154fSTodd Munson               } else if (tau_max > bnk->gamma4_i) {
195eb910715SAlp Dener                 tau = bnk->gamma4_i;
1963105154fSTodd Munson               } else {
197eb910715SAlp Dener                 tau = tau_max;
198eb910715SAlp Dener               }
1998f8a4e06SAlp Dener             } else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
200eb910715SAlp Dener               /*  Good agreement */
201eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
202eb910715SAlp Dener 
203eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
204eb910715SAlp Dener                 tau = bnk->gamma2_i;
205eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
206eb910715SAlp Dener                 tau = bnk->gamma3_i;
207eb910715SAlp Dener               } else {
208eb910715SAlp Dener                 tau = tau_max;
209eb910715SAlp Dener               }
2108f8a4e06SAlp Dener             } else {
211eb910715SAlp Dener               /*  Not good agreement */
212eb910715SAlp Dener               if (tau_min > 1.0) {
213eb910715SAlp Dener                 tau = bnk->gamma2_i;
214eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
215eb910715SAlp Dener                 tau = bnk->gamma1_i;
216eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
217eb910715SAlp Dener                 tau = bnk->gamma1_i;
2183105154fSTodd Munson               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
219eb910715SAlp Dener                 tau = tau_1;
2203105154fSTodd Munson               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
221eb910715SAlp Dener                 tau = tau_2;
222eb910715SAlp Dener               } else {
223eb910715SAlp Dener                 tau = tau_max;
224eb910715SAlp Dener               }
225eb910715SAlp Dener             }
226eb910715SAlp Dener           }
227eb910715SAlp Dener           tao->trust = tau * tao->trust;
228eb910715SAlp Dener         }
229eb910715SAlp Dener 
2300a4511e9SAlp Dener         if (f_min < bnk->f) {
231937a31a1SAlp Dener           /* We accidentally found a solution better than the initial, so accept it */
2320a4511e9SAlp Dener           bnk->f = f_min;
233937a31a1SAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
234eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
2353b063059SAlp Dener           ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr);
236937a31a1SAlp Dener           ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr);
237937a31a1SAlp Dener           ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr);
23809164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
23961be54a6SAlp Dener           ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
24061be54a6SAlp Dener           ierr = VecCopy(bnk->unprojected_gradient, tao->gradient);CHKERRQ(ierr);
24161be54a6SAlp Dener           ierr = VecISSet(tao->gradient, bnk->active_idx, 0.0);CHKERRQ(ierr);
242937a31a1SAlp Dener           /* Compute gradient at the new iterate and flip switch to compute the Hessian later */
243c4b75bccSAlp Dener           ierr = VecNorm(tao->gradient, NORM_2, &bnk->gnorm);CHKERRQ(ierr);
244c0f10754SAlp Dener           *needH = PETSC_TRUE;
245937a31a1SAlp Dener           /* Test the new step for convergence */
24689da521bSAlp Dener           ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->W);CHKERRQ(ierr);
24789da521bSAlp Dener           ierr = VecNorm(bnk->W, NORM_2, &resnorm);CHKERRQ(ierr);
248b4a30f08SAlp Dener           if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
249e031d6f5SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
250e031d6f5SAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr);
251eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
252eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
253937a31a1SAlp Dener           /* active BNCG recycling early because we have a stepdirection computed */
254937a31a1SAlp Dener           ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
255eb910715SAlp Dener         }
256eb910715SAlp Dener       }
257eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
258e031d6f5SAlp Dener 
259e031d6f5SAlp Dener       /* Ensure that the trust radius is within the limits */
260e031d6f5SAlp Dener       tao->trust = PetscMax(tao->trust, bnk->min_radius);
261e031d6f5SAlp Dener       tao->trust = PetscMin(tao->trust, bnk->max_radius);
262eb910715SAlp Dener       break;
263eb910715SAlp Dener 
264eb910715SAlp Dener     default:
265eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
266eb910715SAlp Dener       tao->trust = 0.0;
267eb910715SAlp Dener       break;
268eb910715SAlp Dener     }
269eb910715SAlp Dener   }
270e031d6f5SAlp Dener 
271eb910715SAlp Dener   /* Set initial scaling for the BFGS preconditioner
272eb910715SAlp Dener      This step is done after computing the initial trust-region radius
273eb910715SAlp Dener      since the function value may have decreased */
274*b9ac7092SAlp Dener   if (bnk->M) {
2759b6ef848SAlp Dener     delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
276cd929ea3SAlp Dener     ierr = MatLMVMSetJ0Scale(bnk->M, delta);CHKERRQ(ierr);
277eb910715SAlp Dener   }
278eb910715SAlp Dener   PetscFunctionReturn(0);
279eb910715SAlp Dener }
280eb910715SAlp Dener 
281df278d8fSAlp Dener /*------------------------------------------------------------*/
282df278d8fSAlp Dener 
28362675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */
28462675beeSAlp Dener 
28562675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
28662675beeSAlp Dener {
28762675beeSAlp Dener   PetscErrorCode               ierr;
28862675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
289c4b75bccSAlp Dener   PetscReal                    delta;
29062675beeSAlp Dener 
29162675beeSAlp Dener   PetscFunctionBegin;
29262675beeSAlp Dener   /* Compute the Hessian */
29362675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
29462675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
295*b9ac7092SAlp Dener   if (bnk->M) {
29662675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
29762675beeSAlp Dener     /* Update the BFGS diagonal scaling */
298c4b75bccSAlp Dener     delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
299cd929ea3SAlp Dener     ierr = MatLMVMSetJ0Scale(bnk->M,delta);CHKERRQ(ierr);
30062675beeSAlp Dener   }
30162675beeSAlp Dener   PetscFunctionReturn(0);
30262675beeSAlp Dener }
30362675beeSAlp Dener 
30462675beeSAlp Dener /*------------------------------------------------------------*/
30562675beeSAlp Dener 
3062f75a4aaSAlp Dener /* Routine for estimating the active set */
3072f75a4aaSAlp Dener 
30808752603SAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao, PetscInt asType)
3092f75a4aaSAlp Dener {
3102f75a4aaSAlp Dener   PetscErrorCode               ierr;
3112f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
312c4b75bccSAlp Dener   PetscBool                    hessComputed, diagExists;
3132f75a4aaSAlp Dener 
3142f75a4aaSAlp Dener   PetscFunctionBegin;
31508752603SAlp Dener   switch (asType) {
3162f75a4aaSAlp Dener   case BNK_AS_NONE:
3172f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
3182f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
3192f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
3202f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
3212f75a4aaSAlp Dener     break;
3222f75a4aaSAlp Dener 
3232f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3242f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
325*b9ac7092SAlp Dener     if (bnk->M) {
3262f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
327cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3282f75a4aaSAlp Dener     } else {
32961be54a6SAlp Dener       ierr = MatAssembled(tao->hessian, &hessComputed);CHKERRQ(ierr);
330c4b75bccSAlp Dener       ierr = MatHasOperation(tao->hessian, MATOP_GET_DIAGONAL, &diagExists);CHKERRQ(ierr);
331c4b75bccSAlp Dener       if (hessComputed && diagExists) {
3329b6ef848SAlp Dener         /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3332f75a4aaSAlp Dener         ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3349b6ef848SAlp Dener         ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3359b6ef848SAlp Dener         ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3362f75a4aaSAlp Dener         ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3372f75a4aaSAlp Dener         ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
33861be54a6SAlp Dener       } else {
339c4b75bccSAlp Dener         /* If the Hessian or its diagonal does not exist, we will simply use gradient step */
34061be54a6SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
34161be54a6SAlp Dener       }
3422f75a4aaSAlp Dener     }
3432f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
34489da521bSAlp Dener     ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, bnk->unprojected_gradient, bnk->W, bnk->Xwork, bnk->as_step, &bnk->as_tol,
34589da521bSAlp Dener                                    &bnk->active_lower, &bnk->active_upper, &bnk->active_fixed, &bnk->active_idx, &bnk->inactive_idx);CHKERRQ(ierr);
346c4b75bccSAlp Dener     break;
3472f75a4aaSAlp Dener 
3482f75a4aaSAlp Dener   default:
3492f75a4aaSAlp Dener     break;
3502f75a4aaSAlp Dener   }
3512f75a4aaSAlp Dener   PetscFunctionReturn(0);
3522f75a4aaSAlp Dener }
3532f75a4aaSAlp Dener 
3542f75a4aaSAlp Dener /*------------------------------------------------------------*/
3552f75a4aaSAlp Dener 
3562f75a4aaSAlp Dener /* Routine for bounding the step direction */
3572f75a4aaSAlp Dener 
358a1318120SAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, PetscInt asType, Vec step)
3592f75a4aaSAlp Dener {
3602f75a4aaSAlp Dener   PetscErrorCode               ierr;
3612f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3622f75a4aaSAlp Dener 
3632f75a4aaSAlp Dener   PetscFunctionBegin;
364a1318120SAlp Dener   switch (asType) {
3652f75a4aaSAlp Dener   case BNK_AS_NONE:
366c4b75bccSAlp Dener     ierr = VecISSet(step, bnk->active_idx, 0.0);CHKERRQ(ierr);
3672f75a4aaSAlp Dener     break;
3682f75a4aaSAlp Dener 
3692f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
370c4b75bccSAlp Dener     ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, 1.0, step);CHKERRQ(ierr);
3712f75a4aaSAlp Dener     break;
3722f75a4aaSAlp Dener 
3732f75a4aaSAlp Dener   default:
3742f75a4aaSAlp Dener     break;
3752f75a4aaSAlp Dener   }
3762f75a4aaSAlp Dener   PetscFunctionReturn(0);
3772f75a4aaSAlp Dener }
3782f75a4aaSAlp Dener 
379e031d6f5SAlp Dener /*------------------------------------------------------------*/
380e031d6f5SAlp Dener 
381e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to
382e031d6f5SAlp Dener    accelerate Newton convergence.
383e031d6f5SAlp Dener 
384e031d6f5SAlp Dener    In practice, this approach simply trades off Hessian evaluations
385e031d6f5SAlp Dener    for more gradient evaluations.
386e031d6f5SAlp Dener */
387e031d6f5SAlp Dener 
388c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
389c0f10754SAlp Dener {
390c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
391c0f10754SAlp Dener   PetscErrorCode               ierr;
392c0f10754SAlp Dener 
393c0f10754SAlp Dener   PetscFunctionBegin;
394c0f10754SAlp Dener   *terminate = PETSC_FALSE;
395c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
396c4b75bccSAlp Dener     /* Copy the current function value (important vectors are already shared) */
397c0f10754SAlp Dener     bnk->bncg_ctx->f = bnk->f;
398c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
399c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
400c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
401c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
402c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
403c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
404c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
405e031d6f5SAlp Dener     bnk->tot_cg_its += bnk->bncg->niter;
406c4b75bccSAlp Dener     /* Extract the BNCG function value out and save it into BNK */
407c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
408c0f10754SAlp 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) {
409c0f10754SAlp Dener       *terminate = PETSC_TRUE;
41061be54a6SAlp Dener     } else {
41133c78596SAlp Dener       ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr);
412c0f10754SAlp Dener     }
413c0f10754SAlp Dener   }
414c0f10754SAlp Dener   PetscFunctionReturn(0);
415c0f10754SAlp Dener }
416c0f10754SAlp Dener 
4172f75a4aaSAlp Dener /*------------------------------------------------------------*/
4182f75a4aaSAlp Dener 
419c0f10754SAlp Dener /* Routine for computing the Newton step. */
420df278d8fSAlp Dener 
42162675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason)
422eb910715SAlp Dener {
423eb910715SAlp Dener   PetscErrorCode               ierr;
424eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
425e465cd6fSAlp Dener   PetscReal                    delta;
426eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
427eb910715SAlp Dener   PetscInt                     kspits;
428eb910715SAlp Dener 
429eb910715SAlp Dener   PetscFunctionBegin;
43089da521bSAlp Dener   /* If there are no inactive variables left, save some computation and return an adjusted zero step
43189da521bSAlp Dener      that has (l-x) and (u-x) for lower and upper bounded variables. */
43289da521bSAlp Dener   if (!bnk->inactive_idx) {
43389da521bSAlp Dener     ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
434a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
43589da521bSAlp Dener     PetscFunctionReturn(0);
43689da521bSAlp Dener   }
43789da521bSAlp Dener 
4385e9b73cbSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
43989da521bSAlp Dener   if (bnk->active_idx) {
44033c78596SAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
4415e9b73cbSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
442eb3ba6a7SAlp Dener     if (tao->hessian == tao->hessian_pre) {
443eb3ba6a7SAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
444eb3ba6a7SAlp Dener     } else {
44533c78596SAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
4465e9b73cbSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
447eb3ba6a7SAlp Dener     }
448*b9ac7092SAlp Dener     if (bnk->bfgs_pre) {
449*b9ac7092SAlp Dener       ierr = PCLMVMSetIS(bnk->bfgs_pre, bnk->inactive_idx);CHKERRQ(ierr);
450*b9ac7092SAlp Dener     }
4512f75a4aaSAlp Dener   } else {
45233c78596SAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
45333c78596SAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr);
45462675beeSAlp Dener     if (tao->hessian == tao->hessian_pre) {
45562675beeSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
45662675beeSAlp Dener     } else {
45733c78596SAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
45833c78596SAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);CHKERRQ(ierr);
45962675beeSAlp Dener     }
460*b9ac7092SAlp Dener     if (bnk->bfgs_pre) {
461*b9ac7092SAlp Dener       ierr = PCLMVMClearIS(bnk->bfgs_pre);CHKERRQ(ierr);
462*b9ac7092SAlp Dener     }
46362675beeSAlp Dener   }
46462675beeSAlp Dener 
46562675beeSAlp Dener   /* Shift the reduced Hessian matrix */
46662675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
46762675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
46862675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
46962675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
47062675beeSAlp Dener     }
47162675beeSAlp Dener   }
47262675beeSAlp Dener 
473eb910715SAlp Dener   /* Solve the Newton system of equations */
474937a31a1SAlp Dener   tao->ksp_its = 0;
4752f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
4765e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
47709164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
4785e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
47989da521bSAlp Dener   if (bnk->active_idx) {
4805e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
4815e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
4825e9b73cbSAlp Dener   } else {
4835e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
4845e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
48528017e9fSAlp Dener   }
486eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
487fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
4885e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
489eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
490eb910715SAlp Dener     tao->ksp_its+=kspits;
491eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
492080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
493eb910715SAlp Dener 
494eb910715SAlp Dener     if (0.0 == tao->trust) {
495eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
496080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
497080d2917SAlp Dener         tao->trust = bnk->dnorm;
498eb910715SAlp Dener 
499eb910715SAlp Dener         /* Modify the radius if it is too large or small */
500eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
501eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
502eb910715SAlp Dener       } else {
503eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
504eb910715SAlp Dener            the trust-region subproblem to get a direction */
505eb910715SAlp Dener         tao->trust = tao->trust0;
506eb910715SAlp Dener 
507eb910715SAlp Dener         /* Modify the radius if it is too large or small */
508eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
509eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
510eb910715SAlp Dener 
511fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5125e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
513eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
514eb910715SAlp Dener         tao->ksp_its+=kspits;
515eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
516080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
517eb910715SAlp Dener 
518080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
519eb910715SAlp Dener       }
520eb910715SAlp Dener     }
521eb910715SAlp Dener   } else {
5225e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
523eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
524eb910715SAlp Dener     tao->ksp_its += kspits;
525eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
526eb910715SAlp Dener   }
5275e9b73cbSAlp Dener   /* Restore sub vectors back */
52889da521bSAlp Dener   if (bnk->active_idx) {
5295e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5305e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5315e9b73cbSAlp Dener   }
532770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
533fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
534a1318120SAlp Dener   ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
535770b7498SAlp Dener 
536770b7498SAlp Dener   /* Record convergence reasons */
537e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
538e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
539770b7498SAlp Dener     ++bnk->ksp_atol;
540e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
541770b7498SAlp Dener     ++bnk->ksp_rtol;
542e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
543770b7498SAlp Dener     ++bnk->ksp_ctol;
544e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
545770b7498SAlp Dener     ++bnk->ksp_negc;
546e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
547770b7498SAlp Dener     ++bnk->ksp_dtol;
548e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
549770b7498SAlp Dener     ++bnk->ksp_iter;
550770b7498SAlp Dener   } else {
551770b7498SAlp Dener     ++bnk->ksp_othr;
552770b7498SAlp Dener   }
553fed79b8eSAlp Dener 
554fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
555*b9ac7092SAlp Dener   if (bnk->M) {
556cd929ea3SAlp Dener     ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
557e465cd6fSAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 1)) {
558fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
5599b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
560cd929ea3SAlp Dener       ierr = MatLMVMSetJ0Scale(bnk->M,delta);CHKERRQ(ierr);
561cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
56209164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
563eb910715SAlp Dener     }
564fed79b8eSAlp Dener   }
565e465cd6fSAlp Dener   PetscFunctionReturn(0);
566e465cd6fSAlp Dener }
567eb910715SAlp Dener 
56862675beeSAlp Dener /*------------------------------------------------------------*/
56962675beeSAlp Dener 
5705e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
5715e9b73cbSAlp Dener 
5725e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
5735e9b73cbSAlp Dener {
5745e9b73cbSAlp Dener   PetscErrorCode               ierr;
5755e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
5765e9b73cbSAlp Dener 
5775e9b73cbSAlp Dener   PetscFunctionBegin;
5785e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
57989da521bSAlp Dener   if (bnk->active_idx){
5805e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5815e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5825e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5835e9b73cbSAlp Dener   } else {
5845e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
5855e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
5865e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
5875e9b73cbSAlp Dener   }
5885e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
5895e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
5905e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
59133c78596SAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);CHKERRQ(ierr);
5925e9b73cbSAlp Dener   /* Restore the sub vectors */
59389da521bSAlp Dener   if (bnk->active_idx){
5945e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5955e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
5965e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5975e9b73cbSAlp Dener   }
5985e9b73cbSAlp Dener   PetscFunctionReturn(0);
5995e9b73cbSAlp Dener }
6005e9b73cbSAlp Dener 
6015e9b73cbSAlp Dener /*------------------------------------------------------------*/
6025e9b73cbSAlp Dener 
60362675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
60462675beeSAlp Dener 
60562675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
60662675beeSAlp Dener    in the event that the Newton step fails the test.
60762675beeSAlp Dener */
60862675beeSAlp Dener 
609e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
610e465cd6fSAlp Dener {
611e465cd6fSAlp Dener   PetscErrorCode               ierr;
612e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
613e465cd6fSAlp Dener 
614e465cd6fSAlp Dener   PetscReal                    gdx, delta, e_min;
615e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
616e465cd6fSAlp Dener 
617e465cd6fSAlp Dener   PetscFunctionBegin;
618080d2917SAlp Dener   ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
619eb910715SAlp Dener   if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
620eb910715SAlp Dener     /* Newton step is not descent or direction produced Inf or NaN
621eb910715SAlp Dener        Update the perturbation for next time */
622eb910715SAlp Dener     if (bnk->pert <= 0.0) {
623eb910715SAlp Dener       /* Initialize the perturbation */
624eb910715SAlp Dener       bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
625eb910715SAlp Dener       if (bnk->is_gltr) {
626eb910715SAlp Dener         ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
627eb910715SAlp Dener         bnk->pert = PetscMax(bnk->pert, -e_min);
628eb910715SAlp Dener       }
629eb910715SAlp Dener     } else {
630eb910715SAlp Dener       /* Increase the perturbation */
631eb910715SAlp Dener       bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
632eb910715SAlp Dener     }
633eb910715SAlp Dener 
634*b9ac7092SAlp Dener     if (bnk->M) {
635eb910715SAlp Dener       /* We don't have the bfgs matrix around and updated
636eb910715SAlp Dener          Must use gradient direction in this case */
637080d2917SAlp Dener       ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
638eb910715SAlp Dener       *stepType = BNK_GRADIENT;
639eb910715SAlp Dener     } else {
640eb910715SAlp Dener       /* Attempt to use the BFGS direction */
641cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
642eb910715SAlp Dener 
6438d5ead36SAlp Dener       /* Check for success (descent direction)
6448d5ead36SAlp Dener          NOTE: Negative gdx here means not a descent direction because
6458d5ead36SAlp Dener          the fall-back step is missing a negative sign. */
646080d2917SAlp Dener       ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
6473105154fSTodd Munson       if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
648eb910715SAlp Dener         /* BFGS direction is not descent or direction produced not a number
649eb910715SAlp Dener            We can assert bfgsUpdates > 1 in this case because
650eb910715SAlp Dener            the first solve produces the scaled gradient direction,
651eb910715SAlp Dener            which is guaranteed to be descent */
652eb910715SAlp Dener 
653eb910715SAlp Dener         /* Use steepest descent direction (scaled) */
6549b6ef848SAlp Dener         delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
655cd929ea3SAlp Dener         ierr = MatLMVMSetJ0Scale(bnk->M, delta);CHKERRQ(ierr);
656cd929ea3SAlp Dener         ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
65709164190SAlp Dener         ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
658cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
659eb910715SAlp Dener 
660eb910715SAlp Dener         *stepType = BNK_SCALED_GRADIENT;
661eb910715SAlp Dener       } else {
662cd929ea3SAlp Dener         ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
663eb910715SAlp Dener         if (1 == bfgsUpdates) {
664eb910715SAlp Dener           /* The first BFGS direction is always the scaled gradient */
665eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
666eb910715SAlp Dener         } else {
667eb910715SAlp Dener           *stepType = BNK_BFGS;
668eb910715SAlp Dener         }
669eb910715SAlp Dener       }
670eb910715SAlp Dener     }
6718d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
6728d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
673a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
674eb910715SAlp Dener   } else {
675eb910715SAlp Dener     /* Computed Newton step is descent */
676eb910715SAlp Dener     switch (ksp_reason) {
677eb910715SAlp Dener     case KSP_DIVERGED_NANORINF:
678eb910715SAlp Dener     case KSP_DIVERGED_BREAKDOWN:
679eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_MAT:
680eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_PC:
681eb910715SAlp Dener     case KSP_CONVERGED_CG_NEG_CURVE:
682eb910715SAlp Dener       /* Matrix or preconditioner is indefinite; increase perturbation */
683eb910715SAlp Dener       if (bnk->pert <= 0.0) {
684eb910715SAlp Dener         /* Initialize the perturbation */
685eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
686eb910715SAlp Dener         if (bnk->is_gltr) {
687eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
688eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
689eb910715SAlp Dener         }
690eb910715SAlp Dener       } else {
691eb910715SAlp Dener         /* Increase the perturbation */
692eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
693eb910715SAlp Dener       }
694eb910715SAlp Dener       break;
695eb910715SAlp Dener 
696eb910715SAlp Dener     default:
697eb910715SAlp Dener       /* Newton step computation is good; decrease perturbation */
698eb910715SAlp Dener       bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
699eb910715SAlp Dener       if (bnk->pert < bnk->pmin) {
700eb910715SAlp Dener         bnk->pert = 0.0;
701eb910715SAlp Dener       }
702eb910715SAlp Dener       break;
703eb910715SAlp Dener     }
704fed79b8eSAlp Dener     *stepType = BNK_NEWTON;
705eb910715SAlp Dener   }
706eb910715SAlp Dener   PetscFunctionReturn(0);
707eb910715SAlp Dener }
708eb910715SAlp Dener 
709df278d8fSAlp Dener /*------------------------------------------------------------*/
710df278d8fSAlp Dener 
711df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
712df278d8fSAlp Dener 
713df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
714df278d8fSAlp Dener   Newton step does not produce a valid step length.
715df278d8fSAlp Dener */
716df278d8fSAlp Dener 
717937a31a1SAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt *stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
718c14b763aSAlp Dener {
719c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
720c14b763aSAlp Dener   PetscErrorCode ierr;
721c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
722c14b763aSAlp Dener 
723c14b763aSAlp Dener   PetscReal      e_min, gdx, delta;
724c14b763aSAlp Dener   PetscInt       bfgsUpdates;
725c14b763aSAlp Dener 
726c14b763aSAlp Dener   PetscFunctionBegin;
727c14b763aSAlp Dener   /* Perform the linesearch */
728c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
729c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
730c14b763aSAlp Dener 
731937a31a1SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && *stepType != BNK_GRADIENT) {
732c14b763aSAlp Dener     /* Linesearch failed, revert solution */
733c14b763aSAlp Dener     bnk->f = bnk->fold;
734c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
735c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
736c14b763aSAlp Dener 
737937a31a1SAlp Dener     switch(*stepType) {
738c14b763aSAlp Dener     case BNK_NEWTON:
7398d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
740c14b763aSAlp Dener          Update the perturbation for next time */
741c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
742c14b763aSAlp Dener         /* Initialize the perturbation */
743c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
744c14b763aSAlp Dener         if (bnk->is_gltr) {
745c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
746c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
747c14b763aSAlp Dener         }
748c14b763aSAlp Dener       } else {
749c14b763aSAlp Dener         /* Increase the perturbation */
750c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
751c14b763aSAlp Dener       }
752c14b763aSAlp Dener 
753*b9ac7092SAlp Dener       if (bnk->M) {
754c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
755c14b763aSAlp Dener            Must use gradient direction in this case */
756937a31a1SAlp Dener         ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
757937a31a1SAlp Dener         *stepType = BNK_GRADIENT;
758c14b763aSAlp Dener       } else {
759c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
760cd929ea3SAlp Dener         ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
7618d5ead36SAlp Dener         /* Check for success (descent direction)
7628d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
763c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
7643105154fSTodd Munson         if ((gdx <= 0.0) || PetscIsInfOrNanReal(gdx)) {
765c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
766c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
767c14b763aSAlp Dener              Use steepest descent direction (scaled) */
7689b6ef848SAlp Dener           delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
769cd929ea3SAlp Dener           ierr = MatLMVMSetJ0Scale(bnk->M, delta);CHKERRQ(ierr);
770cd929ea3SAlp Dener           ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
771c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
772cd929ea3SAlp Dener           ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
773c14b763aSAlp Dener 
774c14b763aSAlp Dener           bfgsUpdates = 1;
775937a31a1SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
776c14b763aSAlp Dener         } else {
777cd929ea3SAlp Dener           ierr = MatLMVMGetUpdateCount(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
778c14b763aSAlp Dener           if (1 == bfgsUpdates) {
779c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
780937a31a1SAlp Dener             *stepType = BNK_SCALED_GRADIENT;
781c14b763aSAlp Dener           } else {
782937a31a1SAlp Dener             *stepType = BNK_BFGS;
783c14b763aSAlp Dener           }
784c14b763aSAlp Dener         }
785c14b763aSAlp Dener       }
786c14b763aSAlp Dener       break;
787c14b763aSAlp Dener 
788c14b763aSAlp Dener     case BNK_BFGS:
789c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
790c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
791c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
7929b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
793cd929ea3SAlp Dener       ierr = MatLMVMSetJ0Scale(bnk->M, delta);CHKERRQ(ierr);
794cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
795c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
796cd929ea3SAlp Dener       ierr = MatSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
797c14b763aSAlp Dener 
798c14b763aSAlp Dener       bfgsUpdates = 1;
799937a31a1SAlp Dener       *stepType = BNK_SCALED_GRADIENT;
800c14b763aSAlp Dener       break;
801c14b763aSAlp Dener 
802c14b763aSAlp Dener     case BNK_SCALED_GRADIENT:
803c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
804c14b763aSAlp Dener          The scaled gradient step did not produce a new iterate;
805937a31a1SAlp Dener          reset the BFGS matrix and attemp to use the gradient direction. */
806cd929ea3SAlp Dener       ierr = MatLMVMSetJ0Scale(bnk->M,1.0);CHKERRQ(ierr);
807cd929ea3SAlp Dener       ierr = MatLMVMReset(bnk->M, PETSC_FALSE);CHKERRQ(ierr);
808c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
809937a31a1SAlp Dener       ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
810c14b763aSAlp Dener 
811c14b763aSAlp Dener       bfgsUpdates = 1;
812937a31a1SAlp Dener       *stepType = BNK_GRADIENT;
813c14b763aSAlp Dener       break;
814c14b763aSAlp Dener     }
8158d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
8168d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
817a1318120SAlp Dener     ierr = TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection);CHKERRQ(ierr);
818c14b763aSAlp Dener 
8198d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
820c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
821c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
822c14b763aSAlp Dener   }
823c14b763aSAlp Dener   *reason = ls_reason;
824c14b763aSAlp Dener   PetscFunctionReturn(0);
825c14b763aSAlp Dener }
826c14b763aSAlp Dener 
827df278d8fSAlp Dener /*------------------------------------------------------------*/
828df278d8fSAlp Dener 
829df278d8fSAlp Dener /* Routine for updating the trust radius.
830df278d8fSAlp Dener 
831df278d8fSAlp Dener   Function features three different update methods:
832df278d8fSAlp Dener   1) Line-search step length based
833df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
834df278d8fSAlp Dener   3) Interpolation
835df278d8fSAlp Dener */
836df278d8fSAlp Dener 
83728017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
838080d2917SAlp Dener {
839080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
840080d2917SAlp Dener   PetscErrorCode ierr;
841080d2917SAlp Dener 
842b1c2d0e3SAlp Dener   PetscReal      step, kappa;
843080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
844080d2917SAlp Dener 
845080d2917SAlp Dener   PetscFunctionBegin;
846080d2917SAlp Dener   /* Update trust region radius */
847080d2917SAlp Dener   *accept = PETSC_FALSE;
84828017e9fSAlp Dener   switch(updateType) {
849080d2917SAlp Dener   case BNK_UPDATE_STEP:
850c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
851080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
852080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
853080d2917SAlp Dener       if (step < bnk->nu1) {
854080d2917SAlp Dener         /* Very bad step taken; reduce radius */
855080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
856080d2917SAlp Dener       } else if (step < bnk->nu2) {
857080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
858080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
859080d2917SAlp Dener       } else if (step < bnk->nu3) {
860080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
861080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
862080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
863080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
864080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
865080d2917SAlp Dener         }
866080d2917SAlp Dener       } else if (step < bnk->nu4) {
867080d2917SAlp Dener         /*  Full step taken; increase the radius */
868080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
869080d2917SAlp Dener       } else {
870080d2917SAlp Dener         /*  More than full step taken; increase the radius */
871080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
872080d2917SAlp Dener       }
873080d2917SAlp Dener     } else {
874080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
875080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
876080d2917SAlp Dener     }
877080d2917SAlp Dener     break;
878080d2917SAlp Dener 
879080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
880080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
881b1c2d0e3SAlp Dener       if (prered < 0.0) {
882fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
883fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
884fed79b8eSAlp Dener            be rejected! */
885080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
8863105154fSTodd Munson       } else {
887b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
888080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
889080d2917SAlp Dener         } else {
8903105154fSTodd Munson           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) && (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
891080d2917SAlp Dener             kappa = 1.0;
8923105154fSTodd Munson           } else {
893080d2917SAlp Dener             kappa = actred / prered;
894080d2917SAlp Dener           }
895fed79b8eSAlp Dener 
896fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
897080d2917SAlp Dener           if (kappa < bnk->eta1) {
898fed79b8eSAlp Dener             /* Reject the step */
899080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
9003105154fSTodd Munson           } else {
901fed79b8eSAlp Dener             /* Accept the step */
902c133c014SAlp Dener             *accept = PETSC_TRUE;
903c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
9048d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
905080d2917SAlp Dener               if (kappa < bnk->eta2) {
906080d2917SAlp Dener                 /* Marginal bad step */
907c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
9083105154fSTodd Munson               } else if (kappa < bnk->eta3) {
909fed79b8eSAlp Dener                 /* Reasonable step */
910fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
9113105154fSTodd Munson               } else if (kappa < bnk->eta4) {
912080d2917SAlp Dener                 /* Good step */
913c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
9143105154fSTodd Munson               } else {
915080d2917SAlp Dener                 /* Very good step */
916c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
917080d2917SAlp Dener               }
918c133c014SAlp Dener             }
919080d2917SAlp Dener           }
920080d2917SAlp Dener         }
921080d2917SAlp Dener       }
922080d2917SAlp Dener     } else {
923080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
924080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
925080d2917SAlp Dener     }
926080d2917SAlp Dener     break;
927080d2917SAlp Dener 
928080d2917SAlp Dener   default:
929080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
930b1c2d0e3SAlp Dener       if (prered < 0.0) {
931080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
932080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
933080d2917SAlp Dener         /*  be rejected! */
934080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
935080d2917SAlp Dener       } else {
936b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
937080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
938080d2917SAlp Dener         } else {
939080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
940080d2917SAlp Dener             kappa = 1.0;
941080d2917SAlp Dener           } else {
942080d2917SAlp Dener             kappa = actred / prered;
943080d2917SAlp Dener           }
944080d2917SAlp Dener 
945080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
946080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
947080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
948080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
949080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
950080d2917SAlp Dener 
951080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
952080d2917SAlp Dener             /*  Great agreement */
953080d2917SAlp Dener             *accept = PETSC_TRUE;
954080d2917SAlp Dener             if (tau_max < 1.0) {
955080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
956080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
957080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
958080d2917SAlp Dener             } else {
959080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
960080d2917SAlp Dener             }
961080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
962080d2917SAlp Dener             /*  Good agreement */
963080d2917SAlp Dener             *accept = PETSC_TRUE;
964080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
965080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
966080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
967080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
968080d2917SAlp Dener             } else if (tau_max < 1.0) {
969080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
970080d2917SAlp Dener             } else {
971080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
972080d2917SAlp Dener             }
973080d2917SAlp Dener           } else {
974080d2917SAlp Dener             /*  Not good agreement */
975080d2917SAlp Dener             if (tau_min > 1.0) {
976080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
977080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
978080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
979080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
980080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
981080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
982080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
983080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
984080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
985080d2917SAlp Dener             } else {
986080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
987080d2917SAlp Dener             }
988080d2917SAlp Dener           }
989080d2917SAlp Dener         }
990080d2917SAlp Dener       }
991080d2917SAlp Dener     } else {
992080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
993080d2917SAlp Dener       tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust);
994080d2917SAlp Dener     }
99528017e9fSAlp Dener     break;
996080d2917SAlp Dener   }
997c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
998c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
999fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
1000080d2917SAlp Dener   PetscFunctionReturn(0);
1001080d2917SAlp Dener }
1002080d2917SAlp Dener 
1003eb910715SAlp Dener /* ---------------------------------------------------------- */
1004df278d8fSAlp Dener 
100562675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
100662675beeSAlp Dener {
100762675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
100862675beeSAlp Dener 
100962675beeSAlp Dener   PetscFunctionBegin;
101062675beeSAlp Dener   switch (stepType) {
101162675beeSAlp Dener   case BNK_NEWTON:
101262675beeSAlp Dener     ++bnk->newt;
101362675beeSAlp Dener     break;
101462675beeSAlp Dener   case BNK_BFGS:
101562675beeSAlp Dener     ++bnk->bfgs;
101662675beeSAlp Dener     break;
101762675beeSAlp Dener   case BNK_SCALED_GRADIENT:
101862675beeSAlp Dener     ++bnk->sgrad;
101962675beeSAlp Dener     break;
102062675beeSAlp Dener   case BNK_GRADIENT:
102162675beeSAlp Dener     ++bnk->grad;
102262675beeSAlp Dener     break;
102362675beeSAlp Dener   default:
102462675beeSAlp Dener     break;
102562675beeSAlp Dener   }
102662675beeSAlp Dener   PetscFunctionReturn(0);
102762675beeSAlp Dener }
102862675beeSAlp Dener 
102962675beeSAlp Dener /* ---------------------------------------------------------- */
103062675beeSAlp Dener 
10319b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
1032eb910715SAlp Dener {
1033eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1034eb910715SAlp Dener   PetscErrorCode ierr;
10359b6ef848SAlp Dener   KSPType        ksp_type;
1036e031d6f5SAlp Dener   PetscInt       i;
1037eb910715SAlp Dener 
1038eb910715SAlp Dener   PetscFunctionBegin;
1039c4b75bccSAlp Dener   if (!tao->gradient) {
1040c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);
1041c4b75bccSAlp Dener   }
1042c4b75bccSAlp Dener   if (!tao->stepdirection) {
1043c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);
1044c4b75bccSAlp Dener   }
1045c4b75bccSAlp Dener   if (!bnk->W) {
1046c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);
1047c4b75bccSAlp Dener   }
1048c4b75bccSAlp Dener   if (!bnk->Xold) {
1049c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);
1050c4b75bccSAlp Dener   }
1051c4b75bccSAlp Dener   if (!bnk->Gold) {
1052c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);
1053c4b75bccSAlp Dener   }
1054c4b75bccSAlp Dener   if (!bnk->Xwork) {
1055c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);
1056c4b75bccSAlp Dener   }
1057c4b75bccSAlp Dener   if (!bnk->Gwork) {
1058c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);
1059c4b75bccSAlp Dener   }
1060c4b75bccSAlp Dener   if (!bnk->unprojected_gradient) {
1061c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);
1062c4b75bccSAlp Dener   }
1063c4b75bccSAlp Dener   if (!bnk->unprojected_gradient_old) {
1064c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);
1065c4b75bccSAlp Dener   }
1066c4b75bccSAlp Dener   if (!bnk->Diag_min) {
1067c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);
1068c4b75bccSAlp Dener   }
1069c4b75bccSAlp Dener   if (!bnk->Diag_max) {
1070c4b75bccSAlp Dener     ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);
1071c4b75bccSAlp Dener   }
1072e031d6f5SAlp Dener   if (bnk->max_cg_its > 0) {
1073c4b75bccSAlp Dener     /* Ensure that the important common vectors are shared between BNK and embedded BNCG */
1074c4b75bccSAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
107589da521bSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient_old));CHKERRQ(ierr);
107689da521bSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient_old);CHKERRQ(ierr);
107789da521bSAlp Dener     bnk->bncg_ctx->unprojected_gradient_old = bnk->unprojected_gradient_old;
1078c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->unprojected_gradient));CHKERRQ(ierr);
1079c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
1080c4b75bccSAlp Dener     bnk->bncg_ctx->unprojected_gradient = bnk->unprojected_gradient;
1081c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(bnk->Gold));CHKERRQ(ierr);
1082c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg_ctx->G_old);CHKERRQ(ierr);
1083c4b75bccSAlp Dener     bnk->bncg_ctx->G_old = bnk->Gold;
1084c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->gradient));CHKERRQ(ierr);
1085c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->gradient);CHKERRQ(ierr);
1086c4b75bccSAlp Dener     bnk->bncg->gradient = tao->gradient;
1087c4b75bccSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->stepdirection));CHKERRQ(ierr);
1088c4b75bccSAlp Dener     ierr = VecDestroy(&bnk->bncg->stepdirection);CHKERRQ(ierr);
1089c4b75bccSAlp Dener     bnk->bncg->stepdirection = tao->stepdirection;
1090c4b75bccSAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, tao->solution);CHKERRQ(ierr);
1091c4b75bccSAlp Dener     /* Copy over some settings from BNK into BNCG */
1092e031d6f5SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
1093e031d6f5SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
1094e031d6f5SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
1095937a31a1SAlp Dener     ierr = TaoSetConvergenceTest(bnk->bncg, tao->ops->convergencetest, tao->cnvP);CHKERRQ(ierr);
1096e031d6f5SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
1097e031d6f5SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
1098e031d6f5SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
1099e031d6f5SAlp Dener     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr);
1100c4b75bccSAlp Dener     for (i=0; i<tao->numbermonitors; ++i) {
1101e031d6f5SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
1102e031d6f5SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
1103e031d6f5SAlp Dener     }
1104e031d6f5SAlp Dener   }
1105c0f10754SAlp Dener   bnk->X_inactive = 0;
1106c0f10754SAlp Dener   bnk->G_inactive = 0;
110762675beeSAlp Dener   bnk->inactive_work = 0;
110862675beeSAlp Dener   bnk->active_work = 0;
110962675beeSAlp Dener   bnk->inactive_idx = 0;
111062675beeSAlp Dener   bnk->active_idx = 0;
111162675beeSAlp Dener   bnk->active_lower = 0;
111262675beeSAlp Dener   bnk->active_upper = 0;
111362675beeSAlp Dener   bnk->active_fixed = 0;
1114eb910715SAlp Dener   bnk->M = 0;
111509164190SAlp Dener   bnk->H_inactive = 0;
111609164190SAlp Dener   bnk->Hpre_inactive = 0;
11179b6ef848SAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
11189b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
11199b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
11209b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1121eb910715SAlp Dener   PetscFunctionReturn(0);
1122eb910715SAlp Dener }
1123eb910715SAlp Dener 
1124eb910715SAlp Dener /*------------------------------------------------------------*/
1125df278d8fSAlp Dener 
1126eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao)
1127eb910715SAlp Dener {
1128eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1129eb910715SAlp Dener   PetscErrorCode ierr;
1130eb910715SAlp Dener 
1131eb910715SAlp Dener   PetscFunctionBegin;
1132eb910715SAlp Dener   if (tao->setupcalled) {
1133eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1134eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1135eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
113609164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
113709164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
113809164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
113909164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
114062675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
114162675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1142c4b75bccSAlp Dener   }
1143ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_lower);CHKERRQ(ierr);
1144ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_upper);CHKERRQ(ierr);
1145ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_fixed);CHKERRQ(ierr);
1146ca964c49SAlp Dener   ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
1147ca964c49SAlp Dener   ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
1148c4b75bccSAlp Dener   if (bnk->Hpre_inactive != tao->hessian_pre && bnk->Hpre_inactive != bnk->H_inactive) {
1149c4b75bccSAlp Dener     ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);
1150c4b75bccSAlp Dener   }
1151c4b75bccSAlp Dener   if (bnk->H_inactive != tao->hessian) {
1152c4b75bccSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);
1153c4b75bccSAlp Dener   }
1154ca964c49SAlp Dener   ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1155eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1156eb910715SAlp Dener   PetscFunctionReturn(0);
1157eb910715SAlp Dener }
1158eb910715SAlp Dener 
1159eb910715SAlp Dener /*------------------------------------------------------------*/
1160df278d8fSAlp Dener 
1161eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1162eb910715SAlp Dener {
1163eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1164eb910715SAlp Dener   PetscErrorCode ierr;
1165eb910715SAlp Dener 
1166eb910715SAlp Dener   PetscFunctionBegin;
1167eb910715SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr);
11688d5ead36SAlp 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);
11698d5ead36SAlp 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);
11702f75a4aaSAlp 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);
1171748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "(developer) Hessian perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
1172748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "(developer) minimum initial Hessian perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
1173748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "(developer) maximum initial Hessian perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
1174748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "(developer) initial merit factor for Hessian perturbation", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
1175748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "(developer) minimum Hessian perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
1176748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "(developer) maximum Hessian perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
1177748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "(developer) Hessian perturbation growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
1178748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "(developer) Hessian perturbation shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
1179748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "(developer) merit growth factor for Hessian perturbation", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
1180748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "(developer) merit shrink factor for Hessian perturbation", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
1181748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "(developer) threshold for rejecting step (-tao_bnk_update_type reduction)", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
1182748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "(developer) threshold for accepting marginal step (-tao_bnk_update_type reduction)", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
1183748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "(developer) threshold for accepting reasonable step (-tao_bnk_update_type reduction)", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
1184748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "(developer) threshold for accepting good step (-tao_bnk_update_type reduction)", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
1185748696b1SAlp 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);
1186748696b1SAlp 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);
1187748696b1SAlp 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);
1188748696b1SAlp 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);
1189748696b1SAlp 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);
1190748696b1SAlp 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);
1191748696b1SAlp 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);
1192748696b1SAlp 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);
1193748696b1SAlp 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);
1194748696b1SAlp 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);
1195748696b1SAlp 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);
1196748696b1SAlp 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);
1197748696b1SAlp 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);
1198748696b1SAlp 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);
1199748696b1SAlp 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);
1200748696b1SAlp 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);
1201748696b1SAlp 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);
1202748696b1SAlp 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);
1203748696b1SAlp 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);
1204748696b1SAlp 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);
1205748696b1SAlp 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);
1206748696b1SAlp 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);
1207748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "(developer) threshold for accepting good step (-tao_bnk_update_type interpolation)", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
1208748696b1SAlp 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);
1209748696b1SAlp 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);
1210748696b1SAlp 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);
1211748696b1SAlp 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);
1212748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "(developer) trust region interpolation factor (-tao_bnk_update_type interpolation)", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
1213748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "(developer) lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
1214748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "(developer) upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
1215748696b1SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "(developer) tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
1216748696b1SAlp 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);
1217748696b1SAlp 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);
1218c0f10754SAlp 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);
1219eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
122033c78596SAlp Dener   ierr = TaoSetFromOptions(bnk->bncg);CHKERRQ(ierr);
1221eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1222eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1223eb910715SAlp Dener   PetscFunctionReturn(0);
1224eb910715SAlp Dener }
1225eb910715SAlp Dener 
1226eb910715SAlp Dener /*------------------------------------------------------------*/
1227df278d8fSAlp Dener 
1228eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1229eb910715SAlp Dener {
1230eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1231eb910715SAlp Dener   PetscInt       nrejects;
1232eb910715SAlp Dener   PetscBool      isascii;
1233eb910715SAlp Dener   PetscErrorCode ierr;
1234eb910715SAlp Dener 
1235eb910715SAlp Dener   PetscFunctionBegin;
1236eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1237eb910715SAlp Dener   if (isascii) {
1238eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1239*b9ac7092SAlp Dener     if (bnk->M) {
1240cd929ea3SAlp Dener       ierr = MatLMVMGetRejectCount(bnk->M,&nrejects);CHKERRQ(ierr);
1241*b9ac7092SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected BFGS updates: %D\n",nrejects);CHKERRQ(ierr);
1242eb910715SAlp Dener     }
1243e031d6f5SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr);
1244eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1245*b9ac7092SAlp Dener     if (bnk->M) {
1246eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1247*b9ac7092SAlp Dener     }
1248eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1249eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1250eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1251eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1252eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1253eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1254eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1255eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1256eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1257eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1258eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1259eb910715SAlp Dener   }
1260eb910715SAlp Dener   PetscFunctionReturn(0);
1261eb910715SAlp Dener }
1262eb910715SAlp Dener 
1263eb910715SAlp Dener /* ---------------------------------------------------------- */
1264df278d8fSAlp Dener 
1265eb910715SAlp Dener /*MC
1266eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
126766ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1268eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1269eb910715SAlp Dener               Hk dk = -gk
12702b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12712b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1272eb910715SAlp Dener 
1273eb910715SAlp Dener     Options Database Keys:
1274748696b1SAlp Dener + -tao_max_cg_its - maximum number of bounded conjugate-gradient iterations taken in each Newton loop
1275748696b1SAlp Dener . -tao_bnk_pc_type - preconditioner type ("none", "ahess", "bfgs", "petsc")
12763cb832f1SAlp Dener . -tao_bnk_bfgs_scale_type - BFGS preconditioner diagonal scaling type ("ahess", "phess", "bfgs")
12773cb832f1SAlp Dener . -tao_bnk_init_type - trust radius initialization method ("constant", "direction", "interpolation")
12783cb832f1SAlp Dener . -tao_bnk_update_type - trust radius update method ("step", "direction", "interpolation")
12793cb832f1SAlp Dener . -tao_bnk_as_type - active-set estimation method ("none", "bertsekas")
1280748696b1SAlp Dener . -tao_bnk_as_tol - (developer) initial tolerance used in estimating bounded active variables (-tao_bnk_as_type bertsekas)
1281748696b1SAlp Dener . -tao_bnk_as_step - (developer) trial step length used in estimating bounded active variables (-tao_bnk_as_type bertsekas)
1282748696b1SAlp Dener . -tao_bnk_sval - (developer) Hessian perturbation starting value
1283748696b1SAlp Dener . -tao_bnk_imin - (developer) minimum initial Hessian perturbation
1284748696b1SAlp Dener . -tao_bnk_imax - (developer) maximum initial Hessian perturbation
1285748696b1SAlp Dener . -tao_bnk_pmin - (developer) minimum Hessian perturbation
1286748696b1SAlp Dener . -tao_bnk_pmax - (developer) aximum Hessian perturbation
1287748696b1SAlp Dener . -tao_bnk_pgfac - (developer) Hessian perturbation growth factor
1288748696b1SAlp Dener . -tao_bnk_psfac - (developer) Hessian perturbation shrink factor
1289748696b1SAlp Dener . -tao_bnk_imfac - (developer) initial merit factor for Hessian perturbation
1290748696b1SAlp Dener . -tao_bnk_pmgfac - (developer) merit growth factor for Hessian perturbation
1291748696b1SAlp Dener . -tao_bnk_pmsfac - (developer) merit shrink factor for Hessian perturbation
1292748696b1SAlp Dener . -tao_bnk_eta1 - (developer) threshold for rejecting step (-tao_bnk_update_type reduction)
1293748696b1SAlp Dener . -tao_bnk_eta2 - (developer) threshold for accepting marginal step (-tao_bnk_update_type reduction)
1294748696b1SAlp Dener . -tao_bnk_eta3 - (developer) threshold for accepting reasonable step (-tao_bnk_update_type reduction)
1295748696b1SAlp Dener . -tao_bnk_eta4 - (developer) threshold for accepting good step (-tao_bnk_update_type reduction)
1296748696b1SAlp Dener . -tao_bnk_alpha1 - (developer) radius reduction factor for rejected step (-tao_bnk_update_type reduction)
1297748696b1SAlp Dener . -tao_bnk_alpha2 - (developer) radius reduction factor for marginally accepted bad step (-tao_bnk_update_type reduction)
1298748696b1SAlp Dener . -tao_bnk_alpha3 - (developer) radius increase factor for reasonable accepted step (-tao_bnk_update_type reduction)
1299748696b1SAlp Dener . -tao_bnk_alpha4 - (developer) radius increase factor for good accepted step (-tao_bnk_update_type reduction)
1300748696b1SAlp Dener . -tao_bnk_alpha5 - (developer) radius increase factor for very good accepted step (-tao_bnk_update_type reduction)
1301748696b1SAlp Dener . -tao_bnk_epsilon - (developer) tolerance for small pred/actual ratios that trigger automatic step acceptance (-tao_bnk_update_type reduction)
1302748696b1SAlp Dener . -tao_bnk_mu1 - (developer) threshold for accepting very good step (-tao_bnk_update_type interpolation)
1303748696b1SAlp Dener . -tao_bnk_mu2 - (developer) threshold for accepting good step (-tao_bnk_update_type interpolation)
1304748696b1SAlp Dener . -tao_bnk_gamma1 - (developer) radius reduction factor for rejected very bad step (-tao_bnk_update_type interpolation)
1305748696b1SAlp Dener . -tao_bnk_gamma2 - (developer) radius reduction factor for rejected bad step (-tao_bnk_update_type interpolation)
1306748696b1SAlp Dener . -tao_bnk_gamma3 - (developer) radius increase factor for accepted good step (-tao_bnk_update_type interpolation)
1307748696b1SAlp Dener . -tao_bnk_gamma4 - (developer) radius increase factor for accepted very good step (-tao_bnk_update_type interpolation)
1308748696b1SAlp Dener . -tao_bnk_theta - (developer) trust region interpolation factor (-tao_bnk_update_type interpolation)
1309748696b1SAlp Dener . -tao_bnk_nu1 - (developer) threshold for small line-search step length (-tao_bnk_update_type step)
1310748696b1SAlp Dener . -tao_bnk_nu2 - (developer) threshold for reasonable line-search step length (-tao_bnk_update_type step)
1311748696b1SAlp Dener . -tao_bnk_nu3 - (developer) threshold for large line-search step length (-tao_bnk_update_type step)
1312748696b1SAlp Dener . -tao_bnk_nu4 - (developer) threshold for very large line-search step length (-tao_bnk_update_type step)
1313748696b1SAlp Dener . -tao_bnk_omega1 - (developer) radius reduction factor for very small line-search step length (-tao_bnk_update_type step)
1314748696b1SAlp Dener . -tao_bnk_omega2 - (developer) radius reduction factor for small line-search step length (-tao_bnk_update_type step)
1315748696b1SAlp Dener . -tao_bnk_omega3 - (developer) radius factor for decent line-search step length (-tao_bnk_update_type step)
1316748696b1SAlp Dener . -tao_bnk_omega4 - (developer) radius increase factor for large line-search step length (-tao_bnk_update_type step)
1317748696b1SAlp Dener . -tao_bnk_omega5 - (developer) radius increase factor for very large line-search step length (-tao_bnk_update_type step)
1318748696b1SAlp Dener . -tao_bnk_mu1_i -  (developer) threshold for accepting very good step (-tao_bnk_init_type interpolation)
1319748696b1SAlp Dener . -tao_bnk_mu2_i -  (developer) threshold for accepting good step (-tao_bnk_init_type interpolation)
1320748696b1SAlp Dener . -tao_bnk_gamma1_i - (developer) radius reduction factor for rejected very bad step (-tao_bnk_init_type interpolation)
1321748696b1SAlp Dener . -tao_bnk_gamma2_i - (developer) radius reduction factor for rejected bad step (-tao_bnk_init_type interpolation)
1322748696b1SAlp Dener . -tao_bnk_gamma3_i - (developer) radius increase factor for accepted good step (-tao_bnk_init_type interpolation)
1323748696b1SAlp Dener . -tao_bnk_gamma4_i - (developer) radius increase factor for accepted very good step (-tao_bnk_init_type interpolation)
1324748696b1SAlp Dener - -tao_bnk_theta_i - (developer) trust region interpolation factor (-tao_bnk_init_type interpolation)
1325eb910715SAlp Dener 
1326eb910715SAlp Dener   Level: beginner
1327eb910715SAlp Dener M*/
1328eb910715SAlp Dener 
1329eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1330eb910715SAlp Dener {
1331eb910715SAlp Dener   TAO_BNK        *bnk;
1332eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1333eb910715SAlp Dener   PetscErrorCode ierr;
1334*b9ac7092SAlp Dener   PC             pc;
1335eb910715SAlp Dener 
1336eb910715SAlp Dener   PetscFunctionBegin;
1337eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1338eb910715SAlp Dener 
1339eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1340eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1341eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1342eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1343eb910715SAlp Dener 
1344eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1345eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1346eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1347eb910715SAlp Dener 
1348eb910715SAlp Dener   tao->data = (void*)bnk;
1349eb910715SAlp Dener 
135066ed3702SAlp Dener   /*  Hessian shifting parameters */
1351eb910715SAlp Dener   bnk->sval   = 0.0;
1352eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1353eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1354eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1355eb910715SAlp Dener 
1356eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1357eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1358eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1359eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1360eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1361eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1362eb910715SAlp Dener 
1363eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1364eb910715SAlp Dener   bnk->nu1 = 0.25;
1365eb910715SAlp Dener   bnk->nu2 = 0.50;
1366eb910715SAlp Dener   bnk->nu3 = 1.00;
1367eb910715SAlp Dener   bnk->nu4 = 1.25;
1368eb910715SAlp Dener 
1369eb910715SAlp Dener   bnk->omega1 = 0.25;
1370eb910715SAlp Dener   bnk->omega2 = 0.50;
1371eb910715SAlp Dener   bnk->omega3 = 1.00;
1372eb910715SAlp Dener   bnk->omega4 = 2.00;
1373eb910715SAlp Dener   bnk->omega5 = 4.00;
1374eb910715SAlp Dener 
1375eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1376eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1377eb910715SAlp Dener   bnk->eta2 = 0.25;
1378eb910715SAlp Dener   bnk->eta3 = 0.50;
1379eb910715SAlp Dener   bnk->eta4 = 0.90;
1380eb910715SAlp Dener 
1381eb910715SAlp Dener   bnk->alpha1 = 0.25;
1382eb910715SAlp Dener   bnk->alpha2 = 0.50;
1383eb910715SAlp Dener   bnk->alpha3 = 1.00;
1384eb910715SAlp Dener   bnk->alpha4 = 2.00;
1385eb910715SAlp Dener   bnk->alpha5 = 4.00;
1386eb910715SAlp Dener 
1387eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1388eb910715SAlp Dener   bnk->mu1 = 0.10;
1389eb910715SAlp Dener   bnk->mu2 = 0.50;
1390eb910715SAlp Dener 
1391eb910715SAlp Dener   bnk->gamma1 = 0.25;
1392eb910715SAlp Dener   bnk->gamma2 = 0.50;
1393eb910715SAlp Dener   bnk->gamma3 = 2.00;
1394eb910715SAlp Dener   bnk->gamma4 = 4.00;
1395eb910715SAlp Dener 
1396eb910715SAlp Dener   bnk->theta = 0.05;
1397eb910715SAlp Dener 
1398eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1399eb910715SAlp Dener   bnk->mu1_i = 0.35;
1400eb910715SAlp Dener   bnk->mu2_i = 0.50;
1401eb910715SAlp Dener 
1402eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1403eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1404eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1405eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1406eb910715SAlp Dener 
1407eb910715SAlp Dener   bnk->theta_i = 0.25;
1408eb910715SAlp Dener 
1409eb910715SAlp Dener   /*  Remaining parameters */
1410c0f10754SAlp Dener   bnk->max_cg_its = 0;
1411eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1412eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1413770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
14140a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
14150a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
141662675beeSAlp Dener   bnk->dmin = 1.0e-6;
141762675beeSAlp Dener   bnk->dmax = 1.0e6;
1418eb910715SAlp Dener 
1419*b9ac7092SAlp Dener   bnk->M               = 0;
1420*b9ac7092SAlp Dener   bnk->bfgs_pre        = 0;
1421cd929ea3SAlp Dener   bnk->bfgs_scale_type = BFGS_SCALE_AHESS;
1422eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
1423fed79b8eSAlp Dener   bnk->update_type     = BNK_UPDATE_INTERPOLATION;
14242f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1425eb910715SAlp Dener 
1426e031d6f5SAlp Dener   /* Create the embedded BNCG solver */
1427e031d6f5SAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
1428e031d6f5SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
1429e031d6f5SAlp Dener   ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr);
1430e031d6f5SAlp Dener   ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
1431e031d6f5SAlp Dener 
1432c0f10754SAlp Dener   /* Create the line search */
1433eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1434eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1435e031d6f5SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1436eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1437eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1438eb910715SAlp Dener 
1439eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1440eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1441eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1442eb910715SAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr);
1443eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1444*b9ac7092SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);
1445*b9ac7092SAlp Dener   ierr = PCSetType(pc, PCLMVM);CHKERRQ(ierr);
1446eb910715SAlp Dener   PetscFunctionReturn(0);
1447eb910715SAlp Dener }
1448