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 2662675beeSAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType) 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 36eb910715SAlp Dener PetscInt n,N,needH = 1; 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 56eb910715SAlp Dener /* Number of times ksp stopped because of these reasons */ 57eb910715SAlp Dener bnk->ksp_atol = 0; 58eb910715SAlp Dener bnk->ksp_rtol = 0; 59eb910715SAlp Dener bnk->ksp_dtol = 0; 60eb910715SAlp Dener bnk->ksp_ctol = 0; 61eb910715SAlp Dener bnk->ksp_negc = 0; 62eb910715SAlp Dener bnk->ksp_iter = 0; 63eb910715SAlp Dener bnk->ksp_othr = 0; 64eb910715SAlp Dener 65fed79b8eSAlp Dener /* Initialize the Hessian perturbation */ 66fed79b8eSAlp Dener bnk->pert = bnk->sval; 67fed79b8eSAlp Dener 68eb910715SAlp Dener /* Initialize trust-region radius when using nash, stcg, or gltr 69eb910715SAlp Dener Command automatically ignored for other methods 70eb910715SAlp Dener Will be reset during the first iteration 71eb910715SAlp Dener */ 72eb910715SAlp Dener ierr = KSPCGSetRadius(tao->ksp,bnk->max_radius);CHKERRQ(ierr); 73eb910715SAlp Dener if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) { 74eb910715SAlp Dener if (tao->trust0 < 0.0) SETERRQ(PETSC_COMM_SELF,1,"Initial radius negative"); 75eb910715SAlp Dener tao->trust = tao->trust0; 76eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 77eb910715SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 78eb910715SAlp Dener } 79eb910715SAlp Dener 8028017e9fSAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 8128017e9fSAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,1.0);CHKERRQ(ierr); 8228017e9fSAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 8328017e9fSAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 8428017e9fSAlp Dener 85eb910715SAlp Dener /* Get vectors we will need */ 86eb910715SAlp Dener if (BNK_PC_BFGS == bnk->pc_type && !bnk->M) { 87eb910715SAlp Dener ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); 88eb910715SAlp Dener ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); 89eb910715SAlp Dener ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&bnk->M);CHKERRQ(ierr); 90eb910715SAlp Dener ierr = MatLMVMAllocateVectors(bnk->M,tao->solution);CHKERRQ(ierr); 91eb910715SAlp Dener } 92eb910715SAlp Dener 93eb910715SAlp Dener /* create vectors for the limited memory preconditioner */ 94eb910715SAlp Dener if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_BFGS != bnk->bfgs_scale_type)) { 9562675beeSAlp Dener if (!bnk->Diag) {ierr = VecDuplicate(tao->solution,&bnk->Diag);CHKERRQ(ierr);} 965e9b73cbSAlp Dener } 9762675beeSAlp Dener ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr); 9862675beeSAlp Dener ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr); 99eb910715SAlp Dener 100eb910715SAlp Dener /* Modify the preconditioner to use the bfgs approximation */ 101eb910715SAlp Dener ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr); 102eb910715SAlp Dener switch(bnk->pc_type) { 103eb910715SAlp Dener case BNK_PC_NONE: 104eb910715SAlp Dener ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr); 105eb910715SAlp Dener ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 106eb910715SAlp Dener break; 107eb910715SAlp Dener 108eb910715SAlp Dener case BNK_PC_AHESS: 109eb910715SAlp Dener ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr); 110eb910715SAlp Dener ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 111eb910715SAlp Dener ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr); 112eb910715SAlp Dener break; 113eb910715SAlp Dener 114eb910715SAlp Dener case BNK_PC_BFGS: 115eb910715SAlp Dener ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr); 116eb910715SAlp Dener ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 117eb910715SAlp Dener ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr); 118eb910715SAlp Dener ierr = PCShellSetContext(pc, bnk->M);CHKERRQ(ierr); 119eb910715SAlp Dener ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr); 120eb910715SAlp Dener break; 121eb910715SAlp Dener 122eb910715SAlp Dener default: 123eb910715SAlp Dener /* Use the pc method set by pc_type */ 124eb910715SAlp Dener break; 125eb910715SAlp Dener } 126eb910715SAlp Dener 127eb910715SAlp Dener /* Initialize trust-region radius. The initialization is only performed 128eb910715SAlp Dener when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */ 129eb910715SAlp Dener if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) { 13062675beeSAlp Dener switch(initType) { 131eb910715SAlp Dener case BNK_INIT_CONSTANT: 132eb910715SAlp Dener /* Use the initial radius specified */ 133eb910715SAlp Dener break; 134eb910715SAlp Dener 135eb910715SAlp Dener case BNK_INIT_INTERPOLATION: 136eb910715SAlp Dener /* Use the initial radius specified */ 137eb910715SAlp Dener max_radius = 0.0; 138eb910715SAlp Dener 139eb910715SAlp Dener for (j = 0; j < j_max; ++j) { 1400a4511e9SAlp Dener f_min = bnk->f; 141eb910715SAlp Dener sigma = 0.0; 142eb910715SAlp Dener 143eb910715SAlp Dener if (needH) { 14462602cfbSAlp Dener /* Compute the Hessian at the new step, and extract the inactive subsystem */ 145eb910715SAlp Dener ierr = TaoComputeHessian(tao, tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 146*2ab2a32cSAlp Dener ierr = MatDestroy(&bnk->H_inactive); 14728017e9fSAlp Dener if (bnk->inactive_idx) { 14862602cfbSAlp Dener ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr); 14962602cfbSAlp Dener ierr = VecWhichInactive(tao->XL,tao->solution,bnk->unprojected_gradient,tao->XU,PETSC_TRUE,&bnk->inactive_idx);CHKERRQ(ierr); 150*2ab2a32cSAlp Dener ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr); 15128017e9fSAlp Dener } else { 15262675beeSAlp Dener ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive); 15328017e9fSAlp Dener } 154eb910715SAlp Dener needH = 0; 155eb910715SAlp Dener } 156eb910715SAlp Dener 157eb910715SAlp Dener for (i = 0; i < i_max; ++i) { 15862602cfbSAlp Dener /* Take a steepest descent step and snap it to bounds */ 15962602cfbSAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 16062602cfbSAlp Dener ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr); 16162602cfbSAlp Dener ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr); 162770b7498SAlp Dener /* Recompute the step after bound snapping so that it can be used in predicted decrease calculation later */ 163eb910715SAlp Dener ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr); 16462602cfbSAlp Dener ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr); 16562602cfbSAlp Dener /* Compute the objective at the trial */ 16662602cfbSAlp Dener ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr); 16762602cfbSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 168eb910715SAlp Dener if (PetscIsInfOrNanReal(ftrial)) { 169eb910715SAlp Dener tau = bnk->gamma1_i; 170eb910715SAlp Dener } else { 1710a4511e9SAlp Dener if (ftrial < f_min) { 1720a4511e9SAlp Dener f_min = ftrial; 173eb910715SAlp Dener sigma = -tao->trust / bnk->gnorm; 174eb910715SAlp Dener } 175770b7498SAlp Dener /* Compute the predicted and actual reduction */ 176*2ab2a32cSAlp Dener if (bnk->inactive_idx) { 177*2ab2a32cSAlp Dener ierr = VecGetSubVector(bnk->unprojected_gradient, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 178*2ab2a32cSAlp Dener ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 179*2ab2a32cSAlp Dener } else { 180*2ab2a32cSAlp Dener bnk->G_inactive = bnk->unprojected_gradient; 181*2ab2a32cSAlp Dener bnk->inactive_work = bnk->W; 182*2ab2a32cSAlp Dener } 183*2ab2a32cSAlp Dener ierr = MatMult(bnk->H_inactive, bnk->G_inactive, bnk->inactive_work);CHKERRQ(ierr); 184*2ab2a32cSAlp Dener ierr = VecDot(bnk->G_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr); 185*2ab2a32cSAlp Dener if (bnk->inactive_idx) { 186*2ab2a32cSAlp Dener ierr = VecRestoreSubVector(bnk->unprojected_gradient, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 187*2ab2a32cSAlp Dener ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 188*2ab2a32cSAlp Dener } 189eb910715SAlp Dener prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm)); 190eb910715SAlp Dener actred = bnk->f - ftrial; 191eb910715SAlp Dener if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) { 192eb910715SAlp Dener kappa = 1.0; 193eb910715SAlp Dener } else { 194eb910715SAlp Dener kappa = actred / prered; 195eb910715SAlp Dener } 196eb910715SAlp Dener 197eb910715SAlp Dener tau_1 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust + (1.0 - bnk->theta_i) * prered - actred); 198eb910715SAlp Dener tau_2 = bnk->theta_i * bnk->gnorm * tao->trust / (bnk->theta_i * bnk->gnorm * tao->trust - (1.0 + bnk->theta_i) * prered + actred); 199eb910715SAlp Dener tau_min = PetscMin(tau_1, tau_2); 200eb910715SAlp Dener tau_max = PetscMax(tau_1, tau_2); 201eb910715SAlp Dener 202eb910715SAlp Dener if (PetscAbsScalar(kappa - 1.0) <= bnk->mu1_i) { 203eb910715SAlp Dener /* Great agreement */ 204eb910715SAlp Dener max_radius = PetscMax(max_radius, tao->trust); 205eb910715SAlp Dener 206eb910715SAlp Dener if (tau_max < 1.0) { 207eb910715SAlp Dener tau = bnk->gamma3_i; 208eb910715SAlp Dener } else if (tau_max > bnk->gamma4_i) { 209eb910715SAlp Dener tau = bnk->gamma4_i; 210eb910715SAlp Dener } else if (tau_1 >= 1.0 && tau_1 <= bnk->gamma4_i && tau_2 < 1.0) { 211eb910715SAlp Dener tau = tau_1; 212eb910715SAlp Dener } else if (tau_2 >= 1.0 && tau_2 <= bnk->gamma4_i && tau_1 < 1.0) { 213eb910715SAlp Dener tau = tau_2; 214eb910715SAlp Dener } else { 215eb910715SAlp Dener tau = tau_max; 216eb910715SAlp Dener } 217eb910715SAlp Dener } else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) { 218eb910715SAlp Dener /* Good agreement */ 219eb910715SAlp Dener max_radius = PetscMax(max_radius, tao->trust); 220eb910715SAlp Dener 221eb910715SAlp Dener if (tau_max < bnk->gamma2_i) { 222eb910715SAlp Dener tau = bnk->gamma2_i; 223eb910715SAlp Dener } else if (tau_max > bnk->gamma3_i) { 224eb910715SAlp Dener tau = bnk->gamma3_i; 225eb910715SAlp Dener } else { 226eb910715SAlp Dener tau = tau_max; 227eb910715SAlp Dener } 228eb910715SAlp Dener } else { 229eb910715SAlp Dener /* Not good agreement */ 230eb910715SAlp Dener if (tau_min > 1.0) { 231eb910715SAlp Dener tau = bnk->gamma2_i; 232eb910715SAlp Dener } else if (tau_max < bnk->gamma1_i) { 233eb910715SAlp Dener tau = bnk->gamma1_i; 234eb910715SAlp Dener } else if ((tau_min < bnk->gamma1_i) && (tau_max >= 1.0)) { 235eb910715SAlp Dener tau = bnk->gamma1_i; 236eb910715SAlp Dener } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) { 237eb910715SAlp Dener tau = tau_1; 238eb910715SAlp Dener } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) { 239eb910715SAlp Dener tau = tau_2; 240eb910715SAlp Dener } else { 241eb910715SAlp Dener tau = tau_max; 242eb910715SAlp Dener } 243eb910715SAlp Dener } 244eb910715SAlp Dener } 245eb910715SAlp Dener tao->trust = tau * tao->trust; 246eb910715SAlp Dener } 247eb910715SAlp Dener 2480a4511e9SAlp Dener if (f_min < bnk->f) { 2490a4511e9SAlp Dener bnk->f = f_min; 250eb910715SAlp Dener ierr = VecAXPY(tao->solution,sigma,tao->gradient);CHKERRQ(ierr); 25187602d1eSAlp Dener ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr); 25209164190SAlp Dener ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr); 25309164190SAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 254eb910715SAlp Dener 255eb910715SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 256eb910715SAlp Dener if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN"); 257eb910715SAlp Dener needH = 1; 258eb910715SAlp Dener 259eb910715SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 26028017e9fSAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,1.0);CHKERRQ(ierr); 261eb910715SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 262eb910715SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 263eb910715SAlp Dener } 264eb910715SAlp Dener } 265eb910715SAlp Dener tao->trust = PetscMax(tao->trust, max_radius); 266eb910715SAlp Dener 267eb910715SAlp Dener /* Modify the radius if it is too large or small */ 268eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 269eb910715SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 270eb910715SAlp Dener break; 271eb910715SAlp Dener 272eb910715SAlp Dener default: 273eb910715SAlp Dener /* Norm of the first direction will initialize radius */ 274eb910715SAlp Dener tao->trust = 0.0; 275eb910715SAlp Dener break; 276eb910715SAlp Dener } 277eb910715SAlp Dener } 278eb910715SAlp Dener 279eb910715SAlp Dener /* Set initial scaling for the BFGS preconditioner 280eb910715SAlp Dener This step is done after computing the initial trust-region radius 281eb910715SAlp Dener since the function value may have decreased */ 282eb910715SAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 2839b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 284eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr); 285eb910715SAlp Dener } 286eb910715SAlp Dener 287eb910715SAlp Dener /* Set counter for gradient/reset steps*/ 288eb910715SAlp Dener bnk->newt = 0; 289eb910715SAlp Dener bnk->bfgs = 0; 290eb910715SAlp Dener bnk->sgrad = 0; 291eb910715SAlp Dener bnk->grad = 0; 292eb910715SAlp Dener PetscFunctionReturn(0); 293eb910715SAlp Dener } 294eb910715SAlp Dener 295df278d8fSAlp Dener /*------------------------------------------------------------*/ 296df278d8fSAlp Dener 29762675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */ 29862675beeSAlp Dener 29962675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao) 30062675beeSAlp Dener { 30162675beeSAlp Dener PetscErrorCode ierr; 30262675beeSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 30362675beeSAlp Dener 30462675beeSAlp Dener PetscFunctionBegin; 30562675beeSAlp Dener /* Compute the Hessian */ 30662675beeSAlp Dener ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 30762675beeSAlp Dener /* Add a correction to the BFGS preconditioner */ 30862675beeSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 30962675beeSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 31062675beeSAlp Dener /* Update the BFGS diagonal scaling */ 31162675beeSAlp Dener if (BFGS_SCALE_AHESS == bnk->bfgs_scale_type) { 31262675beeSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr); 31362675beeSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 31462675beeSAlp Dener ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr); 31562675beeSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 31662675beeSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 31762675beeSAlp Dener } 31862675beeSAlp Dener } 31962675beeSAlp Dener PetscFunctionReturn(0); 32062675beeSAlp Dener } 32162675beeSAlp Dener 32262675beeSAlp Dener /*------------------------------------------------------------*/ 32362675beeSAlp Dener 3242f75a4aaSAlp Dener /* Routine for estimating the active set */ 3252f75a4aaSAlp Dener 3262f75a4aaSAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao) 3272f75a4aaSAlp Dener { 3282f75a4aaSAlp Dener PetscErrorCode ierr; 3292f75a4aaSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 3302f75a4aaSAlp Dener 3312f75a4aaSAlp Dener PetscFunctionBegin; 3322f75a4aaSAlp Dener switch (bnk->as_type) { 3332f75a4aaSAlp Dener case BNK_AS_NONE: 3342f75a4aaSAlp Dener ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr); 3352f75a4aaSAlp Dener ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr); 3362f75a4aaSAlp Dener ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr); 3372f75a4aaSAlp Dener ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr); 3382f75a4aaSAlp Dener break; 3392f75a4aaSAlp Dener 3402f75a4aaSAlp Dener case BNK_AS_BERTSEKAS: 3412f75a4aaSAlp Dener /* Compute the trial step vector with which we will estimate the active set at the next iteration */ 3422f75a4aaSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 3432f75a4aaSAlp Dener /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */ 3445e9b73cbSAlp Dener ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr); 3452f75a4aaSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr); 3462f75a4aaSAlp Dener } else { 3479b6ef848SAlp Dener /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */ 3482f75a4aaSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr); 3499b6ef848SAlp Dener ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr); 3509b6ef848SAlp Dener ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr); 3512f75a4aaSAlp Dener ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr); 3522f75a4aaSAlp Dener ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr); 3532f75a4aaSAlp Dener } 3542f75a4aaSAlp Dener ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr); 3550a4511e9SAlp 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); 3562f75a4aaSAlp Dener 3572f75a4aaSAlp Dener default: 3582f75a4aaSAlp Dener break; 3592f75a4aaSAlp Dener } 3602f75a4aaSAlp Dener PetscFunctionReturn(0); 3612f75a4aaSAlp Dener } 3622f75a4aaSAlp Dener 3632f75a4aaSAlp Dener /*------------------------------------------------------------*/ 3642f75a4aaSAlp Dener 3652f75a4aaSAlp Dener /* Routine for bounding the step direction */ 3662f75a4aaSAlp Dener 3672f75a4aaSAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, Vec step) 3682f75a4aaSAlp Dener { 3692f75a4aaSAlp Dener PetscErrorCode ierr; 3702f75a4aaSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 3712f75a4aaSAlp Dener 3722f75a4aaSAlp Dener PetscFunctionBegin; 37328017e9fSAlp Dener if (bnk->active_idx) { 3742f75a4aaSAlp Dener switch (bnk->as_type) { 3752f75a4aaSAlp Dener case BNK_AS_NONE: 3762f75a4aaSAlp Dener if (bnk->active_idx) { 3772f75a4aaSAlp Dener ierr = VecGetSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr); 3782f75a4aaSAlp Dener ierr = VecSet(bnk->active_work, 0.0);CHKERRQ(ierr); 3792f75a4aaSAlp Dener ierr = VecRestoreSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr); 3802f75a4aaSAlp Dener } 3812f75a4aaSAlp Dener break; 3822f75a4aaSAlp Dener 3832f75a4aaSAlp Dener case BNK_AS_BERTSEKAS: 3842f75a4aaSAlp Dener ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, step);CHKERRQ(ierr); 3852f75a4aaSAlp Dener break; 3862f75a4aaSAlp Dener 3872f75a4aaSAlp Dener default: 3882f75a4aaSAlp Dener break; 3892f75a4aaSAlp Dener } 390e465cd6fSAlp Dener } 3912f75a4aaSAlp Dener PetscFunctionReturn(0); 3922f75a4aaSAlp Dener } 3932f75a4aaSAlp Dener 3942f75a4aaSAlp Dener /*------------------------------------------------------------*/ 3952f75a4aaSAlp Dener 396df278d8fSAlp Dener /* Routine for computing the Newton step. 397df278d8fSAlp Dener 398df278d8fSAlp Dener If the safeguard is enabled, the Newton step is verified to be a 399df278d8fSAlp Dener descent direction, with fallbacks onto BFGS, scaled gradient, and unscaled 400df278d8fSAlp Dener gradient steps if/when necessary. 401df278d8fSAlp Dener 402df278d8fSAlp Dener The function reports back on which type of step has ultimately been stored 403df278d8fSAlp Dener under tao->stepdirection. 404df278d8fSAlp Dener */ 405df278d8fSAlp Dener 40662675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason) 407eb910715SAlp Dener { 408eb910715SAlp Dener PetscErrorCode ierr; 409eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 410eb910715SAlp Dener 411e465cd6fSAlp Dener PetscReal delta; 412eb910715SAlp Dener PetscInt bfgsUpdates = 0; 413eb910715SAlp Dener PetscInt kspits; 414eb910715SAlp Dener 415eb910715SAlp Dener PetscFunctionBegin; 4162f75a4aaSAlp Dener /* Determine the active and inactive sets */ 4172f75a4aaSAlp Dener ierr = TaoBNKEstimateActiveSet(tao);CHKERRQ(ierr); 41809164190SAlp Dener 4195e9b73cbSAlp Dener /* Prepare the reduced sub-matrices for the inactive set */ 4202f75a4aaSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { ierr = MatLMVMSetInactive(bnk->M, bnk->inactive_idx);CHKERRQ(ierr); } 4212f75a4aaSAlp Dener if (bnk->inactive_idx) { 4225e9b73cbSAlp Dener ierr = MatDestroy(&bnk->H_inactive); 4235e9b73cbSAlp Dener ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr); 424eb3ba6a7SAlp Dener if (tao->hessian == tao->hessian_pre) { 425eb3ba6a7SAlp Dener bnk->Hpre_inactive = bnk->H_inactive; 426eb3ba6a7SAlp Dener } else { 4275e9b73cbSAlp Dener ierr = MatDestroy(&bnk->Hpre_inactive); 4285e9b73cbSAlp Dener ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr); 429eb3ba6a7SAlp Dener } 4302f75a4aaSAlp Dener } else { 43162675beeSAlp Dener ierr = MatDestroy(&bnk->H_inactive); 43262675beeSAlp Dener ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive); 43362675beeSAlp Dener if (tao->hessian == tao->hessian_pre) { 43462675beeSAlp Dener bnk->Hpre_inactive = bnk->H_inactive; 43562675beeSAlp Dener } else { 43662675beeSAlp Dener ierr = MatDestroy(&bnk->Hpre_inactive); 43762675beeSAlp Dener ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive); 43862675beeSAlp Dener } 43962675beeSAlp Dener } 44062675beeSAlp Dener 44162675beeSAlp Dener /* Shift the reduced Hessian matrix */ 44262675beeSAlp Dener if ((shift) && (bnk->pert > 0)) { 44362675beeSAlp Dener ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr); 44462675beeSAlp Dener if (bnk->H_inactive != bnk->Hpre_inactive) { 44562675beeSAlp Dener ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr); 44662675beeSAlp Dener } 44762675beeSAlp Dener } 44862675beeSAlp Dener 44962675beeSAlp Dener /* Update the diagonal scaling for the BFGS preconditioner, this time with the Hessian perturbation */ 45062675beeSAlp Dener if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_PHESS == bnk->bfgs_scale_type)) { 45162675beeSAlp Dener /* Obtain diagonal for the bfgs preconditioner */ 4525e9b73cbSAlp Dener ierr = VecSet(bnk->Diag, 1.0);CHKERRQ(ierr); 4535e9b73cbSAlp Dener if (bnk->inactive_idx) { 4545e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr); 4555e9b73cbSAlp Dener } else { 4565e9b73cbSAlp Dener bnk->Diag_red = bnk->Diag; 4575e9b73cbSAlp Dener } 4585e9b73cbSAlp Dener ierr = MatGetDiagonal(bnk->H_inactive, bnk->Diag_red);CHKERRQ(ierr); 4595e9b73cbSAlp Dener if (bnk->inactive_idx) { 4605e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr); 4615e9b73cbSAlp Dener } 46262675beeSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 46362675beeSAlp Dener ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr); 46462675beeSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 46562675beeSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 4662f75a4aaSAlp Dener } 46709164190SAlp Dener 468eb910715SAlp Dener /* Solve the Newton system of equations */ 4692f75a4aaSAlp Dener ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr); 4705e9b73cbSAlp Dener ierr = KSPReset(tao->ksp);CHKERRQ(ierr); 47109164190SAlp Dener ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr); 4725e9b73cbSAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr); 4735e9b73cbSAlp Dener if (bnk->inactive_idx) { 4745e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 4755e9b73cbSAlp Dener ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 4765e9b73cbSAlp Dener } else { 4775e9b73cbSAlp Dener bnk->G_inactive = bnk->unprojected_gradient; 4785e9b73cbSAlp Dener bnk->X_inactive = tao->stepdirection; 47928017e9fSAlp Dener } 480eb910715SAlp Dener if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) { 481fed79b8eSAlp Dener ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); 4825e9b73cbSAlp Dener ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr); 483eb910715SAlp Dener ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr); 484eb910715SAlp Dener tao->ksp_its+=kspits; 485eb910715SAlp Dener tao->ksp_tot_its+=kspits; 486080d2917SAlp Dener ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr); 487eb910715SAlp Dener 488eb910715SAlp Dener if (0.0 == tao->trust) { 489eb910715SAlp Dener /* Radius was uninitialized; use the norm of the direction */ 490080d2917SAlp Dener if (bnk->dnorm > 0.0) { 491080d2917SAlp Dener tao->trust = bnk->dnorm; 492eb910715SAlp Dener 493eb910715SAlp Dener /* Modify the radius if it is too large or small */ 494eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 495eb910715SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 496eb910715SAlp Dener } else { 497eb910715SAlp Dener /* The direction was bad; set radius to default value and re-solve 498eb910715SAlp Dener the trust-region subproblem to get a direction */ 499eb910715SAlp Dener tao->trust = tao->trust0; 500eb910715SAlp Dener 501eb910715SAlp Dener /* Modify the radius if it is too large or small */ 502eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 503eb910715SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 504eb910715SAlp Dener 505fed79b8eSAlp Dener ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); 5065e9b73cbSAlp Dener ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr); 507eb910715SAlp Dener ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr); 508eb910715SAlp Dener tao->ksp_its+=kspits; 509eb910715SAlp Dener tao->ksp_tot_its+=kspits; 510080d2917SAlp Dener ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr); 511eb910715SAlp Dener 512080d2917SAlp Dener if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero"); 513eb910715SAlp Dener } 514eb910715SAlp Dener } 515eb910715SAlp Dener } else { 5165e9b73cbSAlp Dener ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr); 517eb910715SAlp Dener ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr); 518eb910715SAlp Dener tao->ksp_its += kspits; 519eb910715SAlp Dener tao->ksp_tot_its+=kspits; 520eb910715SAlp Dener } 5215e9b73cbSAlp Dener /* Restore sub vectors back */ 5225e9b73cbSAlp Dener if (bnk->inactive_idx) { 5235e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 5245e9b73cbSAlp Dener ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 5255e9b73cbSAlp Dener } 526770b7498SAlp Dener /* Make sure the safeguarded fall-back step is zero for actively bounded variables */ 527fed79b8eSAlp Dener ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 5282f75a4aaSAlp Dener ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr); 529770b7498SAlp Dener 530770b7498SAlp Dener /* Record convergence reasons */ 531e465cd6fSAlp Dener ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr); 532e465cd6fSAlp Dener if (KSP_CONVERGED_ATOL == *ksp_reason) { 533770b7498SAlp Dener ++bnk->ksp_atol; 534e465cd6fSAlp Dener } else if (KSP_CONVERGED_RTOL == *ksp_reason) { 535770b7498SAlp Dener ++bnk->ksp_rtol; 536e465cd6fSAlp Dener } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) { 537770b7498SAlp Dener ++bnk->ksp_ctol; 538e465cd6fSAlp Dener } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) { 539770b7498SAlp Dener ++bnk->ksp_negc; 540e465cd6fSAlp Dener } else if (KSP_DIVERGED_DTOL == *ksp_reason) { 541770b7498SAlp Dener ++bnk->ksp_dtol; 542e465cd6fSAlp Dener } else if (KSP_DIVERGED_ITS == *ksp_reason) { 543770b7498SAlp Dener ++bnk->ksp_iter; 544770b7498SAlp Dener } else { 545770b7498SAlp Dener ++bnk->ksp_othr; 546770b7498SAlp Dener } 547fed79b8eSAlp Dener 548fed79b8eSAlp Dener /* Make sure the BFGS preconditioner is healthy */ 549fed79b8eSAlp Dener if (bnk->pc_type == BNK_PC_BFGS) { 550fed79b8eSAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 551e465cd6fSAlp Dener if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 1)) { 552fed79b8eSAlp Dener /* Preconditioner is numerically indefinite; reset the approximation. */ 5539b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 554eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr); 555eb910715SAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 55609164190SAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 557eb910715SAlp Dener } 558fed79b8eSAlp Dener } 559e465cd6fSAlp Dener PetscFunctionReturn(0); 560e465cd6fSAlp Dener } 561eb910715SAlp Dener 56262675beeSAlp Dener /*------------------------------------------------------------*/ 56362675beeSAlp Dener 5645e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */ 5655e9b73cbSAlp Dener 5665e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered) 5675e9b73cbSAlp Dener { 5685e9b73cbSAlp Dener PetscErrorCode ierr; 5695e9b73cbSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 5705e9b73cbSAlp Dener 5715e9b73cbSAlp Dener PetscFunctionBegin; 5725e9b73cbSAlp Dener /* Extract subvectors associated with the inactive set */ 5735e9b73cbSAlp Dener if (bnk->inactive_idx){ 5745e9b73cbSAlp Dener ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 5755e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 5765e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 5775e9b73cbSAlp Dener } else { 5785e9b73cbSAlp Dener bnk->X_inactive = tao->stepdirection; 5795e9b73cbSAlp Dener bnk->inactive_work = bnk->Xwork; 5805e9b73cbSAlp Dener bnk->G_inactive = bnk->Gwork; 5815e9b73cbSAlp Dener } 5825e9b73cbSAlp Dener /* Recompute the predicted decrease based on the quadratic model */ 5835e9b73cbSAlp Dener ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr); 5845e9b73cbSAlp Dener ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr); 5855e9b73cbSAlp Dener ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered); 5865e9b73cbSAlp Dener /* Restore the sub vectors */ 5875e9b73cbSAlp Dener if (bnk->inactive_idx){ 5885e9b73cbSAlp Dener ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 5895e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 5905e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 5915e9b73cbSAlp Dener } 5925e9b73cbSAlp Dener PetscFunctionReturn(0); 5935e9b73cbSAlp Dener } 5945e9b73cbSAlp Dener 5955e9b73cbSAlp Dener /*------------------------------------------------------------*/ 5965e9b73cbSAlp Dener 59762675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction. 59862675beeSAlp Dener 59962675beeSAlp Dener The step direction falls back onto BFGS, scaled gradient and gradient steps 60062675beeSAlp Dener in the event that the Newton step fails the test. 60162675beeSAlp Dener */ 60262675beeSAlp Dener 603e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType) 604e465cd6fSAlp Dener { 605e465cd6fSAlp Dener PetscErrorCode ierr; 606e465cd6fSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 607e465cd6fSAlp Dener 608e465cd6fSAlp Dener PetscReal gdx, delta, e_min; 609e465cd6fSAlp Dener PetscInt bfgsUpdates; 610e465cd6fSAlp Dener 611e465cd6fSAlp Dener PetscFunctionBegin; 612080d2917SAlp Dener ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr); 613eb910715SAlp Dener if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) { 614eb910715SAlp Dener /* Newton step is not descent or direction produced Inf or NaN 615eb910715SAlp Dener Update the perturbation for next time */ 616eb910715SAlp Dener if (bnk->pert <= 0.0) { 617eb910715SAlp Dener /* Initialize the perturbation */ 618eb910715SAlp Dener bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm)); 619eb910715SAlp Dener if (bnk->is_gltr) { 620eb910715SAlp Dener ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr); 621eb910715SAlp Dener bnk->pert = PetscMax(bnk->pert, -e_min); 622eb910715SAlp Dener } 623eb910715SAlp Dener } else { 624eb910715SAlp Dener /* Increase the perturbation */ 625eb910715SAlp Dener bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm)); 626eb910715SAlp Dener } 627eb910715SAlp Dener 628eb910715SAlp Dener if (BNK_PC_BFGS != bnk->pc_type) { 629eb910715SAlp Dener /* We don't have the bfgs matrix around and updated 630eb910715SAlp Dener Must use gradient direction in this case */ 631080d2917SAlp Dener ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr); 632eb910715SAlp Dener *stepType = BNK_GRADIENT; 633eb910715SAlp Dener } else { 634eb910715SAlp Dener /* Attempt to use the BFGS direction */ 635*2ab2a32cSAlp Dener ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr); 63609164190SAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 637eb910715SAlp Dener 6388d5ead36SAlp Dener /* Check for success (descent direction) 6398d5ead36SAlp Dener NOTE: Negative gdx here means not a descent direction because 6408d5ead36SAlp Dener the fall-back step is missing a negative sign. */ 641080d2917SAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr); 6428d5ead36SAlp Dener if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) { 643eb910715SAlp Dener /* BFGS direction is not descent or direction produced not a number 644eb910715SAlp Dener We can assert bfgsUpdates > 1 in this case because 645eb910715SAlp Dener the first solve produces the scaled gradient direction, 646eb910715SAlp Dener which is guaranteed to be descent */ 647eb910715SAlp Dener 648eb910715SAlp Dener /* Use steepest descent direction (scaled) */ 6499b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 650eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 651eb910715SAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 65209164190SAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 65309164190SAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 654eb910715SAlp Dener 655eb910715SAlp Dener *stepType = BNK_SCALED_GRADIENT; 656eb910715SAlp Dener } else { 657770b7498SAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 658eb910715SAlp Dener if (1 == bfgsUpdates) { 659eb910715SAlp Dener /* The first BFGS direction is always the scaled gradient */ 660eb910715SAlp Dener *stepType = BNK_SCALED_GRADIENT; 661eb910715SAlp Dener } else { 662eb910715SAlp Dener *stepType = BNK_BFGS; 663eb910715SAlp Dener } 664eb910715SAlp Dener } 665eb910715SAlp Dener } 6668d5ead36SAlp Dener /* Make sure the safeguarded fall-back step is zero for actively bounded variables */ 6678d5ead36SAlp Dener ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 6682f75a4aaSAlp Dener ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr); 669eb910715SAlp Dener } else { 670eb910715SAlp Dener /* Computed Newton step is descent */ 671eb910715SAlp Dener switch (ksp_reason) { 672eb910715SAlp Dener case KSP_DIVERGED_NANORINF: 673eb910715SAlp Dener case KSP_DIVERGED_BREAKDOWN: 674eb910715SAlp Dener case KSP_DIVERGED_INDEFINITE_MAT: 675eb910715SAlp Dener case KSP_DIVERGED_INDEFINITE_PC: 676eb910715SAlp Dener case KSP_CONVERGED_CG_NEG_CURVE: 677eb910715SAlp Dener /* Matrix or preconditioner is indefinite; increase perturbation */ 678eb910715SAlp Dener if (bnk->pert <= 0.0) { 679eb910715SAlp Dener /* Initialize the perturbation */ 680eb910715SAlp Dener bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm)); 681eb910715SAlp Dener if (bnk->is_gltr) { 682eb910715SAlp Dener ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr); 683eb910715SAlp Dener bnk->pert = PetscMax(bnk->pert, -e_min); 684eb910715SAlp Dener } 685eb910715SAlp Dener } else { 686eb910715SAlp Dener /* Increase the perturbation */ 687eb910715SAlp Dener bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm)); 688eb910715SAlp Dener } 689eb910715SAlp Dener break; 690eb910715SAlp Dener 691eb910715SAlp Dener default: 692eb910715SAlp Dener /* Newton step computation is good; decrease perturbation */ 693eb910715SAlp Dener bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm); 694eb910715SAlp Dener if (bnk->pert < bnk->pmin) { 695eb910715SAlp Dener bnk->pert = 0.0; 696eb910715SAlp Dener } 697eb910715SAlp Dener break; 698eb910715SAlp Dener } 699fed79b8eSAlp Dener *stepType = BNK_NEWTON; 700eb910715SAlp Dener } 701eb910715SAlp Dener PetscFunctionReturn(0); 702eb910715SAlp Dener } 703eb910715SAlp Dener 704df278d8fSAlp Dener /*------------------------------------------------------------*/ 705df278d8fSAlp Dener 706df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search. 707df278d8fSAlp Dener 708df278d8fSAlp Dener Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the 709df278d8fSAlp Dener Newton step does not produce a valid step length. 710df278d8fSAlp Dener */ 711df278d8fSAlp Dener 712c14b763aSAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason) 713c14b763aSAlp Dener { 714c14b763aSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 715c14b763aSAlp Dener PetscErrorCode ierr; 716c14b763aSAlp Dener TaoLineSearchConvergedReason ls_reason; 717c14b763aSAlp Dener 718c14b763aSAlp Dener PetscReal e_min, gdx, delta; 719c14b763aSAlp Dener PetscInt bfgsUpdates; 720c14b763aSAlp Dener 721c14b763aSAlp Dener PetscFunctionBegin; 722c14b763aSAlp Dener /* Perform the linesearch */ 723c14b763aSAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr); 724c14b763aSAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 725c14b763aSAlp Dener 7269b6ef848SAlp Dener while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && (stepType != BNK_GRADIENT || stepType !=BNK_SCALED_GRADIENT)) { 727c14b763aSAlp Dener /* Linesearch failed, revert solution */ 728c14b763aSAlp Dener bnk->f = bnk->fold; 729c14b763aSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 730c14b763aSAlp Dener ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr); 731c14b763aSAlp Dener 732c14b763aSAlp Dener switch(stepType) { 733c14b763aSAlp Dener case BNK_NEWTON: 7348d5ead36SAlp Dener /* Failed to obtain acceptable iterate with Newton step 735c14b763aSAlp Dener Update the perturbation for next time */ 736c14b763aSAlp Dener if (bnk->pert <= 0.0) { 737c14b763aSAlp Dener /* Initialize the perturbation */ 738c14b763aSAlp Dener bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm)); 739c14b763aSAlp Dener if (bnk->is_gltr) { 740c14b763aSAlp Dener ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr); 741c14b763aSAlp Dener bnk->pert = PetscMax(bnk->pert, -e_min); 742c14b763aSAlp Dener } 743c14b763aSAlp Dener } else { 744c14b763aSAlp Dener /* Increase the perturbation */ 745c14b763aSAlp Dener bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm)); 746c14b763aSAlp Dener } 747c14b763aSAlp Dener 748c14b763aSAlp Dener if (BNK_PC_BFGS != bnk->pc_type) { 749c14b763aSAlp Dener /* We don't have the bfgs matrix around and being updated 750c14b763aSAlp Dener Must use gradient direction in this case */ 751c14b763aSAlp Dener ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr); 752c14b763aSAlp Dener stepType = BNK_GRADIENT; 753c14b763aSAlp Dener } else { 754c14b763aSAlp Dener /* Attempt to use the BFGS direction */ 755c14b763aSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 7568d5ead36SAlp Dener /* Check for success (descent direction) 7578d5ead36SAlp Dener NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */ 758c14b763aSAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr); 759c14b763aSAlp Dener if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) { 760c14b763aSAlp Dener /* BFGS direction is not descent or direction produced not a number 761c14b763aSAlp Dener We can assert bfgsUpdates > 1 in this case 762c14b763aSAlp Dener Use steepest descent direction (scaled) */ 7639b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 764c14b763aSAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 765c14b763aSAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 766c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 767c14b763aSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 768c14b763aSAlp Dener 769c14b763aSAlp Dener bfgsUpdates = 1; 770c14b763aSAlp Dener stepType = BNK_SCALED_GRADIENT; 771c14b763aSAlp Dener } else { 772c14b763aSAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 773c14b763aSAlp Dener if (1 == bfgsUpdates) { 774c14b763aSAlp Dener /* The first BFGS direction is always the scaled gradient */ 775c14b763aSAlp Dener stepType = BNK_SCALED_GRADIENT; 776c14b763aSAlp Dener } else { 777c14b763aSAlp Dener stepType = BNK_BFGS; 778c14b763aSAlp Dener } 779c14b763aSAlp Dener } 780c14b763aSAlp Dener } 781c14b763aSAlp Dener break; 782c14b763aSAlp Dener 783c14b763aSAlp Dener case BNK_BFGS: 784c14b763aSAlp Dener /* Can only enter if pc_type == BNK_PC_BFGS 785c14b763aSAlp Dener Failed to obtain acceptable iterate with BFGS step 786c14b763aSAlp Dener Attempt to use the scaled gradient direction */ 7879b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 788c14b763aSAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 789c14b763aSAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 790c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 791c14b763aSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 792c14b763aSAlp Dener 793c14b763aSAlp Dener bfgsUpdates = 1; 794c14b763aSAlp Dener stepType = BNK_SCALED_GRADIENT; 795c14b763aSAlp Dener break; 796c14b763aSAlp Dener 797c14b763aSAlp Dener case BNK_SCALED_GRADIENT: 798c14b763aSAlp Dener /* Can only enter if pc_type == BNK_PC_BFGS 799c14b763aSAlp Dener The scaled gradient step did not produce a new iterate; 800c14b763aSAlp Dener attemp to use the gradient direction. 801c14b763aSAlp Dener Need to make sure we are not using a different diagonal scaling */ 802c14b763aSAlp Dener ierr = MatLMVMSetScale(bnk->M,0);CHKERRQ(ierr); 803c14b763aSAlp Dener ierr = MatLMVMSetDelta(bnk->M,1.0);CHKERRQ(ierr); 804c14b763aSAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 805c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 806c14b763aSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 807c14b763aSAlp Dener 808c14b763aSAlp Dener bfgsUpdates = 1; 809c14b763aSAlp Dener stepType = BNK_GRADIENT; 810c14b763aSAlp Dener break; 811c14b763aSAlp Dener } 8128d5ead36SAlp Dener /* Make sure the safeguarded fall-back step is zero for actively bounded variables */ 8138d5ead36SAlp Dener ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 8142f75a4aaSAlp Dener ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr); 815c14b763aSAlp Dener 8168d5ead36SAlp Dener /* Perform one last line search with the fall-back step */ 817c14b763aSAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr); 818c14b763aSAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 819c14b763aSAlp Dener } 820c14b763aSAlp Dener *reason = ls_reason; 821c14b763aSAlp Dener PetscFunctionReturn(0); 822c14b763aSAlp Dener } 823c14b763aSAlp Dener 824df278d8fSAlp Dener /*------------------------------------------------------------*/ 825df278d8fSAlp Dener 826df278d8fSAlp Dener /* Routine for updating the trust radius. 827df278d8fSAlp Dener 828df278d8fSAlp Dener Function features three different update methods: 829df278d8fSAlp Dener 1) Line-search step length based 830df278d8fSAlp Dener 2) Predicted decrease on the CG quadratic model 831df278d8fSAlp Dener 3) Interpolation 832df278d8fSAlp Dener */ 833df278d8fSAlp Dener 83428017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept) 835080d2917SAlp Dener { 836080d2917SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 837080d2917SAlp Dener PetscErrorCode ierr; 838080d2917SAlp Dener 839b1c2d0e3SAlp Dener PetscReal step, kappa; 840080d2917SAlp Dener PetscReal gdx, tau_1, tau_2, tau_min, tau_max; 841080d2917SAlp Dener 842080d2917SAlp Dener PetscFunctionBegin; 843080d2917SAlp Dener /* Update trust region radius */ 844080d2917SAlp Dener *accept = PETSC_FALSE; 84528017e9fSAlp Dener switch(updateType) { 846080d2917SAlp Dener case BNK_UPDATE_STEP: 847c14b763aSAlp Dener *accept = PETSC_TRUE; /* always accept here because line search succeeded */ 848080d2917SAlp Dener if (stepType == BNK_NEWTON) { 849080d2917SAlp Dener ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr); 850080d2917SAlp Dener if (step < bnk->nu1) { 851080d2917SAlp Dener /* Very bad step taken; reduce radius */ 852080d2917SAlp Dener tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust); 853080d2917SAlp Dener } else if (step < bnk->nu2) { 854080d2917SAlp Dener /* Reasonably bad step taken; reduce radius */ 855080d2917SAlp Dener tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust); 856080d2917SAlp Dener } else if (step < bnk->nu3) { 857080d2917SAlp Dener /* Reasonable step was taken; leave radius alone */ 858080d2917SAlp Dener if (bnk->omega3 < 1.0) { 859080d2917SAlp Dener tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust); 860080d2917SAlp Dener } else if (bnk->omega3 > 1.0) { 861080d2917SAlp Dener tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust); 862080d2917SAlp Dener } 863080d2917SAlp Dener } else if (step < bnk->nu4) { 864080d2917SAlp Dener /* Full step taken; increase the radius */ 865080d2917SAlp Dener tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust); 866080d2917SAlp Dener } else { 867080d2917SAlp Dener /* More than full step taken; increase the radius */ 868080d2917SAlp Dener tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust); 869080d2917SAlp Dener } 870080d2917SAlp Dener } else { 871080d2917SAlp Dener /* Newton step was not good; reduce the radius */ 872080d2917SAlp Dener tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust); 873080d2917SAlp Dener } 874080d2917SAlp Dener break; 875080d2917SAlp Dener 876080d2917SAlp Dener case BNK_UPDATE_REDUCTION: 877080d2917SAlp Dener if (stepType == BNK_NEWTON) { 878b1c2d0e3SAlp Dener if (prered < 0.0) { 879fed79b8eSAlp Dener /* The predicted reduction has the wrong sign. This cannot 880fed79b8eSAlp Dener happen in infinite precision arithmetic. Step should 881fed79b8eSAlp Dener be rejected! */ 882080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm); 883fed79b8eSAlp Dener } 884fed79b8eSAlp Dener else { 885b1c2d0e3SAlp Dener if (PetscIsInfOrNanReal(actred)) { 886080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm); 887080d2917SAlp Dener } else { 8880a4511e9SAlp Dener if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) && 8890a4511e9SAlp Dener (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) { 890080d2917SAlp Dener kappa = 1.0; 891fed79b8eSAlp Dener } 892fed79b8eSAlp Dener else { 893080d2917SAlp Dener kappa = actred / prered; 894080d2917SAlp Dener } 895fed79b8eSAlp Dener 896fed79b8eSAlp Dener /* Accept or reject the step and update radius */ 897080d2917SAlp Dener if (kappa < bnk->eta1) { 898fed79b8eSAlp Dener /* Reject the step */ 899080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm); 900fed79b8eSAlp Dener } 901fed79b8eSAlp Dener else { 902fed79b8eSAlp Dener /* Accept the step */ 903c133c014SAlp Dener *accept = PETSC_TRUE; 904c133c014SAlp Dener /* Update the trust region radius only if the computed step is at the trust radius boundary */ 9058d5ead36SAlp Dener if (bnk->dnorm == tao->trust) { 906080d2917SAlp Dener if (kappa < bnk->eta2) { 907080d2917SAlp Dener /* Marginal bad step */ 908c133c014SAlp Dener tao->trust = bnk->alpha2 * tao->trust; 909080d2917SAlp Dener } 910fed79b8eSAlp Dener else if (kappa < bnk->eta3) { 911fed79b8eSAlp Dener /* Reasonable step */ 912fed79b8eSAlp Dener tao->trust = bnk->alpha3 * tao->trust; 913fed79b8eSAlp Dener } 914fed79b8eSAlp Dener else if (kappa < bnk->eta4) { 915080d2917SAlp Dener /* Good step */ 916c133c014SAlp Dener tao->trust = bnk->alpha4 * tao->trust; 917fed79b8eSAlp Dener } 918fed79b8eSAlp Dener else { 919080d2917SAlp Dener /* Very good step */ 920c133c014SAlp Dener tao->trust = bnk->alpha5 * tao->trust; 921080d2917SAlp Dener } 922c133c014SAlp Dener } 923080d2917SAlp Dener } 924080d2917SAlp Dener } 925080d2917SAlp Dener } 926080d2917SAlp Dener } else { 927080d2917SAlp Dener /* Newton step was not good; reduce the radius */ 928080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust); 929080d2917SAlp Dener } 930080d2917SAlp Dener break; 931080d2917SAlp Dener 932080d2917SAlp Dener default: 933080d2917SAlp Dener if (stepType == BNK_NEWTON) { 934b1c2d0e3SAlp Dener if (prered < 0.0) { 935080d2917SAlp Dener /* The predicted reduction has the wrong sign. This cannot */ 936080d2917SAlp Dener /* happen in infinite precision arithmetic. Step should */ 937080d2917SAlp Dener /* be rejected! */ 938080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 939080d2917SAlp Dener } else { 940b1c2d0e3SAlp Dener if (PetscIsInfOrNanReal(actred)) { 941080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 942080d2917SAlp Dener } else { 943080d2917SAlp Dener if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) { 944080d2917SAlp Dener kappa = 1.0; 945080d2917SAlp Dener } else { 946080d2917SAlp Dener kappa = actred / prered; 947080d2917SAlp Dener } 948080d2917SAlp Dener 949080d2917SAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr); 950080d2917SAlp Dener tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred); 951080d2917SAlp Dener tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred); 952080d2917SAlp Dener tau_min = PetscMin(tau_1, tau_2); 953080d2917SAlp Dener tau_max = PetscMax(tau_1, tau_2); 954080d2917SAlp Dener 955080d2917SAlp Dener if (kappa >= 1.0 - bnk->mu1) { 956080d2917SAlp Dener /* Great agreement */ 957080d2917SAlp Dener *accept = PETSC_TRUE; 958080d2917SAlp Dener if (tau_max < 1.0) { 959080d2917SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm); 960080d2917SAlp Dener } else if (tau_max > bnk->gamma4) { 961080d2917SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm); 962080d2917SAlp Dener } else { 963080d2917SAlp Dener tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm); 964080d2917SAlp Dener } 965080d2917SAlp Dener } else if (kappa >= 1.0 - bnk->mu2) { 966080d2917SAlp Dener /* Good agreement */ 967080d2917SAlp Dener *accept = PETSC_TRUE; 968080d2917SAlp Dener if (tau_max < bnk->gamma2) { 969080d2917SAlp Dener tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm); 970080d2917SAlp Dener } else if (tau_max > bnk->gamma3) { 971080d2917SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm); 972080d2917SAlp Dener } else if (tau_max < 1.0) { 973080d2917SAlp Dener tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm); 974080d2917SAlp Dener } else { 975080d2917SAlp Dener tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm); 976080d2917SAlp Dener } 977080d2917SAlp Dener } else { 978080d2917SAlp Dener /* Not good agreement */ 979080d2917SAlp Dener if (tau_min > 1.0) { 980080d2917SAlp Dener tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm); 981080d2917SAlp Dener } else if (tau_max < bnk->gamma1) { 982080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 983080d2917SAlp Dener } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) { 984080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 985080d2917SAlp Dener } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) { 986080d2917SAlp Dener tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm); 987080d2917SAlp Dener } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) { 988080d2917SAlp Dener tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm); 989080d2917SAlp Dener } else { 990080d2917SAlp Dener tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm); 991080d2917SAlp Dener } 992080d2917SAlp Dener } 993080d2917SAlp Dener } 994080d2917SAlp Dener } 995080d2917SAlp Dener } else { 996080d2917SAlp Dener /* Newton step was not good; reduce the radius */ 997080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust); 998080d2917SAlp Dener } 99928017e9fSAlp Dener break; 1000080d2917SAlp Dener } 1001c133c014SAlp Dener /* Make sure the radius does not violate min and max settings */ 1002c133c014SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 1003fed79b8eSAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 1004080d2917SAlp Dener PetscFunctionReturn(0); 1005080d2917SAlp Dener } 1006080d2917SAlp Dener 1007eb910715SAlp Dener /* ---------------------------------------------------------- */ 1008df278d8fSAlp Dener 100962675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType) 101062675beeSAlp Dener { 101162675beeSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 101262675beeSAlp Dener 101362675beeSAlp Dener PetscFunctionBegin; 101462675beeSAlp Dener switch (stepType) { 101562675beeSAlp Dener case BNK_NEWTON: 101662675beeSAlp Dener ++bnk->newt; 101762675beeSAlp Dener break; 101862675beeSAlp Dener case BNK_BFGS: 101962675beeSAlp Dener ++bnk->bfgs; 102062675beeSAlp Dener break; 102162675beeSAlp Dener case BNK_SCALED_GRADIENT: 102262675beeSAlp Dener ++bnk->sgrad; 102362675beeSAlp Dener break; 102462675beeSAlp Dener case BNK_GRADIENT: 102562675beeSAlp Dener ++bnk->grad; 102662675beeSAlp Dener break; 102762675beeSAlp Dener default: 102862675beeSAlp Dener break; 102962675beeSAlp Dener } 103062675beeSAlp Dener PetscFunctionReturn(0); 103162675beeSAlp Dener } 103262675beeSAlp Dener 103362675beeSAlp Dener /* ---------------------------------------------------------- */ 103462675beeSAlp Dener 10359b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao) 1036eb910715SAlp Dener { 1037eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1038eb910715SAlp Dener PetscErrorCode ierr; 10399b6ef848SAlp Dener KSPType ksp_type; 1040eb910715SAlp Dener 1041eb910715SAlp Dener PetscFunctionBegin; 1042eb910715SAlp Dener if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);} 1043eb910715SAlp Dener if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);} 1044eb910715SAlp Dener if (!bnk->W) {ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);} 1045eb910715SAlp Dener if (!bnk->Xold) {ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);} 1046eb910715SAlp Dener if (!bnk->Gold) {ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);} 104709164190SAlp Dener if (!bnk->Xwork) {ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);} 104809164190SAlp Dener if (!bnk->Gwork) {ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);} 104909164190SAlp Dener if (!bnk->unprojected_gradient) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);} 105009164190SAlp Dener if (!bnk->unprojected_gradient_old) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);} 1051198282dbSAlp Dener if (!bnk->G_inactive) {ierr = VecDuplicate(tao->solution,&bnk->G_inactive);CHKERRQ(ierr);} 10525e9b73cbSAlp Dener if (!bnk->Diag_min) {ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);} 10535e9b73cbSAlp Dener if (!bnk->Diag_max) {ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);} 1054eb910715SAlp Dener bnk->Diag = 0; 105562675beeSAlp Dener bnk->inactive_work = 0; 105662675beeSAlp Dener bnk->active_work = 0; 105762675beeSAlp Dener bnk->inactive_idx = 0; 105862675beeSAlp Dener bnk->active_idx = 0; 105962675beeSAlp Dener bnk->active_lower = 0; 106062675beeSAlp Dener bnk->active_upper = 0; 106162675beeSAlp Dener bnk->active_fixed = 0; 1062eb910715SAlp Dener bnk->M = 0; 106309164190SAlp Dener bnk->H_inactive = 0; 106409164190SAlp Dener bnk->Hpre_inactive = 0; 10659b6ef848SAlp Dener ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr); 10669b6ef848SAlp Dener ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr); 10679b6ef848SAlp Dener ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr); 10689b6ef848SAlp Dener ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr); 1069eb910715SAlp Dener PetscFunctionReturn(0); 1070eb910715SAlp Dener } 1071eb910715SAlp Dener 1072eb910715SAlp Dener /*------------------------------------------------------------*/ 1073df278d8fSAlp Dener 1074eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao) 1075eb910715SAlp Dener { 1076eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1077eb910715SAlp Dener PetscErrorCode ierr; 1078eb910715SAlp Dener 1079eb910715SAlp Dener PetscFunctionBegin; 1080eb910715SAlp Dener if (tao->setupcalled) { 1081eb910715SAlp Dener ierr = VecDestroy(&bnk->W);CHKERRQ(ierr); 1082eb910715SAlp Dener ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr); 1083eb910715SAlp Dener ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr); 108409164190SAlp Dener ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr); 108509164190SAlp Dener ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr); 108609164190SAlp Dener ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr); 108709164190SAlp Dener ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr); 1088198282dbSAlp Dener ierr = VecDestroy(&bnk->G_inactive);CHKERRQ(ierr); 108962675beeSAlp Dener ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr); 109062675beeSAlp Dener ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr); 10915e9b73cbSAlp Dener } 10925e9b73cbSAlp Dener ierr = VecDestroy(&bnk->Diag);CHKERRQ(ierr); 1093eb910715SAlp Dener ierr = MatDestroy(&bnk->M);CHKERRQ(ierr); 109462675beeSAlp Dener if (bnk->Hpre_inactive != bnk->H_inactive) {ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);} 109562675beeSAlp Dener ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr); 1096eb910715SAlp Dener ierr = PetscFree(tao->data);CHKERRQ(ierr); 1097eb910715SAlp Dener PetscFunctionReturn(0); 1098eb910715SAlp Dener } 1099eb910715SAlp Dener 1100eb910715SAlp Dener /*------------------------------------------------------------*/ 1101df278d8fSAlp Dener 1102eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao) 1103eb910715SAlp Dener { 1104eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1105eb910715SAlp Dener PetscErrorCode ierr; 1106eb910715SAlp Dener 1107eb910715SAlp Dener PetscFunctionBegin; 1108eb910715SAlp Dener ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr); 11098d5ead36SAlp 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); 11108d5ead36SAlp 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); 11118d5ead36SAlp 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); 11128d5ead36SAlp 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); 11132f75a4aaSAlp 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); 11148d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_sval", "perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr); 11158d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_imin", "minimum initial perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr); 11168d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_imax", "maximum initial perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr); 11178d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_imfac", "initial merit factor", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr); 11188d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmin", "minimum perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr); 11198d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmax", "maximum perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr); 11208d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pgfac", "growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr); 11218d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_psfac", "shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr); 11228d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmgfac", "merit growth factor", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr); 11238d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmsfac", "merit shrink factor", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr); 11248d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta1", "poor steplength; reduce radius", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr); 11258d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta2", "reasonable steplength; leave radius alone", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr); 11268d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta3", "good steplength; increase radius", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr); 11278d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta4", "excellent steplength; greatly increase radius", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr); 11288d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha1", "", "", bnk->alpha1, &bnk->alpha1,NULL);CHKERRQ(ierr); 11298d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha2", "", "", bnk->alpha2, &bnk->alpha2,NULL);CHKERRQ(ierr); 11308d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha3", "", "", bnk->alpha3, &bnk->alpha3,NULL);CHKERRQ(ierr); 11318d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha4", "", "", bnk->alpha4, &bnk->alpha4,NULL);CHKERRQ(ierr); 11328d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha5", "", "", bnk->alpha5, &bnk->alpha5,NULL);CHKERRQ(ierr); 11338d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu1", "poor steplength; reduce radius", "", bnk->nu1, &bnk->nu1,NULL);CHKERRQ(ierr); 11348d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu2", "reasonable steplength; leave radius alone", "", bnk->nu2, &bnk->nu2,NULL);CHKERRQ(ierr); 11358d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu3", "good steplength; increase radius", "", bnk->nu3, &bnk->nu3,NULL);CHKERRQ(ierr); 11368d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu4", "excellent steplength; greatly increase radius", "", bnk->nu4, &bnk->nu4,NULL);CHKERRQ(ierr); 11378d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega1", "", "", bnk->omega1, &bnk->omega1,NULL);CHKERRQ(ierr); 11388d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega2", "", "", bnk->omega2, &bnk->omega2,NULL);CHKERRQ(ierr); 11398d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega3", "", "", bnk->omega3, &bnk->omega3,NULL);CHKERRQ(ierr); 11408d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega4", "", "", bnk->omega4, &bnk->omega4,NULL);CHKERRQ(ierr); 11418d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega5", "", "", bnk->omega5, &bnk->omega5,NULL);CHKERRQ(ierr); 11428d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu1_i", "", "", bnk->mu1_i, &bnk->mu1_i,NULL);CHKERRQ(ierr); 11438d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu2_i", "", "", bnk->mu2_i, &bnk->mu2_i,NULL);CHKERRQ(ierr); 11448d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma1_i", "", "", bnk->gamma1_i, &bnk->gamma1_i,NULL);CHKERRQ(ierr); 11458d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma2_i", "", "", bnk->gamma2_i, &bnk->gamma2_i,NULL);CHKERRQ(ierr); 11468d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma3_i", "", "", bnk->gamma3_i, &bnk->gamma3_i,NULL);CHKERRQ(ierr); 11478d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma4_i", "", "", bnk->gamma4_i, &bnk->gamma4_i,NULL);CHKERRQ(ierr); 11488d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_theta_i", "", "", bnk->theta_i, &bnk->theta_i,NULL);CHKERRQ(ierr); 11498d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu1", "", "", bnk->mu1, &bnk->mu1,NULL);CHKERRQ(ierr); 11508d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu2", "", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr); 11518d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma1", "", "", bnk->gamma1, &bnk->gamma1,NULL);CHKERRQ(ierr); 11528d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma2", "", "", bnk->gamma2, &bnk->gamma2,NULL);CHKERRQ(ierr); 11538d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma3", "", "", bnk->gamma3, &bnk->gamma3,NULL);CHKERRQ(ierr); 11548d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma4", "", "", bnk->gamma4, &bnk->gamma4,NULL);CHKERRQ(ierr); 11558d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_theta", "", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr); 11568d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_min_radius", "lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr); 11578d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_max_radius", "upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr); 11588d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_epsilon", "tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr); 11590a4511e9SAlp Dener ierr = PetscOptionsReal("-tao_bnk_as_tol", "initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol,NULL);CHKERRQ(ierr); 11600a4511e9SAlp Dener ierr = PetscOptionsReal("-tao_bnk_as_step", "step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step,NULL);CHKERRQ(ierr); 1161eb910715SAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 1162eb910715SAlp Dener ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr); 1163eb910715SAlp Dener ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr); 1164eb910715SAlp Dener PetscFunctionReturn(0); 1165eb910715SAlp Dener } 1166eb910715SAlp Dener 1167eb910715SAlp Dener /*------------------------------------------------------------*/ 1168df278d8fSAlp Dener 1169eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer) 1170eb910715SAlp Dener { 1171eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1172eb910715SAlp Dener PetscInt nrejects; 1173eb910715SAlp Dener PetscBool isascii; 1174eb910715SAlp Dener PetscErrorCode ierr; 1175eb910715SAlp Dener 1176eb910715SAlp Dener PetscFunctionBegin; 1177eb910715SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 1178eb910715SAlp Dener if (isascii) { 1179eb910715SAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1180eb910715SAlp Dener if (BNK_PC_BFGS == bnk->pc_type && bnk->M) { 1181eb910715SAlp Dener ierr = MatLMVMGetRejects(bnk->M,&nrejects);CHKERRQ(ierr); 1182eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects);CHKERRQ(ierr); 1183eb910715SAlp Dener } 1184eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr); 1185eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr); 1186eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr); 1187eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr); 1188eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr); 1189eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr); 1190eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr); 1191eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr); 1192eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr); 1193eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr); 1194eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr); 1195eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr); 1196eb910715SAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1197eb910715SAlp Dener } 1198eb910715SAlp Dener PetscFunctionReturn(0); 1199eb910715SAlp Dener } 1200eb910715SAlp Dener 1201eb910715SAlp Dener /* ---------------------------------------------------------- */ 1202df278d8fSAlp Dener 1203eb910715SAlp Dener /*MC 1204eb910715SAlp Dener TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms. 120566ed3702SAlp Dener At each iteration, the BNK methods solve the symmetric 1206eb910715SAlp Dener system of equations to obtain the step diretion dk: 1207eb910715SAlp Dener Hk dk = -gk 12082b97c8d8SAlp Dener for free variables only. The step can be globalized either through 12092b97c8d8SAlp Dener trust-region methods, or a line search, or a heuristic mixture of both. 1210eb910715SAlp Dener 1211eb910715SAlp Dener Options Database Keys: 12128d5ead36SAlp Dener + -tao_bnk_pc_type - "none","ahess","bfgs","petsc" 12138d5ead36SAlp Dener . -tao_bnk_bfgs_scale_type - "ahess","phess","bfgs" 12148d5ead36SAlp Dener . -tao_bnk_init_type - "constant","direction","interpolation" 12158d5ead36SAlp Dener . -tao_bnk_update_type - "step","direction","interpolation" 12162f75a4aaSAlp Dener . -tao_bnk_as_type - "none","bertsekas" 12178d5ead36SAlp Dener . -tao_bnk_sval - perturbation starting value 12188d5ead36SAlp Dener . -tao_bnk_imin - minimum initial perturbation 12198d5ead36SAlp Dener . -tao_bnk_imax - maximum initial perturbation 12208d5ead36SAlp Dener . -tao_bnk_pmin - minimum perturbation 12218d5ead36SAlp Dener . -tao_bnk_pmax - maximum perturbation 12228d5ead36SAlp Dener . -tao_bnk_pgfac - growth factor 12238d5ead36SAlp Dener . -tao_bnk_psfac - shrink factor 12248d5ead36SAlp Dener . -tao_bnk_imfac - initial merit factor 12258d5ead36SAlp Dener . -tao_bnk_pmgfac - merit growth factor 12268d5ead36SAlp Dener . -tao_bnk_pmsfac - merit shrink factor 12278d5ead36SAlp Dener . -tao_bnk_eta1 - poor steplength; reduce radius 12288d5ead36SAlp Dener . -tao_bnk_eta2 - reasonable steplength; leave radius 12298d5ead36SAlp Dener . -tao_bnk_eta3 - good steplength; increase readius 12308d5ead36SAlp Dener . -tao_bnk_eta4 - excellent steplength; greatly increase radius 12318d5ead36SAlp Dener . -tao_bnk_alpha1 - alpha1 reduction 12328d5ead36SAlp Dener . -tao_bnk_alpha2 - alpha2 reduction 12338d5ead36SAlp Dener . -tao_bnk_alpha3 - alpha3 reduction 12348d5ead36SAlp Dener . -tao_bnk_alpha4 - alpha4 reduction 12358d5ead36SAlp Dener . -tao_bnk_alpha - alpha5 reduction 12368d5ead36SAlp Dener . -tao_bnk_mu1 - mu1 interpolation update 12378d5ead36SAlp Dener . -tao_bnk_mu2 - mu2 interpolation update 12388d5ead36SAlp Dener . -tao_bnk_gamma1 - gamma1 interpolation update 12398d5ead36SAlp Dener . -tao_bnk_gamma2 - gamma2 interpolation update 12408d5ead36SAlp Dener . -tao_bnk_gamma3 - gamma3 interpolation update 12418d5ead36SAlp Dener . -tao_bnk_gamma4 - gamma4 interpolation update 12428d5ead36SAlp Dener . -tao_bnk_theta - theta interpolation update 12438d5ead36SAlp Dener . -tao_bnk_omega1 - omega1 step update 12448d5ead36SAlp Dener . -tao_bnk_omega2 - omega2 step update 12458d5ead36SAlp Dener . -tao_bnk_omega3 - omega3 step update 12468d5ead36SAlp Dener . -tao_bnk_omega4 - omega4 step update 12478d5ead36SAlp Dener . -tao_bnk_omega5 - omega5 step update 12488d5ead36SAlp Dener . -tao_bnk_mu1_i - mu1 interpolation init factor 12498d5ead36SAlp Dener . -tao_bnk_mu2_i - mu2 interpolation init factor 12508d5ead36SAlp Dener . -tao_bnk_gamma1_i - gamma1 interpolation init factor 12518d5ead36SAlp Dener . -tao_bnk_gamma2_i - gamma2 interpolation init factor 12528d5ead36SAlp Dener . -tao_bnk_gamma3_i - gamma3 interpolation init factor 12538d5ead36SAlp Dener . -tao_bnk_gamma4_i - gamma4 interpolation init factor 12542f75a4aaSAlp Dener . -tao_bnk_theta_i - theta interpolation init factor 12552f75a4aaSAlp Dener - -tao_bnk_bound_tol - initial tolerance used in estimating bounded active variables 1256eb910715SAlp Dener 1257eb910715SAlp Dener Level: beginner 1258eb910715SAlp Dener M*/ 1259eb910715SAlp Dener 1260eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao) 1261eb910715SAlp Dener { 1262eb910715SAlp Dener TAO_BNK *bnk; 1263eb910715SAlp Dener const char *morethuente_type = TAOLINESEARCHMT; 1264eb910715SAlp Dener PetscErrorCode ierr; 1265eb910715SAlp Dener 1266eb910715SAlp Dener PetscFunctionBegin; 1267eb910715SAlp Dener ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr); 1268eb910715SAlp Dener 1269eb910715SAlp Dener tao->ops->setup = TaoSetUp_BNK; 1270eb910715SAlp Dener tao->ops->view = TaoView_BNK; 1271eb910715SAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_BNK; 1272eb910715SAlp Dener tao->ops->destroy = TaoDestroy_BNK; 1273eb910715SAlp Dener 1274eb910715SAlp Dener /* Override default settings (unless already changed) */ 1275eb910715SAlp Dener if (!tao->max_it_changed) tao->max_it = 50; 1276eb910715SAlp Dener if (!tao->trust0_changed) tao->trust0 = 100.0; 1277eb910715SAlp Dener 1278eb910715SAlp Dener tao->data = (void*)bnk; 1279eb910715SAlp Dener 128066ed3702SAlp Dener /* Hessian shifting parameters */ 1281eb910715SAlp Dener bnk->sval = 0.0; 1282eb910715SAlp Dener bnk->imin = 1.0e-4; 1283eb910715SAlp Dener bnk->imax = 1.0e+2; 1284eb910715SAlp Dener bnk->imfac = 1.0e-1; 1285eb910715SAlp Dener 1286eb910715SAlp Dener bnk->pmin = 1.0e-12; 1287eb910715SAlp Dener bnk->pmax = 1.0e+2; 1288eb910715SAlp Dener bnk->pgfac = 1.0e+1; 1289eb910715SAlp Dener bnk->psfac = 4.0e-1; 1290eb910715SAlp Dener bnk->pmgfac = 1.0e-1; 1291eb910715SAlp Dener bnk->pmsfac = 1.0e-1; 1292eb910715SAlp Dener 1293eb910715SAlp Dener /* Default values for trust-region radius update based on steplength */ 1294eb910715SAlp Dener bnk->nu1 = 0.25; 1295eb910715SAlp Dener bnk->nu2 = 0.50; 1296eb910715SAlp Dener bnk->nu3 = 1.00; 1297eb910715SAlp Dener bnk->nu4 = 1.25; 1298eb910715SAlp Dener 1299eb910715SAlp Dener bnk->omega1 = 0.25; 1300eb910715SAlp Dener bnk->omega2 = 0.50; 1301eb910715SAlp Dener bnk->omega3 = 1.00; 1302eb910715SAlp Dener bnk->omega4 = 2.00; 1303eb910715SAlp Dener bnk->omega5 = 4.00; 1304eb910715SAlp Dener 1305eb910715SAlp Dener /* Default values for trust-region radius update based on reduction */ 1306eb910715SAlp Dener bnk->eta1 = 1.0e-4; 1307eb910715SAlp Dener bnk->eta2 = 0.25; 1308eb910715SAlp Dener bnk->eta3 = 0.50; 1309eb910715SAlp Dener bnk->eta4 = 0.90; 1310eb910715SAlp Dener 1311eb910715SAlp Dener bnk->alpha1 = 0.25; 1312eb910715SAlp Dener bnk->alpha2 = 0.50; 1313eb910715SAlp Dener bnk->alpha3 = 1.00; 1314eb910715SAlp Dener bnk->alpha4 = 2.00; 1315eb910715SAlp Dener bnk->alpha5 = 4.00; 1316eb910715SAlp Dener 1317eb910715SAlp Dener /* Default values for trust-region radius update based on interpolation */ 1318eb910715SAlp Dener bnk->mu1 = 0.10; 1319eb910715SAlp Dener bnk->mu2 = 0.50; 1320eb910715SAlp Dener 1321eb910715SAlp Dener bnk->gamma1 = 0.25; 1322eb910715SAlp Dener bnk->gamma2 = 0.50; 1323eb910715SAlp Dener bnk->gamma3 = 2.00; 1324eb910715SAlp Dener bnk->gamma4 = 4.00; 1325eb910715SAlp Dener 1326eb910715SAlp Dener bnk->theta = 0.05; 1327eb910715SAlp Dener 1328eb910715SAlp Dener /* Default values for trust region initialization based on interpolation */ 1329eb910715SAlp Dener bnk->mu1_i = 0.35; 1330eb910715SAlp Dener bnk->mu2_i = 0.50; 1331eb910715SAlp Dener 1332eb910715SAlp Dener bnk->gamma1_i = 0.0625; 1333eb910715SAlp Dener bnk->gamma2_i = 0.5; 1334eb910715SAlp Dener bnk->gamma3_i = 2.0; 1335eb910715SAlp Dener bnk->gamma4_i = 5.0; 1336eb910715SAlp Dener 1337eb910715SAlp Dener bnk->theta_i = 0.25; 1338eb910715SAlp Dener 1339eb910715SAlp Dener /* Remaining parameters */ 1340eb910715SAlp Dener bnk->min_radius = 1.0e-10; 1341eb910715SAlp Dener bnk->max_radius = 1.0e10; 1342770b7498SAlp Dener bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0); 13430a4511e9SAlp Dener bnk->as_tol = 1.0e-3; 13440a4511e9SAlp Dener bnk->as_step = 1.0e-3; 134562675beeSAlp Dener bnk->dmin = 1.0e-6; 134662675beeSAlp Dener bnk->dmax = 1.0e6; 1347eb910715SAlp Dener 1348eb910715SAlp Dener bnk->pc_type = BNK_PC_BFGS; 1349eb910715SAlp Dener bnk->bfgs_scale_type = BFGS_SCALE_PHESS; 1350eb910715SAlp Dener bnk->init_type = BNK_INIT_INTERPOLATION; 1351fed79b8eSAlp Dener bnk->update_type = BNK_UPDATE_INTERPOLATION; 13522f75a4aaSAlp Dener bnk->as_type = BNK_AS_BERTSEKAS; 1353eb910715SAlp Dener 1354eb910715SAlp Dener ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr); 1355eb910715SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr); 1356eb910715SAlp Dener ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr); 1357eb910715SAlp Dener ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr); 1358eb910715SAlp Dener ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr); 1359eb910715SAlp Dener 1360eb910715SAlp Dener /* Set linear solver to default for symmetric matrices */ 1361eb910715SAlp Dener ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr); 1362eb910715SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr); 1363eb910715SAlp Dener ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr); 1364eb910715SAlp Dener ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr); 1365eb910715SAlp Dener PetscFunctionReturn(0); 1366eb910715SAlp Dener } 1367