xref: /petsc/src/tao/bound/impls/bnk/bnk.c (revision c0f10754485ee18591b934b1c07ed0e16c2beadd)
1eb910715SAlp Dener #include <petsctaolinesearch.h>
2eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h>
3eb910715SAlp Dener 
4eb910715SAlp Dener #include <petscksp.h>
5eb910715SAlp Dener 
6eb910715SAlp Dener /* Routine for BFGS preconditioner */
7eb910715SAlp Dener 
8eb910715SAlp Dener PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x)
9eb910715SAlp Dener {
10eb910715SAlp Dener   PetscErrorCode ierr;
11eb910715SAlp Dener   Mat            M;
12eb910715SAlp Dener 
13eb910715SAlp Dener   PetscFunctionBegin;
14eb910715SAlp Dener   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
15eb910715SAlp Dener   PetscValidHeaderSpecific(b,VEC_CLASSID,2);
16eb910715SAlp Dener   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
17eb910715SAlp Dener   ierr = PCShellGetContext(pc,(void**)&M);CHKERRQ(ierr);
185e9b73cbSAlp Dener   ierr = MatLMVMSolve(M, b, x);CHKERRQ(ierr);
19eb910715SAlp Dener   PetscFunctionReturn(0);
20eb910715SAlp Dener }
21eb910715SAlp Dener 
22df278d8fSAlp Dener /*------------------------------------------------------------*/
23df278d8fSAlp Dener 
24df278d8fSAlp Dener /* Routine for initializing the KSP solver, the BFGS preconditioner, and the initial trust radius estimation */
25df278d8fSAlp Dener 
26*c0f10754SAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType, PetscBool *needH)
27eb910715SAlp Dener {
28eb910715SAlp Dener   PetscErrorCode               ierr;
29eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
30eb910715SAlp Dener   PC                           pc;
31eb910715SAlp Dener 
320a4511e9SAlp Dener   PetscReal                    f_min, ftrial, prered, actred, kappa, sigma;
33eb910715SAlp Dener   PetscReal                    tau, tau_1, tau_2, tau_max, tau_min, max_radius;
3428017e9fSAlp Dener   PetscReal                    delta;
35eb910715SAlp Dener 
36*c0f10754SAlp Dener   PetscInt                     n,N;
37eb910715SAlp Dener 
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);
4528017e9fSAlp Dener   ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr);
4628017e9fSAlp Dener 
4728017e9fSAlp Dener   /* Project the initial point onto the feasible region */
4828017e9fSAlp Dener   ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr);
4928017e9fSAlp Dener 
5028017e9fSAlp Dener   /* Check convergence criteria */
5128017e9fSAlp Dener   ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr);
5228017e9fSAlp Dener   ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
5328017e9fSAlp Dener   ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
5428017e9fSAlp Dener   if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN");
5528017e9fSAlp Dener 
56*c0f10754SAlp Dener   /* Test the initial point for convergence */
57*c0f10754SAlp Dener   ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
58*c0f10754SAlp Dener   ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,1.0);CHKERRQ(ierr);
59*c0f10754SAlp Dener   ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
60*c0f10754SAlp Dener   if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
61*c0f10754SAlp Dener 
62*c0f10754SAlp Dener   /* Prep the embedded BNCG algorithm */
63*c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
64*c0f10754SAlp Dener     ierr = VecCopy(tao->solution, bnk->bncg_sol);CHKERRQ(ierr);
65*c0f10754SAlp Dener     ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr);
66*c0f10754SAlp Dener     ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr);
67*c0f10754SAlp Dener     ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr);
68*c0f10754SAlp Dener 
69*c0f10754SAlp Dener     ierr = TaoSetInitialVector(bnk->bncg, bnk->bncg_sol);CHKERRQ(ierr);
70*c0f10754SAlp Dener     ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr);
71*c0f10754SAlp Dener     ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr);
72*c0f10754SAlp Dener     ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr);
73*c0f10754SAlp Dener 
74*c0f10754SAlp Dener     ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_bncg_");CHKERRQ(ierr);
75*c0f10754SAlp Dener     ierr = TaoSetVariableBounds(bnk->bncg, tao->XL, tao->XU);CHKERRQ(ierr);
76*c0f10754SAlp Dener     ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr);
77*c0f10754SAlp Dener     ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
78*c0f10754SAlp Dener     ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr);
79*c0f10754SAlp Dener     for (i=0; i<tao->numbermonitors; i++) {
80*c0f10754SAlp Dener       ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
81*c0f10754SAlp Dener       ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
82*c0f10754SAlp Dener     }
83*c0f10754SAlp Dener     ierr = TaoSetFromOptions(bnk->bncg);
84*c0f10754SAlp Dener     bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data;
85*c0f10754SAlp Dener   }
86*c0f10754SAlp Dener 
87eb910715SAlp Dener   /* Number of times ksp stopped because of these reasons */
88eb910715SAlp Dener   bnk->ksp_atol = 0;
89eb910715SAlp Dener   bnk->ksp_rtol = 0;
90eb910715SAlp Dener   bnk->ksp_dtol = 0;
91eb910715SAlp Dener   bnk->ksp_ctol = 0;
92eb910715SAlp Dener   bnk->ksp_negc = 0;
93eb910715SAlp Dener   bnk->ksp_iter = 0;
94eb910715SAlp Dener   bnk->ksp_othr = 0;
95eb910715SAlp Dener 
96fed79b8eSAlp Dener   /* Initialize the Hessian perturbation */
97fed79b8eSAlp Dener   bnk->pert = bnk->sval;
98fed79b8eSAlp Dener 
99eb910715SAlp Dener   /* Get vectors we will need */
100eb910715SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type && !bnk->M) {
101eb910715SAlp Dener     ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr);
102eb910715SAlp Dener     ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr);
103eb910715SAlp Dener     ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&bnk->M);CHKERRQ(ierr);
104eb910715SAlp Dener     ierr = MatLMVMAllocateVectors(bnk->M,tao->solution);CHKERRQ(ierr);
105eb910715SAlp Dener   }
106eb910715SAlp Dener 
107eb910715SAlp Dener   /* create vectors for the limited memory preconditioner */
108eb910715SAlp Dener   if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_BFGS != bnk->bfgs_scale_type)) {
10962675beeSAlp Dener     if (!bnk->Diag) {ierr = VecDuplicate(tao->solution,&bnk->Diag);CHKERRQ(ierr);}
1105e9b73cbSAlp Dener   }
11162675beeSAlp Dener   ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr);
11262675beeSAlp Dener   ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr);
113eb910715SAlp Dener 
114eb910715SAlp Dener   /* Modify the preconditioner to use the bfgs approximation */
115eb910715SAlp Dener   ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr);
116eb910715SAlp Dener   switch(bnk->pc_type) {
117eb910715SAlp Dener   case BNK_PC_NONE:
118eb910715SAlp Dener     ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr);
119eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
120eb910715SAlp Dener     break;
121eb910715SAlp Dener 
122eb910715SAlp Dener   case BNK_PC_AHESS:
123eb910715SAlp Dener     ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr);
124eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
125eb910715SAlp Dener     ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr);
126eb910715SAlp Dener     break;
127eb910715SAlp Dener 
128eb910715SAlp Dener   case BNK_PC_BFGS:
129eb910715SAlp Dener     ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr);
130eb910715SAlp Dener     ierr = PCSetFromOptions(pc);CHKERRQ(ierr);
131eb910715SAlp Dener     ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr);
132eb910715SAlp Dener     ierr = PCShellSetContext(pc, bnk->M);CHKERRQ(ierr);
133eb910715SAlp Dener     ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr);
134eb910715SAlp Dener     break;
135eb910715SAlp Dener 
136eb910715SAlp Dener   default:
137eb910715SAlp Dener     /* Use the pc method set by pc_type */
138eb910715SAlp Dener     break;
139eb910715SAlp Dener   }
140eb910715SAlp Dener 
141eb910715SAlp Dener   /* Initialize trust-region radius.  The initialization is only performed
142eb910715SAlp Dener      when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */
143*c0f10754SAlp Dener   *needH = PETSC_TRUE;
144eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
14562675beeSAlp Dener     switch(initType) {
146eb910715SAlp Dener     case BNK_INIT_CONSTANT:
147eb910715SAlp Dener       /* Use the initial radius specified */
148*c0f10754SAlp Dener       tao->trust = tao->trust0;
149eb910715SAlp Dener       break;
150eb910715SAlp Dener 
151eb910715SAlp Dener     case BNK_INIT_INTERPOLATION:
152*c0f10754SAlp Dener       /* Use interpolation based on the initial Hessian */
153eb910715SAlp Dener       max_radius = 0.0;
154eb910715SAlp Dener       for (j = 0; j < j_max; ++j) {
1550a4511e9SAlp Dener         f_min = bnk->f;
156eb910715SAlp Dener         sigma = 0.0;
157eb910715SAlp Dener 
158*c0f10754SAlp Dener         if (*needH) {
15962602cfbSAlp Dener           /* Compute the Hessian at the new step, and extract the inactive subsystem */
160eb910715SAlp Dener           ierr = TaoComputeHessian(tao, tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
1612ab2a32cSAlp Dener           ierr = MatDestroy(&bnk->H_inactive);
16228017e9fSAlp Dener           if (bnk->inactive_idx) {
16362602cfbSAlp Dener             ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
16462602cfbSAlp Dener             ierr = VecWhichInactive(tao->XL,tao->solution,bnk->unprojected_gradient,tao->XU,PETSC_TRUE,&bnk->inactive_idx);CHKERRQ(ierr);
1652ab2a32cSAlp Dener             ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
16628017e9fSAlp Dener           } else {
16762675beeSAlp Dener             ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);
16828017e9fSAlp Dener           }
169*c0f10754SAlp Dener           *needH = PETSC_FALSE;
170eb910715SAlp Dener         }
171eb910715SAlp Dener 
172eb910715SAlp Dener         for (i = 0; i < i_max; ++i) {
17362602cfbSAlp Dener           /* Take a steepest descent step and snap it to bounds */
17462602cfbSAlp Dener           ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr);
17562602cfbSAlp Dener           ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr);
17662602cfbSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
177770b7498SAlp Dener           /* Recompute the step after bound snapping so that it can be used in predicted decrease calculation later */
178eb910715SAlp Dener           ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr);
17962602cfbSAlp Dener           ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr);
18062602cfbSAlp Dener           /* Compute the objective at the trial */
18162602cfbSAlp Dener           ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr);
18262602cfbSAlp Dener           ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
183eb910715SAlp Dener           if (PetscIsInfOrNanReal(ftrial)) {
184eb910715SAlp Dener             tau = bnk->gamma1_i;
185eb910715SAlp Dener           } else {
1860a4511e9SAlp Dener             if (ftrial < f_min) {
1870a4511e9SAlp Dener               f_min = ftrial;
188eb910715SAlp Dener               sigma = -tao->trust / bnk->gnorm;
189eb910715SAlp Dener             }
190770b7498SAlp Dener             /* Compute the predicted and actual reduction */
1912ab2a32cSAlp Dener             if (bnk->inactive_idx) {
1922ab2a32cSAlp Dener               ierr = VecGetSubVector(bnk->unprojected_gradient, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
1932ab2a32cSAlp Dener               ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
1942ab2a32cSAlp Dener             } else {
1952ab2a32cSAlp Dener               bnk->G_inactive = bnk->unprojected_gradient;
1962ab2a32cSAlp Dener               bnk->inactive_work = bnk->W;
1972ab2a32cSAlp Dener             }
1982ab2a32cSAlp Dener             ierr = MatMult(bnk->H_inactive, bnk->G_inactive, bnk->inactive_work);CHKERRQ(ierr);
1992ab2a32cSAlp Dener             ierr = VecDot(bnk->G_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr);
2002ab2a32cSAlp Dener             if (bnk->inactive_idx) {
2012ab2a32cSAlp Dener               ierr = VecRestoreSubVector(bnk->unprojected_gradient, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
2022ab2a32cSAlp Dener               ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
2032ab2a32cSAlp Dener             }
204eb910715SAlp Dener             prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm));
205eb910715SAlp Dener             actred = bnk->f - ftrial;
206eb910715SAlp Dener             if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
207eb910715SAlp Dener               kappa = 1.0;
208eb910715SAlp Dener             } else {
209eb910715SAlp Dener               kappa = actred / prered;
210eb910715SAlp Dener             }
211eb910715SAlp Dener 
212eb910715SAlp Dener             tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred);
213eb910715SAlp Dener             tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred);
214eb910715SAlp Dener             tau_min = PetscMin(tau_1, tau_2);
215eb910715SAlp Dener             tau_max = PetscMax(tau_1, tau_2);
216eb910715SAlp Dener 
217eb910715SAlp Dener             if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) {
218eb910715SAlp Dener               /* Great agreement */
219eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
220eb910715SAlp Dener 
221eb910715SAlp Dener               if (tau_max < 1.0) {
222eb910715SAlp Dener                 tau = bnk->gamma3_i;
223eb910715SAlp Dener               } else if (tau_max > bnk->gamma4_i) {
224eb910715SAlp Dener                 tau = bnk->gamma4_i;
225eb910715SAlp Dener               } else if (tau_1 >= 1.0 && tau_1 <= bnk->gamma4_i && tau_2 < 1.0) {
226eb910715SAlp Dener                 tau = tau_1;
227eb910715SAlp Dener               } else if (tau_2 >= 1.0 && tau_2 <= bnk->gamma4_i && tau_1 < 1.0) {
228eb910715SAlp Dener                 tau = tau_2;
229eb910715SAlp Dener               } else {
230eb910715SAlp Dener                 tau = tau_max;
231eb910715SAlp Dener               }
232eb910715SAlp Dener             } else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) {
233eb910715SAlp Dener               /* Good agreement */
234eb910715SAlp Dener               max_radius = PetscMax(max_radius, tao->trust);
235eb910715SAlp Dener 
236eb910715SAlp Dener               if (tau_max < bnk->gamma2_i) {
237eb910715SAlp Dener                 tau = bnk->gamma2_i;
238eb910715SAlp Dener               } else if (tau_max > bnk->gamma3_i) {
239eb910715SAlp Dener                 tau = bnk->gamma3_i;
240eb910715SAlp Dener               } else {
241eb910715SAlp Dener                 tau = tau_max;
242eb910715SAlp Dener               }
243eb910715SAlp Dener             } else {
244eb910715SAlp Dener               /* Not good agreement */
245eb910715SAlp Dener               if (tau_min > 1.0) {
246eb910715SAlp Dener                 tau = bnk->gamma2_i;
247eb910715SAlp Dener               } else if (tau_max < bnk->gamma1_i) {
248eb910715SAlp Dener                 tau = bnk->gamma1_i;
249eb910715SAlp Dener               } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) {
250eb910715SAlp Dener                 tau = bnk->gamma1_i;
251eb910715SAlp Dener               } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
252eb910715SAlp Dener                 tau = tau_1;
253eb910715SAlp Dener               } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) {
254eb910715SAlp Dener                 tau = tau_2;
255eb910715SAlp Dener               } else {
256eb910715SAlp Dener                 tau = tau_max;
257eb910715SAlp Dener               }
258eb910715SAlp Dener             }
259eb910715SAlp Dener           }
260eb910715SAlp Dener           tao->trust = tau * tao->trust;
261*c0f10754SAlp Dener 
262*c0f10754SAlp Dener           /* Ensure that the trust radius is within the limits */
263*c0f10754SAlp Dener           tao->trust = PetscMax(tao->trust, bnk->min_radius);
264*c0f10754SAlp Dener           tao->trust = PetscMin(tao->trust, bnk->max_radius);
265eb910715SAlp Dener         }
266eb910715SAlp Dener 
2670a4511e9SAlp Dener         if (f_min < bnk->f) {
2680a4511e9SAlp Dener           bnk->f = f_min;
269eb910715SAlp Dener           ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr);
27087602d1eSAlp Dener           ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr);
27109164190SAlp Dener           ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr);
27209164190SAlp Dener           ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr);
273eb910715SAlp Dener 
274eb910715SAlp Dener           ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr);
275eb910715SAlp Dener           if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN");
276*c0f10754SAlp Dener           *needH = PETSC_TRUE;
277eb910715SAlp Dener 
278eb910715SAlp Dener           ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr);
27928017e9fSAlp Dener           ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,1.0);CHKERRQ(ierr);
280eb910715SAlp Dener           ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr);
281eb910715SAlp Dener           if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0);
282eb910715SAlp Dener         }
283eb910715SAlp Dener       }
284eb910715SAlp Dener       tao->trust = PetscMax(tao->trust, max_radius);
285eb910715SAlp Dener       break;
286eb910715SAlp Dener 
287eb910715SAlp Dener     default:
288eb910715SAlp Dener       /* Norm of the first direction will initialize radius */
289eb910715SAlp Dener       tao->trust = 0.0;
290eb910715SAlp Dener       break;
291eb910715SAlp Dener     }
292eb910715SAlp Dener   }
293eb910715SAlp Dener   /* Set initial scaling for the BFGS preconditioner
294eb910715SAlp Dener      This step is done after computing the initial trust-region radius
295eb910715SAlp Dener      since the function value may have decreased */
296eb910715SAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
2979b6ef848SAlp Dener     delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
298eb910715SAlp Dener     ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
299eb910715SAlp Dener   }
300eb910715SAlp Dener 
301eb910715SAlp Dener   /* Set counter for gradient/reset steps*/
302eb910715SAlp Dener   bnk->newt = 0;
303eb910715SAlp Dener   bnk->bfgs = 0;
304eb910715SAlp Dener   bnk->sgrad = 0;
305eb910715SAlp Dener   bnk->grad = 0;
306eb910715SAlp Dener   PetscFunctionReturn(0);
307eb910715SAlp Dener }
308eb910715SAlp Dener 
309df278d8fSAlp Dener /*------------------------------------------------------------*/
310df278d8fSAlp Dener 
31162675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */
31262675beeSAlp Dener 
31362675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao)
31462675beeSAlp Dener {
31562675beeSAlp Dener   PetscErrorCode               ierr;
31662675beeSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
31762675beeSAlp Dener 
31862675beeSAlp Dener   PetscFunctionBegin;
31962675beeSAlp Dener   /* Compute the Hessian */
32062675beeSAlp Dener   ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr);
32162675beeSAlp Dener   /* Add a correction to the BFGS preconditioner */
32262675beeSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) {
32362675beeSAlp Dener     ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
32462675beeSAlp Dener     /* Update the BFGS diagonal scaling */
32562675beeSAlp Dener     if (BFGS_SCALE_AHESS == bnk->bfgs_scale_type) {
32662675beeSAlp Dener       ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr);
32762675beeSAlp Dener       ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
32862675beeSAlp Dener       ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
32962675beeSAlp Dener       ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
33062675beeSAlp Dener       ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
33162675beeSAlp Dener     }
33262675beeSAlp Dener   }
33362675beeSAlp Dener   PetscFunctionReturn(0);
33462675beeSAlp Dener }
33562675beeSAlp Dener 
33662675beeSAlp Dener /*------------------------------------------------------------*/
33762675beeSAlp Dener 
3382f75a4aaSAlp Dener /* Routine for estimating the active set */
3392f75a4aaSAlp Dener 
3402f75a4aaSAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao)
3412f75a4aaSAlp Dener {
3422f75a4aaSAlp Dener   PetscErrorCode               ierr;
3432f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3442f75a4aaSAlp Dener 
3452f75a4aaSAlp Dener   PetscFunctionBegin;
3462f75a4aaSAlp Dener   switch (bnk->as_type) {
3472f75a4aaSAlp Dener   case BNK_AS_NONE:
3482f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr);
3492f75a4aaSAlp Dener     ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr);
3502f75a4aaSAlp Dener     ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr);
3512f75a4aaSAlp Dener     ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr);
3522f75a4aaSAlp Dener     break;
3532f75a4aaSAlp Dener 
3542f75a4aaSAlp Dener   case BNK_AS_BERTSEKAS:
3552f75a4aaSAlp Dener     /* Compute the trial step vector with which we will estimate the active set at the next iteration */
3562f75a4aaSAlp Dener     if (BNK_PC_BFGS == bnk->pc_type) {
3572f75a4aaSAlp Dener       /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */
3585e9b73cbSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
3592f75a4aaSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr);
3602f75a4aaSAlp Dener     } else {
3619b6ef848SAlp Dener       /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */
3622f75a4aaSAlp Dener       ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr);
3639b6ef848SAlp Dener       ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr);
3649b6ef848SAlp Dener       ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr);
3652f75a4aaSAlp Dener       ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr);
3662f75a4aaSAlp Dener       ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr);
3672f75a4aaSAlp Dener     }
3682f75a4aaSAlp Dener     ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr);
3690a4511e9SAlp Dener     ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, bnk->unprojected_gradient, bnk->W, bnk->as_step, &bnk->as_tol, &bnk->active_lower, &bnk->active_upper, &bnk->active_fixed, &bnk->active_idx, &bnk->inactive_idx);CHKERRQ(ierr);
3702f75a4aaSAlp Dener 
3712f75a4aaSAlp Dener   default:
3722f75a4aaSAlp Dener     break;
3732f75a4aaSAlp Dener   }
3742f75a4aaSAlp Dener   PetscFunctionReturn(0);
3752f75a4aaSAlp Dener }
3762f75a4aaSAlp Dener 
3772f75a4aaSAlp Dener /*------------------------------------------------------------*/
3782f75a4aaSAlp Dener 
3792f75a4aaSAlp Dener /* Routine for bounding the step direction */
3802f75a4aaSAlp Dener 
3812f75a4aaSAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, Vec step)
3822f75a4aaSAlp Dener {
3832f75a4aaSAlp Dener   PetscErrorCode               ierr;
3842f75a4aaSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
3852f75a4aaSAlp Dener 
3862f75a4aaSAlp Dener   PetscFunctionBegin;
38728017e9fSAlp Dener   if (bnk->active_idx) {
3882f75a4aaSAlp Dener     switch (bnk->as_type) {
3892f75a4aaSAlp Dener     case BNK_AS_NONE:
3902f75a4aaSAlp Dener       if (bnk->active_idx) {
3912f75a4aaSAlp Dener         ierr = VecGetSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr);
3922f75a4aaSAlp Dener         ierr = VecSet(bnk->active_work, 0.0);CHKERRQ(ierr);
3932f75a4aaSAlp Dener         ierr = VecRestoreSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr);
3942f75a4aaSAlp Dener       }
3952f75a4aaSAlp Dener       break;
3962f75a4aaSAlp Dener 
3972f75a4aaSAlp Dener     case BNK_AS_BERTSEKAS:
3982f75a4aaSAlp Dener       ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, step);CHKERRQ(ierr);
3992f75a4aaSAlp Dener       break;
4002f75a4aaSAlp Dener 
4012f75a4aaSAlp Dener     default:
4022f75a4aaSAlp Dener       break;
4032f75a4aaSAlp Dener     }
404e465cd6fSAlp Dener   }
4052f75a4aaSAlp Dener   PetscFunctionReturn(0);
4062f75a4aaSAlp Dener }
4072f75a4aaSAlp Dener 
408*c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate)
409*c0f10754SAlp Dener {
410*c0f10754SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
411*c0f10754SAlp Dener   PetscErrorCode               ierr;
412*c0f10754SAlp Dener 
413*c0f10754SAlp Dener   PetscFunctionBegin;
414*c0f10754SAlp Dener   *terminate = PETSC_FALSE;
415*c0f10754SAlp Dener   if (bnk->max_cg_its > 0) {
416*c0f10754SAlp Dener     /* Copy the current solution, unprojected gradient and step info into BNCG */
417*c0f10754SAlp Dener     ierr = VecCopy(tao->solution, bnk->bncg->solution);CHKERRQ(ierr);
418*c0f10754SAlp Dener     if (tao->niter > 1) {
419*c0f10754SAlp Dener       bnk->bncg_ctx->f = bnk->f;
420*c0f10754SAlp Dener       ierr = VecCopy(bnk->unprojected_gradient, bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr);
421*c0f10754SAlp Dener       ierr = VecCopy(tao->stepdirection, bnk->bncg->stepdirection);CHKERRQ(ierr);
422*c0f10754SAlp Dener       ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr);
423*c0f10754SAlp Dener     }
424*c0f10754SAlp Dener     /* Take some small finite number of BNCG iterations */
425*c0f10754SAlp Dener     ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr);
426*c0f10754SAlp Dener     /* Add the number of gradient and function evaluations to the total */
427*c0f10754SAlp Dener     tao->nfuncs += bnk->bncg->nfuncs;
428*c0f10754SAlp Dener     tao->nfuncgrads += bnk->bncg->nfuncgrads;
429*c0f10754SAlp Dener     tao->ngrads += bnk->bncg->ngrads;
430*c0f10754SAlp Dener     tao->nhess += bnk->bncg->nhess;
431*c0f10754SAlp Dener     /* Extract the BNCG solution out and save it into BNK */
432*c0f10754SAlp Dener     bnk->f = bnk->bncg_ctx->f;
433*c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg->solution, tao->solution);
434*c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg_ctx->unprojected_gradient, bnk->unprojected_gradient);
435*c0f10754SAlp Dener     ierr = VecCopy(bnk->bncg->gradient, tao->gradient);
436*c0f10754SAlp Dener     /* Check to see if BNCG converged the problem */
437*c0f10754SAlp 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) {
438*c0f10754SAlp Dener       *terminate = PETSC_TRUE;
439*c0f10754SAlp Dener     }
440*c0f10754SAlp Dener   }
441*c0f10754SAlp Dener   PetscFunctionReturn(0);
442*c0f10754SAlp Dener }
443*c0f10754SAlp Dener 
4442f75a4aaSAlp Dener /*------------------------------------------------------------*/
4452f75a4aaSAlp Dener 
446*c0f10754SAlp Dener /* Routine for computing the Newton step. */
447df278d8fSAlp Dener 
44862675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason)
449eb910715SAlp Dener {
450eb910715SAlp Dener   PetscErrorCode               ierr;
451eb910715SAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
452eb910715SAlp Dener 
453e465cd6fSAlp Dener   PetscReal                    delta;
454eb910715SAlp Dener   PetscInt                     bfgsUpdates = 0;
455eb910715SAlp Dener   PetscInt                     kspits;
456eb910715SAlp Dener 
457eb910715SAlp Dener   PetscFunctionBegin;
4582f75a4aaSAlp Dener   /* Determine the active and inactive sets */
4592f75a4aaSAlp Dener   ierr = TaoBNKEstimateActiveSet(tao);CHKERRQ(ierr);
46009164190SAlp Dener 
4615e9b73cbSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
4622f75a4aaSAlp Dener   if (BNK_PC_BFGS == bnk->pc_type) { ierr = MatLMVMSetInactive(bnk->M, bnk->inactive_idx);CHKERRQ(ierr); }
4632f75a4aaSAlp Dener   if (bnk->inactive_idx) {
4645e9b73cbSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
4655e9b73cbSAlp Dener     ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr);
466eb3ba6a7SAlp Dener     if (tao->hessian == tao->hessian_pre) {
467eb3ba6a7SAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
468eb3ba6a7SAlp Dener     } else {
4695e9b73cbSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
4705e9b73cbSAlp Dener       ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr);
471eb3ba6a7SAlp Dener     }
4722f75a4aaSAlp Dener   } else {
47362675beeSAlp Dener     ierr = MatDestroy(&bnk->H_inactive);
47462675beeSAlp Dener     ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);
47562675beeSAlp Dener     if (tao->hessian == tao->hessian_pre) {
47662675beeSAlp Dener       bnk->Hpre_inactive = bnk->H_inactive;
47762675beeSAlp Dener     } else {
47862675beeSAlp Dener       ierr = MatDestroy(&bnk->Hpre_inactive);
47962675beeSAlp Dener       ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive);
48062675beeSAlp Dener     }
48162675beeSAlp Dener   }
48262675beeSAlp Dener 
48362675beeSAlp Dener   /* Shift the reduced Hessian matrix */
48462675beeSAlp Dener   if ((shift) && (bnk->pert > 0)) {
48562675beeSAlp Dener     ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr);
48662675beeSAlp Dener     if (bnk->H_inactive != bnk->Hpre_inactive) {
48762675beeSAlp Dener       ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr);
48862675beeSAlp Dener     }
48962675beeSAlp Dener   }
49062675beeSAlp Dener 
49162675beeSAlp Dener   /* Update the diagonal scaling for the BFGS preconditioner, this time with the Hessian perturbation */
49262675beeSAlp Dener   if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_PHESS == bnk->bfgs_scale_type)) {
49362675beeSAlp Dener     /* Obtain diagonal for the bfgs preconditioner  */
4945e9b73cbSAlp Dener     ierr = VecSet(bnk->Diag, 1.0);CHKERRQ(ierr);
4955e9b73cbSAlp Dener     if (bnk->inactive_idx) {
4965e9b73cbSAlp Dener       ierr = VecGetSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
4975e9b73cbSAlp Dener     } else {
4985e9b73cbSAlp Dener       bnk->Diag_red = bnk->Diag;
4995e9b73cbSAlp Dener     }
5005e9b73cbSAlp Dener     ierr = MatGetDiagonal(bnk->H_inactive, bnk->Diag_red);CHKERRQ(ierr);
5015e9b73cbSAlp Dener     if (bnk->inactive_idx) {
5025e9b73cbSAlp Dener       ierr = VecRestoreSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr);
5035e9b73cbSAlp Dener     }
50462675beeSAlp Dener     ierr = VecAbs(bnk->Diag);CHKERRQ(ierr);
50562675beeSAlp Dener     ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr);
50662675beeSAlp Dener     ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr);
50762675beeSAlp Dener     ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr);
5082f75a4aaSAlp Dener   }
50909164190SAlp Dener 
510eb910715SAlp Dener   /* Solve the Newton system of equations */
5112f75a4aaSAlp Dener   ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr);
5125e9b73cbSAlp Dener   ierr = KSPReset(tao->ksp);CHKERRQ(ierr);
51309164190SAlp Dener   ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr);
5145e9b73cbSAlp Dener   ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr);
5155e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5165e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5175e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5185e9b73cbSAlp Dener   } else {
5195e9b73cbSAlp Dener     bnk->G_inactive = bnk->unprojected_gradient;
5205e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
52128017e9fSAlp Dener   }
522eb910715SAlp Dener   if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) {
523fed79b8eSAlp Dener     ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5245e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
525eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
526eb910715SAlp Dener     tao->ksp_its+=kspits;
527eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
528080d2917SAlp Dener     ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
529eb910715SAlp Dener 
530eb910715SAlp Dener     if (0.0 == tao->trust) {
531eb910715SAlp Dener       /* Radius was uninitialized; use the norm of the direction */
532080d2917SAlp Dener       if (bnk->dnorm > 0.0) {
533080d2917SAlp Dener         tao->trust = bnk->dnorm;
534eb910715SAlp Dener 
535eb910715SAlp Dener         /* Modify the radius if it is too large or small */
536eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
537eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
538eb910715SAlp Dener       } else {
539eb910715SAlp Dener         /* The direction was bad; set radius to default value and re-solve
540eb910715SAlp Dener            the trust-region subproblem to get a direction */
541eb910715SAlp Dener         tao->trust = tao->trust0;
542eb910715SAlp Dener 
543eb910715SAlp Dener         /* Modify the radius if it is too large or small */
544eb910715SAlp Dener         tao->trust = PetscMax(tao->trust, bnk->min_radius);
545eb910715SAlp Dener         tao->trust = PetscMin(tao->trust, bnk->max_radius);
546eb910715SAlp Dener 
547fed79b8eSAlp Dener         ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr);
5485e9b73cbSAlp Dener         ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
549eb910715SAlp Dener         ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr);
550eb910715SAlp Dener         tao->ksp_its+=kspits;
551eb910715SAlp Dener         tao->ksp_tot_its+=kspits;
552080d2917SAlp Dener         ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr);
553eb910715SAlp Dener 
554080d2917SAlp Dener         if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero");
555eb910715SAlp Dener       }
556eb910715SAlp Dener     }
557eb910715SAlp Dener   } else {
5585e9b73cbSAlp Dener     ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr);
559eb910715SAlp Dener     ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr);
560eb910715SAlp Dener     tao->ksp_its += kspits;
561eb910715SAlp Dener     tao->ksp_tot_its+=kspits;
562eb910715SAlp Dener   }
5635e9b73cbSAlp Dener   /* Restore sub vectors back */
5645e9b73cbSAlp Dener   if (bnk->inactive_idx) {
5655e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
5665e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
5675e9b73cbSAlp Dener   }
568770b7498SAlp Dener   /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
569fed79b8eSAlp Dener   ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
5702f75a4aaSAlp Dener   ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
571770b7498SAlp Dener 
572770b7498SAlp Dener   /* Record convergence reasons */
573e465cd6fSAlp Dener   ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr);
574e465cd6fSAlp Dener   if (KSP_CONVERGED_ATOL == *ksp_reason) {
575770b7498SAlp Dener     ++bnk->ksp_atol;
576e465cd6fSAlp Dener   } else if (KSP_CONVERGED_RTOL == *ksp_reason) {
577770b7498SAlp Dener     ++bnk->ksp_rtol;
578e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) {
579770b7498SAlp Dener     ++bnk->ksp_ctol;
580e465cd6fSAlp Dener   } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) {
581770b7498SAlp Dener     ++bnk->ksp_negc;
582e465cd6fSAlp Dener   } else if (KSP_DIVERGED_DTOL == *ksp_reason) {
583770b7498SAlp Dener     ++bnk->ksp_dtol;
584e465cd6fSAlp Dener   } else if (KSP_DIVERGED_ITS == *ksp_reason) {
585770b7498SAlp Dener     ++bnk->ksp_iter;
586770b7498SAlp Dener   } else {
587770b7498SAlp Dener     ++bnk->ksp_othr;
588770b7498SAlp Dener   }
589fed79b8eSAlp Dener 
590fed79b8eSAlp Dener   /* Make sure the BFGS preconditioner is healthy */
591fed79b8eSAlp Dener   if (bnk->pc_type == BNK_PC_BFGS) {
592fed79b8eSAlp Dener     ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
593e465cd6fSAlp Dener     if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 1)) {
594fed79b8eSAlp Dener       /* Preconditioner is numerically indefinite; reset the approximation. */
5959b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
596eb910715SAlp Dener       ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr);
597eb910715SAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
59809164190SAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
599eb910715SAlp Dener     }
600fed79b8eSAlp Dener   }
601e465cd6fSAlp Dener   PetscFunctionReturn(0);
602e465cd6fSAlp Dener }
603eb910715SAlp Dener 
60462675beeSAlp Dener /*------------------------------------------------------------*/
60562675beeSAlp Dener 
6065e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */
6075e9b73cbSAlp Dener 
6085e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered)
6095e9b73cbSAlp Dener {
6105e9b73cbSAlp Dener   PetscErrorCode               ierr;
6115e9b73cbSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
6125e9b73cbSAlp Dener 
6135e9b73cbSAlp Dener   PetscFunctionBegin;
6145e9b73cbSAlp Dener   /* Extract subvectors associated with the inactive set */
6155e9b73cbSAlp Dener   if (bnk->inactive_idx){
6165e9b73cbSAlp Dener     ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6175e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6185e9b73cbSAlp Dener     ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6195e9b73cbSAlp Dener   } else {
6205e9b73cbSAlp Dener     bnk->X_inactive = tao->stepdirection;
6215e9b73cbSAlp Dener     bnk->inactive_work = bnk->Xwork;
6225e9b73cbSAlp Dener     bnk->G_inactive = bnk->Gwork;
6235e9b73cbSAlp Dener   }
6245e9b73cbSAlp Dener   /* Recompute the predicted decrease based on the quadratic model */
6255e9b73cbSAlp Dener   ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr);
6265e9b73cbSAlp Dener   ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr);
6275e9b73cbSAlp Dener   ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered);
6285e9b73cbSAlp Dener   /* Restore the sub vectors */
6295e9b73cbSAlp Dener   if (bnk->inactive_idx){
6305e9b73cbSAlp Dener     ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr);
6315e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr);
6325e9b73cbSAlp Dener     ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr);
6335e9b73cbSAlp Dener   }
6345e9b73cbSAlp Dener   PetscFunctionReturn(0);
6355e9b73cbSAlp Dener }
6365e9b73cbSAlp Dener 
6375e9b73cbSAlp Dener /*------------------------------------------------------------*/
6385e9b73cbSAlp Dener 
63962675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction.
64062675beeSAlp Dener 
64162675beeSAlp Dener    The step direction falls back onto BFGS, scaled gradient and gradient steps
64262675beeSAlp Dener    in the event that the Newton step fails the test.
64362675beeSAlp Dener */
64462675beeSAlp Dener 
645e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType)
646e465cd6fSAlp Dener {
647e465cd6fSAlp Dener   PetscErrorCode               ierr;
648e465cd6fSAlp Dener   TAO_BNK                      *bnk = (TAO_BNK *)tao->data;
649e465cd6fSAlp Dener 
650e465cd6fSAlp Dener   PetscReal                    gdx, delta, e_min;
651e465cd6fSAlp Dener   PetscInt                     bfgsUpdates;
652e465cd6fSAlp Dener 
653e465cd6fSAlp Dener   PetscFunctionBegin;
654080d2917SAlp Dener   ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr);
655eb910715SAlp Dener   if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) {
656eb910715SAlp Dener     /* Newton step is not descent or direction produced Inf or NaN
657eb910715SAlp Dener        Update the perturbation for next time */
658eb910715SAlp Dener     if (bnk->pert <= 0.0) {
659eb910715SAlp Dener       /* Initialize the perturbation */
660eb910715SAlp Dener       bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
661eb910715SAlp Dener       if (bnk->is_gltr) {
662eb910715SAlp Dener         ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
663eb910715SAlp Dener         bnk->pert = PetscMax(bnk->pert, -e_min);
664eb910715SAlp Dener       }
665eb910715SAlp Dener     } else {
666eb910715SAlp Dener       /* Increase the perturbation */
667eb910715SAlp Dener       bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
668eb910715SAlp Dener     }
669eb910715SAlp Dener 
670eb910715SAlp Dener     if (BNK_PC_BFGS != bnk->pc_type) {
671eb910715SAlp Dener       /* We don't have the bfgs matrix around and updated
672eb910715SAlp Dener          Must use gradient direction in this case */
673080d2917SAlp Dener       ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
674eb910715SAlp Dener       *stepType = BNK_GRADIENT;
675eb910715SAlp Dener     } else {
676eb910715SAlp Dener       /* Attempt to use the BFGS direction */
6772ab2a32cSAlp Dener       ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr);
67809164190SAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
679eb910715SAlp Dener 
6808d5ead36SAlp Dener       /* Check for success (descent direction)
6818d5ead36SAlp Dener          NOTE: Negative gdx here means not a descent direction because
6828d5ead36SAlp Dener          the fall-back step is missing a negative sign. */
683080d2917SAlp Dener       ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
6848d5ead36SAlp Dener       if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
685eb910715SAlp Dener         /* BFGS direction is not descent or direction produced not a number
686eb910715SAlp Dener            We can assert bfgsUpdates > 1 in this case because
687eb910715SAlp Dener            the first solve produces the scaled gradient direction,
688eb910715SAlp Dener            which is guaranteed to be descent */
689eb910715SAlp Dener 
690eb910715SAlp Dener         /* Use steepest descent direction (scaled) */
6919b6ef848SAlp Dener         delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
692eb910715SAlp Dener         ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
693eb910715SAlp Dener         ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
69409164190SAlp Dener         ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
69509164190SAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
696eb910715SAlp Dener 
697eb910715SAlp Dener         *stepType = BNK_SCALED_GRADIENT;
698eb910715SAlp Dener       } else {
699770b7498SAlp Dener         ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
700eb910715SAlp Dener         if (1 == bfgsUpdates) {
701eb910715SAlp Dener           /* The first BFGS direction is always the scaled gradient */
702eb910715SAlp Dener           *stepType = BNK_SCALED_GRADIENT;
703eb910715SAlp Dener         } else {
704eb910715SAlp Dener           *stepType = BNK_BFGS;
705eb910715SAlp Dener         }
706eb910715SAlp Dener       }
707eb910715SAlp Dener     }
7088d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
7098d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
7102f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
711eb910715SAlp Dener   } else {
712eb910715SAlp Dener     /* Computed Newton step is descent */
713eb910715SAlp Dener     switch (ksp_reason) {
714eb910715SAlp Dener     case KSP_DIVERGED_NANORINF:
715eb910715SAlp Dener     case KSP_DIVERGED_BREAKDOWN:
716eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_MAT:
717eb910715SAlp Dener     case KSP_DIVERGED_INDEFINITE_PC:
718eb910715SAlp Dener     case KSP_CONVERGED_CG_NEG_CURVE:
719eb910715SAlp Dener       /* Matrix or preconditioner is indefinite; increase perturbation */
720eb910715SAlp Dener       if (bnk->pert <= 0.0) {
721eb910715SAlp Dener         /* Initialize the perturbation */
722eb910715SAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
723eb910715SAlp Dener         if (bnk->is_gltr) {
724eb910715SAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr);
725eb910715SAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
726eb910715SAlp Dener         }
727eb910715SAlp Dener       } else {
728eb910715SAlp Dener         /* Increase the perturbation */
729eb910715SAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
730eb910715SAlp Dener       }
731eb910715SAlp Dener       break;
732eb910715SAlp Dener 
733eb910715SAlp Dener     default:
734eb910715SAlp Dener       /* Newton step computation is good; decrease perturbation */
735eb910715SAlp Dener       bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm);
736eb910715SAlp Dener       if (bnk->pert < bnk->pmin) {
737eb910715SAlp Dener         bnk->pert = 0.0;
738eb910715SAlp Dener       }
739eb910715SAlp Dener       break;
740eb910715SAlp Dener     }
741fed79b8eSAlp Dener     *stepType = BNK_NEWTON;
742eb910715SAlp Dener   }
743eb910715SAlp Dener   PetscFunctionReturn(0);
744eb910715SAlp Dener }
745eb910715SAlp Dener 
746df278d8fSAlp Dener /*------------------------------------------------------------*/
747df278d8fSAlp Dener 
748df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search.
749df278d8fSAlp Dener 
750df278d8fSAlp Dener   Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the
751df278d8fSAlp Dener   Newton step does not produce a valid step length.
752df278d8fSAlp Dener */
753df278d8fSAlp Dener 
754c14b763aSAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason)
755c14b763aSAlp Dener {
756c14b763aSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
757c14b763aSAlp Dener   PetscErrorCode ierr;
758c14b763aSAlp Dener   TaoLineSearchConvergedReason ls_reason;
759c14b763aSAlp Dener 
760c14b763aSAlp Dener   PetscReal      e_min, gdx, delta;
761c14b763aSAlp Dener   PetscInt       bfgsUpdates;
762c14b763aSAlp Dener 
763c14b763aSAlp Dener   PetscFunctionBegin;
764c14b763aSAlp Dener   /* Perform the linesearch */
765c14b763aSAlp Dener   ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
766c14b763aSAlp Dener   ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
767c14b763aSAlp Dener 
7689b6ef848SAlp Dener   while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && (stepType != BNK_GRADIENT || stepType !=BNK_SCALED_GRADIENT)) {
769c14b763aSAlp Dener     /* Linesearch failed, revert solution */
770c14b763aSAlp Dener     bnk->f = bnk->fold;
771c14b763aSAlp Dener     ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr);
772c14b763aSAlp Dener     ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr);
773c14b763aSAlp Dener 
774c14b763aSAlp Dener     switch(stepType) {
775c14b763aSAlp Dener     case BNK_NEWTON:
7768d5ead36SAlp Dener       /* Failed to obtain acceptable iterate with Newton step
777c14b763aSAlp Dener          Update the perturbation for next time */
778c14b763aSAlp Dener       if (bnk->pert <= 0.0) {
779c14b763aSAlp Dener         /* Initialize the perturbation */
780c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm));
781c14b763aSAlp Dener         if (bnk->is_gltr) {
782c14b763aSAlp Dener           ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr);
783c14b763aSAlp Dener           bnk->pert = PetscMax(bnk->pert, -e_min);
784c14b763aSAlp Dener         }
785c14b763aSAlp Dener       } else {
786c14b763aSAlp Dener         /* Increase the perturbation */
787c14b763aSAlp Dener         bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm));
788c14b763aSAlp Dener       }
789c14b763aSAlp Dener 
790c14b763aSAlp Dener       if (BNK_PC_BFGS != bnk->pc_type) {
791c14b763aSAlp Dener         /* We don't have the bfgs matrix around and being updated
792c14b763aSAlp Dener            Must use gradient direction in this case */
793c14b763aSAlp Dener         ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr);
794c14b763aSAlp Dener         stepType = BNK_GRADIENT;
795c14b763aSAlp Dener       } else {
796c14b763aSAlp Dener         /* Attempt to use the BFGS direction */
797c14b763aSAlp Dener         ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
7988d5ead36SAlp Dener         /* Check for success (descent direction)
7998d5ead36SAlp Dener            NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */
800c14b763aSAlp Dener         ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
801c14b763aSAlp Dener         if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) {
802c14b763aSAlp Dener           /* BFGS direction is not descent or direction produced not a number
803c14b763aSAlp Dener              We can assert bfgsUpdates > 1 in this case
804c14b763aSAlp Dener              Use steepest descent direction (scaled) */
8059b6ef848SAlp Dener           delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
806c14b763aSAlp Dener           ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
807c14b763aSAlp Dener           ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
808c14b763aSAlp Dener           ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
809c14b763aSAlp Dener           ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
810c14b763aSAlp Dener 
811c14b763aSAlp Dener           bfgsUpdates = 1;
812c14b763aSAlp Dener           stepType = BNK_SCALED_GRADIENT;
813c14b763aSAlp Dener         } else {
814c14b763aSAlp Dener           ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr);
815c14b763aSAlp Dener           if (1 == bfgsUpdates) {
816c14b763aSAlp Dener             /* The first BFGS direction is always the scaled gradient */
817c14b763aSAlp Dener             stepType = BNK_SCALED_GRADIENT;
818c14b763aSAlp Dener           } else {
819c14b763aSAlp Dener             stepType = BNK_BFGS;
820c14b763aSAlp Dener           }
821c14b763aSAlp Dener         }
822c14b763aSAlp Dener       }
823c14b763aSAlp Dener       break;
824c14b763aSAlp Dener 
825c14b763aSAlp Dener     case BNK_BFGS:
826c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
827c14b763aSAlp Dener          Failed to obtain acceptable iterate with BFGS step
828c14b763aSAlp Dener          Attempt to use the scaled gradient direction */
8299b6ef848SAlp Dener       delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm);
830c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr);
831c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
832c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
833c14b763aSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
834c14b763aSAlp Dener 
835c14b763aSAlp Dener       bfgsUpdates = 1;
836c14b763aSAlp Dener       stepType = BNK_SCALED_GRADIENT;
837c14b763aSAlp Dener       break;
838c14b763aSAlp Dener 
839c14b763aSAlp Dener     case BNK_SCALED_GRADIENT:
840c14b763aSAlp Dener       /* Can only enter if pc_type == BNK_PC_BFGS
841c14b763aSAlp Dener          The scaled gradient step did not produce a new iterate;
842c14b763aSAlp Dener          attemp to use the gradient direction.
843c14b763aSAlp Dener          Need to make sure we are not using a different diagonal scaling */
844c14b763aSAlp Dener       ierr = MatLMVMSetScale(bnk->M,0);CHKERRQ(ierr);
845c14b763aSAlp Dener       ierr = MatLMVMSetDelta(bnk->M,1.0);CHKERRQ(ierr);
846c14b763aSAlp Dener       ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr);
847c14b763aSAlp Dener       ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr);
848c14b763aSAlp Dener       ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr);
849c14b763aSAlp Dener 
850c14b763aSAlp Dener       bfgsUpdates = 1;
851c14b763aSAlp Dener       stepType = BNK_GRADIENT;
852c14b763aSAlp Dener       break;
853c14b763aSAlp Dener     }
8548d5ead36SAlp Dener     /* Make sure the safeguarded fall-back step is zero for actively bounded variables */
8558d5ead36SAlp Dener     ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr);
8562f75a4aaSAlp Dener     ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr);
857c14b763aSAlp Dener 
8588d5ead36SAlp Dener     /* Perform one last line search with the fall-back step */
859c14b763aSAlp Dener     ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr);
860c14b763aSAlp Dener     ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr);
861c14b763aSAlp Dener   }
862c14b763aSAlp Dener   *reason = ls_reason;
863c14b763aSAlp Dener   PetscFunctionReturn(0);
864c14b763aSAlp Dener }
865c14b763aSAlp Dener 
866df278d8fSAlp Dener /*------------------------------------------------------------*/
867df278d8fSAlp Dener 
868df278d8fSAlp Dener /* Routine for updating the trust radius.
869df278d8fSAlp Dener 
870df278d8fSAlp Dener   Function features three different update methods:
871df278d8fSAlp Dener   1) Line-search step length based
872df278d8fSAlp Dener   2) Predicted decrease on the CG quadratic model
873df278d8fSAlp Dener   3) Interpolation
874df278d8fSAlp Dener */
875df278d8fSAlp Dener 
87628017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept)
877080d2917SAlp Dener {
878080d2917SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
879080d2917SAlp Dener   PetscErrorCode ierr;
880080d2917SAlp Dener 
881b1c2d0e3SAlp Dener   PetscReal      step, kappa;
882080d2917SAlp Dener   PetscReal      gdx, tau_1, tau_2, tau_min, tau_max;
883080d2917SAlp Dener 
884080d2917SAlp Dener   PetscFunctionBegin;
885080d2917SAlp Dener   /* Update trust region radius */
886080d2917SAlp Dener   *accept = PETSC_FALSE;
88728017e9fSAlp Dener   switch(updateType) {
888080d2917SAlp Dener   case BNK_UPDATE_STEP:
889c14b763aSAlp Dener     *accept = PETSC_TRUE; /* always accept here because line search succeeded */
890080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
891080d2917SAlp Dener       ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr);
892080d2917SAlp Dener       if (step < bnk->nu1) {
893080d2917SAlp Dener         /* Very bad step taken; reduce radius */
894080d2917SAlp Dener         tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
895080d2917SAlp Dener       } else if (step < bnk->nu2) {
896080d2917SAlp Dener         /* Reasonably bad step taken; reduce radius */
897080d2917SAlp Dener         tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust);
898080d2917SAlp Dener       } else if (step < bnk->nu3) {
899080d2917SAlp Dener         /*  Reasonable step was taken; leave radius alone */
900080d2917SAlp Dener         if (bnk->omega3 < 1.0) {
901080d2917SAlp Dener           tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust);
902080d2917SAlp Dener         } else if (bnk->omega3 > 1.0) {
903080d2917SAlp Dener           tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust);
904080d2917SAlp Dener         }
905080d2917SAlp Dener       } else if (step < bnk->nu4) {
906080d2917SAlp Dener         /*  Full step taken; increase the radius */
907080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust);
908080d2917SAlp Dener       } else {
909080d2917SAlp Dener         /*  More than full step taken; increase the radius */
910080d2917SAlp Dener         tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust);
911080d2917SAlp Dener       }
912080d2917SAlp Dener     } else {
913080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
914080d2917SAlp Dener       tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust);
915080d2917SAlp Dener     }
916080d2917SAlp Dener     break;
917080d2917SAlp Dener 
918080d2917SAlp Dener   case BNK_UPDATE_REDUCTION:
919080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
920b1c2d0e3SAlp Dener       if (prered < 0.0) {
921fed79b8eSAlp Dener         /* The predicted reduction has the wrong sign.  This cannot
922fed79b8eSAlp Dener            happen in infinite precision arithmetic.  Step should
923fed79b8eSAlp Dener            be rejected! */
924080d2917SAlp Dener         tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
925fed79b8eSAlp Dener       }
926fed79b8eSAlp Dener       else {
927b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
928080d2917SAlp Dener           tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
929080d2917SAlp Dener         } else {
9300a4511e9SAlp Dener           if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) &&
9310a4511e9SAlp Dener               (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) {
932080d2917SAlp Dener             kappa = 1.0;
933fed79b8eSAlp Dener           }
934fed79b8eSAlp Dener           else {
935080d2917SAlp Dener             kappa = actred / prered;
936080d2917SAlp Dener           }
937fed79b8eSAlp Dener 
938fed79b8eSAlp Dener           /* Accept or reject the step and update radius */
939080d2917SAlp Dener           if (kappa < bnk->eta1) {
940fed79b8eSAlp Dener             /* Reject the step */
941080d2917SAlp Dener             tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm);
942fed79b8eSAlp Dener           }
943fed79b8eSAlp Dener           else {
944fed79b8eSAlp Dener             /* Accept the step */
945c133c014SAlp Dener             *accept = PETSC_TRUE;
946c133c014SAlp Dener             /* Update the trust region radius only if the computed step is at the trust radius boundary */
9478d5ead36SAlp Dener             if (bnk->dnorm == tao->trust) {
948080d2917SAlp Dener               if (kappa < bnk->eta2) {
949080d2917SAlp Dener                 /* Marginal bad step */
950c133c014SAlp Dener                 tao->trust = bnk->alpha2 * tao->trust;
951080d2917SAlp Dener               }
952fed79b8eSAlp Dener               else if (kappa < bnk->eta3) {
953fed79b8eSAlp Dener                 /* Reasonable step */
954fed79b8eSAlp Dener                 tao->trust = bnk->alpha3 * tao->trust;
955fed79b8eSAlp Dener               }
956fed79b8eSAlp Dener               else if (kappa < bnk->eta4) {
957080d2917SAlp Dener                 /* Good step */
958c133c014SAlp Dener                 tao->trust = bnk->alpha4 * tao->trust;
959fed79b8eSAlp Dener               }
960fed79b8eSAlp Dener               else {
961080d2917SAlp Dener                 /* Very good step */
962c133c014SAlp Dener                 tao->trust = bnk->alpha5 * tao->trust;
963080d2917SAlp Dener               }
964c133c014SAlp Dener             }
965080d2917SAlp Dener           }
966080d2917SAlp Dener         }
967080d2917SAlp Dener       }
968080d2917SAlp Dener     } else {
969080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
970080d2917SAlp Dener       tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust);
971080d2917SAlp Dener     }
972080d2917SAlp Dener     break;
973080d2917SAlp Dener 
974080d2917SAlp Dener   default:
975080d2917SAlp Dener     if (stepType == BNK_NEWTON) {
976b1c2d0e3SAlp Dener       if (prered < 0.0) {
977080d2917SAlp Dener         /*  The predicted reduction has the wrong sign.  This cannot */
978080d2917SAlp Dener         /*  happen in infinite precision arithmetic.  Step should */
979080d2917SAlp Dener         /*  be rejected! */
980080d2917SAlp Dener         tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
981080d2917SAlp Dener       } else {
982b1c2d0e3SAlp Dener         if (PetscIsInfOrNanReal(actred)) {
983080d2917SAlp Dener           tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
984080d2917SAlp Dener         } else {
985080d2917SAlp Dener           if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) {
986080d2917SAlp Dener             kappa = 1.0;
987080d2917SAlp Dener           } else {
988080d2917SAlp Dener             kappa = actred / prered;
989080d2917SAlp Dener           }
990080d2917SAlp Dener 
991080d2917SAlp Dener           ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr);
992080d2917SAlp Dener           tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred);
993080d2917SAlp Dener           tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred);
994080d2917SAlp Dener           tau_min = PetscMin(tau_1, tau_2);
995080d2917SAlp Dener           tau_max = PetscMax(tau_1, tau_2);
996080d2917SAlp Dener 
997080d2917SAlp Dener           if (kappa >= 1.0 - bnk->mu1) {
998080d2917SAlp Dener             /*  Great agreement */
999080d2917SAlp Dener             *accept = PETSC_TRUE;
1000080d2917SAlp Dener             if (tau_max < 1.0) {
1001080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1002080d2917SAlp Dener             } else if (tau_max > bnk->gamma4) {
1003080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm);
1004080d2917SAlp Dener             } else {
1005080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1006080d2917SAlp Dener             }
1007080d2917SAlp Dener           } else if (kappa >= 1.0 - bnk->mu2) {
1008080d2917SAlp Dener             /*  Good agreement */
1009080d2917SAlp Dener             *accept = PETSC_TRUE;
1010080d2917SAlp Dener             if (tau_max < bnk->gamma2) {
1011080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1012080d2917SAlp Dener             } else if (tau_max > bnk->gamma3) {
1013080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm);
1014080d2917SAlp Dener             } else if (tau_max < 1.0) {
1015080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1016080d2917SAlp Dener             } else {
1017080d2917SAlp Dener               tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm);
1018080d2917SAlp Dener             }
1019080d2917SAlp Dener           } else {
1020080d2917SAlp Dener             /*  Not good agreement */
1021080d2917SAlp Dener             if (tau_min > 1.0) {
1022080d2917SAlp Dener               tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm);
1023080d2917SAlp Dener             } else if (tau_max < bnk->gamma1) {
1024080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1025080d2917SAlp Dener             } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) {
1026080d2917SAlp Dener               tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm);
1027080d2917SAlp Dener             } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) {
1028080d2917SAlp Dener               tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm);
1029080d2917SAlp Dener             } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) {
1030080d2917SAlp Dener               tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm);
1031080d2917SAlp Dener             } else {
1032080d2917SAlp Dener               tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm);
1033080d2917SAlp Dener             }
1034080d2917SAlp Dener           }
1035080d2917SAlp Dener         }
1036080d2917SAlp Dener       }
1037080d2917SAlp Dener     } else {
1038080d2917SAlp Dener       /*  Newton step was not good; reduce the radius */
1039080d2917SAlp Dener       tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust);
1040080d2917SAlp Dener     }
104128017e9fSAlp Dener     break;
1042080d2917SAlp Dener   }
1043c133c014SAlp Dener   /* Make sure the radius does not violate min and max settings */
1044c133c014SAlp Dener   tao->trust = PetscMin(tao->trust, bnk->max_radius);
1045fed79b8eSAlp Dener   tao->trust = PetscMax(tao->trust, bnk->min_radius);
1046080d2917SAlp Dener   PetscFunctionReturn(0);
1047080d2917SAlp Dener }
1048080d2917SAlp Dener 
1049eb910715SAlp Dener /* ---------------------------------------------------------- */
1050df278d8fSAlp Dener 
105162675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType)
105262675beeSAlp Dener {
105362675beeSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
105462675beeSAlp Dener 
105562675beeSAlp Dener   PetscFunctionBegin;
105662675beeSAlp Dener   switch (stepType) {
105762675beeSAlp Dener   case BNK_NEWTON:
105862675beeSAlp Dener     ++bnk->newt;
105962675beeSAlp Dener     break;
106062675beeSAlp Dener   case BNK_BFGS:
106162675beeSAlp Dener     ++bnk->bfgs;
106262675beeSAlp Dener     break;
106362675beeSAlp Dener   case BNK_SCALED_GRADIENT:
106462675beeSAlp Dener     ++bnk->sgrad;
106562675beeSAlp Dener     break;
106662675beeSAlp Dener   case BNK_GRADIENT:
106762675beeSAlp Dener     ++bnk->grad;
106862675beeSAlp Dener     break;
106962675beeSAlp Dener   default:
107062675beeSAlp Dener     break;
107162675beeSAlp Dener   }
107262675beeSAlp Dener   PetscFunctionReturn(0);
107362675beeSAlp Dener }
107462675beeSAlp Dener 
107562675beeSAlp Dener /* ---------------------------------------------------------- */
107662675beeSAlp Dener 
10779b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao)
1078eb910715SAlp Dener {
1079eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1080eb910715SAlp Dener   PetscErrorCode ierr;
10819b6ef848SAlp Dener   KSPType        ksp_type;
1082eb910715SAlp Dener 
1083eb910715SAlp Dener   PetscFunctionBegin;
1084eb910715SAlp Dener   if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);}
1085eb910715SAlp Dener   if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);}
1086eb910715SAlp Dener   if (!bnk->W) {ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);}
1087eb910715SAlp Dener   if (!bnk->Xold) {ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);}
1088eb910715SAlp Dener   if (!bnk->Gold) {ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);}
108909164190SAlp Dener   if (!bnk->Xwork) {ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);}
109009164190SAlp Dener   if (!bnk->Gwork) {ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);}
109109164190SAlp Dener   if (!bnk->unprojected_gradient) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);}
109209164190SAlp Dener   if (!bnk->unprojected_gradient_old) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);}
10935e9b73cbSAlp Dener   if (!bnk->Diag_min) {ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);}
10945e9b73cbSAlp Dener   if (!bnk->Diag_max) {ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);}
1095*c0f10754SAlp Dener   if (!bnk->bncg_sol && bnk->max_cg_its > 0) {ierr = VecDuplicate(tao->solution,&bnk->bncg_sol);CHKERRQ(ierr);}
1096eb910715SAlp Dener   bnk->Diag = 0;
1097*c0f10754SAlp Dener   bnk->Diag_red = 0;
1098*c0f10754SAlp Dener   bnk->X_inactive = 0;
1099*c0f10754SAlp Dener   bnk->G_inactive = 0;
110062675beeSAlp Dener   bnk->inactive_work = 0;
110162675beeSAlp Dener   bnk->active_work = 0;
110262675beeSAlp Dener   bnk->inactive_idx = 0;
110362675beeSAlp Dener   bnk->active_idx = 0;
110462675beeSAlp Dener   bnk->active_lower = 0;
110562675beeSAlp Dener   bnk->active_upper = 0;
110662675beeSAlp Dener   bnk->active_fixed = 0;
1107eb910715SAlp Dener   bnk->M = 0;
110809164190SAlp Dener   bnk->H_inactive = 0;
110909164190SAlp Dener   bnk->Hpre_inactive = 0;
11109b6ef848SAlp Dener   ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr);
11119b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr);
11129b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr);
11139b6ef848SAlp Dener   ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr);
1114eb910715SAlp Dener   PetscFunctionReturn(0);
1115eb910715SAlp Dener }
1116eb910715SAlp Dener 
1117eb910715SAlp Dener /*------------------------------------------------------------*/
1118df278d8fSAlp Dener 
1119eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao)
1120eb910715SAlp Dener {
1121eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1122eb910715SAlp Dener   PetscErrorCode ierr;
1123eb910715SAlp Dener 
1124eb910715SAlp Dener   PetscFunctionBegin;
1125eb910715SAlp Dener   if (tao->setupcalled) {
1126eb910715SAlp Dener     ierr = VecDestroy(&bnk->W);CHKERRQ(ierr);
1127eb910715SAlp Dener     ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr);
1128eb910715SAlp Dener     ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr);
112909164190SAlp Dener     ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr);
113009164190SAlp Dener     ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr);
113109164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr);
113209164190SAlp Dener     ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr);
113362675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr);
113462675beeSAlp Dener     ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr);
1135*c0f10754SAlp Dener     if (bnk->max_cg_its > 0) {
1136*c0f10754SAlp Dener       ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr);
1137*c0f10754SAlp Dener       ierr = VecDestroy(&bnk->bncg_sol);CHKERRQ(ierr);
1138*c0f10754SAlp Dener     }
11395e9b73cbSAlp Dener   }
11405e9b73cbSAlp Dener   ierr = VecDestroy(&bnk->Diag);CHKERRQ(ierr);
1141eb910715SAlp Dener   ierr = MatDestroy(&bnk->M);CHKERRQ(ierr);
1142*c0f10754SAlp Dener   if (bnk->Hpre_inactive != tao->hessian_pre && bnk->Hpre_inactive != bnk->H_inactive) {ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);}
1143*c0f10754SAlp Dener   if (bnk->H_inactive != tao->hessian) {ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);}
1144eb910715SAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
1145eb910715SAlp Dener   PetscFunctionReturn(0);
1146eb910715SAlp Dener }
1147eb910715SAlp Dener 
1148eb910715SAlp Dener /*------------------------------------------------------------*/
1149df278d8fSAlp Dener 
1150eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao)
1151eb910715SAlp Dener {
1152eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1153eb910715SAlp Dener   PetscErrorCode ierr;
1154eb910715SAlp Dener 
1155eb910715SAlp Dener   PetscFunctionBegin;
1156eb910715SAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr);
11578d5ead36SAlp Dener   ierr = PetscOptionsEList("-tao_bnk_pc_type", "pc type", "", BNK_PC, BNK_PC_TYPES, BNK_PC[bnk->pc_type], &bnk->pc_type, 0);CHKERRQ(ierr);
11588d5ead36SAlp Dener   ierr = PetscOptionsEList("-tao_bnk_bfgs_scale_type", "bfgs scale type", "", BFGS_SCALE, BFGS_SCALE_TYPES, BFGS_SCALE[bnk->bfgs_scale_type], &bnk->bfgs_scale_type, 0);CHKERRQ(ierr);
11598d5ead36SAlp 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);
11608d5ead36SAlp 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);
11612f75a4aaSAlp 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);
11628d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_sval", "perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr);
11638d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imin", "minimum initial perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr);
11648d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imax", "maximum initial perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr);
11658d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_imfac", "initial merit factor", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr);
11668d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmin", "minimum perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr);
11678d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmax", "maximum perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr);
11688d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pgfac", "growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr);
11698d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_psfac", "shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr);
11708d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmgfac", "merit growth factor", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr);
11718d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_pmsfac", "merit shrink factor", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr);
11728d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta1", "poor steplength; reduce radius", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr);
11738d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta2", "reasonable steplength; leave radius alone", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr);
11748d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta3", "good steplength; increase radius", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr);
11758d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_eta4", "excellent steplength; greatly increase radius", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr);
11768d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha1", "", "", bnk->alpha1, &bnk->alpha1,NULL);CHKERRQ(ierr);
11778d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha2", "", "", bnk->alpha2, &bnk->alpha2,NULL);CHKERRQ(ierr);
11788d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha3", "", "", bnk->alpha3, &bnk->alpha3,NULL);CHKERRQ(ierr);
11798d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha4", "", "", bnk->alpha4, &bnk->alpha4,NULL);CHKERRQ(ierr);
11808d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_alpha5", "", "", bnk->alpha5, &bnk->alpha5,NULL);CHKERRQ(ierr);
11818d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu1", "poor steplength; reduce radius", "", bnk->nu1, &bnk->nu1,NULL);CHKERRQ(ierr);
11828d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu2", "reasonable steplength; leave radius alone", "", bnk->nu2, &bnk->nu2,NULL);CHKERRQ(ierr);
11838d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu3", "good steplength; increase radius", "", bnk->nu3, &bnk->nu3,NULL);CHKERRQ(ierr);
11848d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_nu4", "excellent steplength; greatly increase radius", "", bnk->nu4, &bnk->nu4,NULL);CHKERRQ(ierr);
11858d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega1", "", "", bnk->omega1, &bnk->omega1,NULL);CHKERRQ(ierr);
11868d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega2", "", "", bnk->omega2, &bnk->omega2,NULL);CHKERRQ(ierr);
11878d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega3", "", "", bnk->omega3, &bnk->omega3,NULL);CHKERRQ(ierr);
11888d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega4", "", "", bnk->omega4, &bnk->omega4,NULL);CHKERRQ(ierr);
11898d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_omega5", "", "", bnk->omega5, &bnk->omega5,NULL);CHKERRQ(ierr);
11908d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1_i", "", "", bnk->mu1_i, &bnk->mu1_i,NULL);CHKERRQ(ierr);
11918d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2_i", "", "", bnk->mu2_i, &bnk->mu2_i,NULL);CHKERRQ(ierr);
11928d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1_i", "", "", bnk->gamma1_i, &bnk->gamma1_i,NULL);CHKERRQ(ierr);
11938d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2_i", "", "", bnk->gamma2_i, &bnk->gamma2_i,NULL);CHKERRQ(ierr);
11948d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3_i", "", "", bnk->gamma3_i, &bnk->gamma3_i,NULL);CHKERRQ(ierr);
11958d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4_i", "", "", bnk->gamma4_i, &bnk->gamma4_i,NULL);CHKERRQ(ierr);
11968d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta_i", "", "", bnk->theta_i, &bnk->theta_i,NULL);CHKERRQ(ierr);
11978d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu1", "", "", bnk->mu1, &bnk->mu1,NULL);CHKERRQ(ierr);
11988d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_mu2", "", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr);
11998d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma1", "", "", bnk->gamma1, &bnk->gamma1,NULL);CHKERRQ(ierr);
12008d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma2", "", "", bnk->gamma2, &bnk->gamma2,NULL);CHKERRQ(ierr);
12018d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma3", "", "", bnk->gamma3, &bnk->gamma3,NULL);CHKERRQ(ierr);
12028d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_gamma4", "", "", bnk->gamma4, &bnk->gamma4,NULL);CHKERRQ(ierr);
12038d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_theta", "", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr);
12048d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_min_radius", "lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr);
12058d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_max_radius", "upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr);
12068d5ead36SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_epsilon", "tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr);
12070a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_tol", "initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol,NULL);CHKERRQ(ierr);
12080a4511e9SAlp Dener   ierr = PetscOptionsReal("-tao_bnk_as_step", "step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step,NULL);CHKERRQ(ierr);
1209*c0f10754SAlp 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);
1210eb910715SAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
1211eb910715SAlp Dener   ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr);
1212eb910715SAlp Dener   ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr);
1213eb910715SAlp Dener   PetscFunctionReturn(0);
1214eb910715SAlp Dener }
1215eb910715SAlp Dener 
1216eb910715SAlp Dener /*------------------------------------------------------------*/
1217df278d8fSAlp Dener 
1218eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer)
1219eb910715SAlp Dener {
1220eb910715SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1221eb910715SAlp Dener   PetscInt       nrejects;
1222eb910715SAlp Dener   PetscBool      isascii;
1223eb910715SAlp Dener   PetscErrorCode ierr;
1224eb910715SAlp Dener 
1225eb910715SAlp Dener   PetscFunctionBegin;
1226eb910715SAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1227eb910715SAlp Dener   if (isascii) {
1228eb910715SAlp Dener     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1229eb910715SAlp Dener     if (BNK_PC_BFGS == bnk->pc_type && bnk->M) {
1230eb910715SAlp Dener       ierr = MatLMVMGetRejects(bnk->M,&nrejects);CHKERRQ(ierr);
1231eb910715SAlp Dener       ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects);CHKERRQ(ierr);
1232eb910715SAlp Dener     }
1233eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr);
1234eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr);
1235eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr);
1236eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr);
1237eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr);
1238eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr);
1239eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr);
1240eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr);
1241eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr);
1242eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr);
1243eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr);
1244eb910715SAlp Dener     ierr = PetscViewerASCIIPrintf(viewer, "  othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr);
1245eb910715SAlp Dener     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1246eb910715SAlp Dener   }
1247eb910715SAlp Dener   PetscFunctionReturn(0);
1248eb910715SAlp Dener }
1249eb910715SAlp Dener 
1250eb910715SAlp Dener /* ---------------------------------------------------------- */
1251df278d8fSAlp Dener 
1252eb910715SAlp Dener /*MC
1253eb910715SAlp Dener   TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms.
125466ed3702SAlp Dener   At each iteration, the BNK methods solve the symmetric
1255eb910715SAlp Dener   system of equations to obtain the step diretion dk:
1256eb910715SAlp Dener               Hk dk = -gk
12572b97c8d8SAlp Dener   for free variables only. The step can be globalized either through
12582b97c8d8SAlp Dener   trust-region methods, or a line search, or a heuristic mixture of both.
1259eb910715SAlp Dener 
1260eb910715SAlp Dener     Options Database Keys:
12618d5ead36SAlp Dener + -tao_bnk_pc_type - "none","ahess","bfgs","petsc"
12628d5ead36SAlp Dener . -tao_bnk_bfgs_scale_type - "ahess","phess","bfgs"
12638d5ead36SAlp Dener . -tao_bnk_init_type - "constant","direction","interpolation"
12648d5ead36SAlp Dener . -tao_bnk_update_type - "step","direction","interpolation"
12652f75a4aaSAlp Dener . -tao_bnk_as_type - "none","bertsekas"
12668d5ead36SAlp Dener . -tao_bnk_sval - perturbation starting value
12678d5ead36SAlp Dener . -tao_bnk_imin - minimum initial perturbation
12688d5ead36SAlp Dener . -tao_bnk_imax - maximum initial perturbation
12698d5ead36SAlp Dener . -tao_bnk_pmin - minimum perturbation
12708d5ead36SAlp Dener . -tao_bnk_pmax - maximum perturbation
12718d5ead36SAlp Dener . -tao_bnk_pgfac - growth factor
12728d5ead36SAlp Dener . -tao_bnk_psfac - shrink factor
12738d5ead36SAlp Dener . -tao_bnk_imfac - initial merit factor
12748d5ead36SAlp Dener . -tao_bnk_pmgfac - merit growth factor
12758d5ead36SAlp Dener . -tao_bnk_pmsfac - merit shrink factor
12768d5ead36SAlp Dener . -tao_bnk_eta1 - poor steplength; reduce radius
12778d5ead36SAlp Dener . -tao_bnk_eta2 - reasonable steplength; leave radius
12788d5ead36SAlp Dener . -tao_bnk_eta3 - good steplength; increase readius
12798d5ead36SAlp Dener . -tao_bnk_eta4 - excellent steplength; greatly increase radius
12808d5ead36SAlp Dener . -tao_bnk_alpha1 - alpha1 reduction
12818d5ead36SAlp Dener . -tao_bnk_alpha2 - alpha2 reduction
12828d5ead36SAlp Dener . -tao_bnk_alpha3 - alpha3 reduction
12838d5ead36SAlp Dener . -tao_bnk_alpha4 - alpha4 reduction
12848d5ead36SAlp Dener . -tao_bnk_alpha - alpha5 reduction
12858d5ead36SAlp Dener . -tao_bnk_mu1 - mu1 interpolation update
12868d5ead36SAlp Dener . -tao_bnk_mu2 - mu2 interpolation update
12878d5ead36SAlp Dener . -tao_bnk_gamma1 - gamma1 interpolation update
12888d5ead36SAlp Dener . -tao_bnk_gamma2 - gamma2 interpolation update
12898d5ead36SAlp Dener . -tao_bnk_gamma3 - gamma3 interpolation update
12908d5ead36SAlp Dener . -tao_bnk_gamma4 - gamma4 interpolation update
12918d5ead36SAlp Dener . -tao_bnk_theta - theta interpolation update
12928d5ead36SAlp Dener . -tao_bnk_omega1 - omega1 step update
12938d5ead36SAlp Dener . -tao_bnk_omega2 - omega2 step update
12948d5ead36SAlp Dener . -tao_bnk_omega3 - omega3 step update
12958d5ead36SAlp Dener . -tao_bnk_omega4 - omega4 step update
12968d5ead36SAlp Dener . -tao_bnk_omega5 - omega5 step update
12978d5ead36SAlp Dener . -tao_bnk_mu1_i -  mu1 interpolation init factor
12988d5ead36SAlp Dener . -tao_bnk_mu2_i -  mu2 interpolation init factor
12998d5ead36SAlp Dener . -tao_bnk_gamma1_i -  gamma1 interpolation init factor
13008d5ead36SAlp Dener . -tao_bnk_gamma2_i -  gamma2 interpolation init factor
13018d5ead36SAlp Dener . -tao_bnk_gamma3_i -  gamma3 interpolation init factor
13028d5ead36SAlp Dener . -tao_bnk_gamma4_i -  gamma4 interpolation init factor
13032f75a4aaSAlp Dener . -tao_bnk_theta_i -  theta interpolation init factor
13042f75a4aaSAlp Dener - -tao_bnk_bound_tol -  initial tolerance used in estimating bounded active variables
1305eb910715SAlp Dener 
1306eb910715SAlp Dener   Level: beginner
1307eb910715SAlp Dener M*/
1308eb910715SAlp Dener 
1309eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao)
1310eb910715SAlp Dener {
1311eb910715SAlp Dener   TAO_BNK        *bnk;
1312eb910715SAlp Dener   const char     *morethuente_type = TAOLINESEARCHMT;
1313eb910715SAlp Dener   PetscErrorCode ierr;
1314eb910715SAlp Dener 
1315eb910715SAlp Dener   PetscFunctionBegin;
1316eb910715SAlp Dener   ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr);
1317eb910715SAlp Dener 
1318eb910715SAlp Dener   tao->ops->setup = TaoSetUp_BNK;
1319eb910715SAlp Dener   tao->ops->view = TaoView_BNK;
1320eb910715SAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BNK;
1321eb910715SAlp Dener   tao->ops->destroy = TaoDestroy_BNK;
1322eb910715SAlp Dener 
1323eb910715SAlp Dener   /*  Override default settings (unless already changed) */
1324eb910715SAlp Dener   if (!tao->max_it_changed) tao->max_it = 50;
1325eb910715SAlp Dener   if (!tao->trust0_changed) tao->trust0 = 100.0;
1326eb910715SAlp Dener 
1327eb910715SAlp Dener   tao->data = (void*)bnk;
1328eb910715SAlp Dener 
132966ed3702SAlp Dener   /*  Hessian shifting parameters */
1330eb910715SAlp Dener   bnk->sval   = 0.0;
1331eb910715SAlp Dener   bnk->imin   = 1.0e-4;
1332eb910715SAlp Dener   bnk->imax   = 1.0e+2;
1333eb910715SAlp Dener   bnk->imfac  = 1.0e-1;
1334eb910715SAlp Dener 
1335eb910715SAlp Dener   bnk->pmin   = 1.0e-12;
1336eb910715SAlp Dener   bnk->pmax   = 1.0e+2;
1337eb910715SAlp Dener   bnk->pgfac  = 1.0e+1;
1338eb910715SAlp Dener   bnk->psfac  = 4.0e-1;
1339eb910715SAlp Dener   bnk->pmgfac = 1.0e-1;
1340eb910715SAlp Dener   bnk->pmsfac = 1.0e-1;
1341eb910715SAlp Dener 
1342eb910715SAlp Dener   /*  Default values for trust-region radius update based on steplength */
1343eb910715SAlp Dener   bnk->nu1 = 0.25;
1344eb910715SAlp Dener   bnk->nu2 = 0.50;
1345eb910715SAlp Dener   bnk->nu3 = 1.00;
1346eb910715SAlp Dener   bnk->nu4 = 1.25;
1347eb910715SAlp Dener 
1348eb910715SAlp Dener   bnk->omega1 = 0.25;
1349eb910715SAlp Dener   bnk->omega2 = 0.50;
1350eb910715SAlp Dener   bnk->omega3 = 1.00;
1351eb910715SAlp Dener   bnk->omega4 = 2.00;
1352eb910715SAlp Dener   bnk->omega5 = 4.00;
1353eb910715SAlp Dener 
1354eb910715SAlp Dener   /*  Default values for trust-region radius update based on reduction */
1355eb910715SAlp Dener   bnk->eta1 = 1.0e-4;
1356eb910715SAlp Dener   bnk->eta2 = 0.25;
1357eb910715SAlp Dener   bnk->eta3 = 0.50;
1358eb910715SAlp Dener   bnk->eta4 = 0.90;
1359eb910715SAlp Dener 
1360eb910715SAlp Dener   bnk->alpha1 = 0.25;
1361eb910715SAlp Dener   bnk->alpha2 = 0.50;
1362eb910715SAlp Dener   bnk->alpha3 = 1.00;
1363eb910715SAlp Dener   bnk->alpha4 = 2.00;
1364eb910715SAlp Dener   bnk->alpha5 = 4.00;
1365eb910715SAlp Dener 
1366eb910715SAlp Dener   /*  Default values for trust-region radius update based on interpolation */
1367eb910715SAlp Dener   bnk->mu1 = 0.10;
1368eb910715SAlp Dener   bnk->mu2 = 0.50;
1369eb910715SAlp Dener 
1370eb910715SAlp Dener   bnk->gamma1 = 0.25;
1371eb910715SAlp Dener   bnk->gamma2 = 0.50;
1372eb910715SAlp Dener   bnk->gamma3 = 2.00;
1373eb910715SAlp Dener   bnk->gamma4 = 4.00;
1374eb910715SAlp Dener 
1375eb910715SAlp Dener   bnk->theta = 0.05;
1376eb910715SAlp Dener 
1377eb910715SAlp Dener   /*  Default values for trust region initialization based on interpolation */
1378eb910715SAlp Dener   bnk->mu1_i = 0.35;
1379eb910715SAlp Dener   bnk->mu2_i = 0.50;
1380eb910715SAlp Dener 
1381eb910715SAlp Dener   bnk->gamma1_i = 0.0625;
1382eb910715SAlp Dener   bnk->gamma2_i = 0.5;
1383eb910715SAlp Dener   bnk->gamma3_i = 2.0;
1384eb910715SAlp Dener   bnk->gamma4_i = 5.0;
1385eb910715SAlp Dener 
1386eb910715SAlp Dener   bnk->theta_i = 0.25;
1387eb910715SAlp Dener 
1388eb910715SAlp Dener   /*  Remaining parameters */
1389*c0f10754SAlp Dener   bnk->max_cg_its = 0;
1390eb910715SAlp Dener   bnk->min_radius = 1.0e-10;
1391eb910715SAlp Dener   bnk->max_radius = 1.0e10;
1392770b7498SAlp Dener   bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
13930a4511e9SAlp Dener   bnk->as_tol = 1.0e-3;
13940a4511e9SAlp Dener   bnk->as_step = 1.0e-3;
139562675beeSAlp Dener   bnk->dmin = 1.0e-6;
139662675beeSAlp Dener   bnk->dmax = 1.0e6;
1397eb910715SAlp Dener 
1398eb910715SAlp Dener   bnk->pc_type         = BNK_PC_BFGS;
1399eb910715SAlp Dener   bnk->bfgs_scale_type = BFGS_SCALE_PHESS;
1400eb910715SAlp Dener   bnk->init_type       = BNK_INIT_INTERPOLATION;
1401fed79b8eSAlp Dener   bnk->update_type     = BNK_UPDATE_INTERPOLATION;
14022f75a4aaSAlp Dener   bnk->as_type         = BNK_AS_BERTSEKAS;
1403eb910715SAlp Dener 
1404*c0f10754SAlp Dener   /* Create the line search */
1405eb910715SAlp Dener   ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr);
1406eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr);
1407eb910715SAlp Dener   ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr);
1408eb910715SAlp Dener   ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr);
1409eb910715SAlp Dener   ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr);
1410eb910715SAlp Dener 
1411eb910715SAlp Dener   /*  Set linear solver to default for symmetric matrices */
1412eb910715SAlp Dener   ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr);
1413eb910715SAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr);
1414eb910715SAlp Dener   ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr);
1415eb910715SAlp Dener   ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr);
1416eb910715SAlp Dener   PetscFunctionReturn(0);
1417eb910715SAlp Dener }
1418