1eb910715SAlp Dener #include <petsctaolinesearch.h> 2eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h> 3eb910715SAlp Dener 4eb910715SAlp Dener #include <petscksp.h> 5eb910715SAlp Dener 6e031d6f5SAlp Dener static const char *BNK_PC[64] = {"none", "ahess", "bfgs", "petsc"}; 7e031d6f5SAlp Dener static const char *BFGS_SCALE[64] = {"ahess", "phess", "bfgs"}; 8e031d6f5SAlp Dener static const char *BNK_INIT[64] = {"constant", "direction", "interpolation"}; 9e031d6f5SAlp Dener static const char *BNK_UPDATE[64] = {"step", "reduction", "interpolation"}; 10e031d6f5SAlp Dener static const char *BNK_AS[64] = {"none", "bertsekas"}; 11e031d6f5SAlp Dener 12e031d6f5SAlp Dener /*------------------------------------------------------------*/ 13e031d6f5SAlp Dener 14eb910715SAlp Dener /* Routine for BFGS preconditioner */ 15eb910715SAlp Dener 16eb910715SAlp Dener PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x) 17eb910715SAlp Dener { 18eb910715SAlp Dener PetscErrorCode ierr; 19eb910715SAlp Dener Mat M; 20eb910715SAlp Dener 21eb910715SAlp Dener PetscFunctionBegin; 22eb910715SAlp Dener PetscValidHeaderSpecific(pc,PC_CLASSID,1); 23eb910715SAlp Dener PetscValidHeaderSpecific(b,VEC_CLASSID,2); 24eb910715SAlp Dener PetscValidHeaderSpecific(x,VEC_CLASSID,3); 25eb910715SAlp Dener ierr = PCShellGetContext(pc,(void**)&M);CHKERRQ(ierr); 265e9b73cbSAlp Dener ierr = MatLMVMSolve(M, b, x);CHKERRQ(ierr); 27eb910715SAlp Dener PetscFunctionReturn(0); 28eb910715SAlp Dener } 29eb910715SAlp Dener 30df278d8fSAlp Dener /*------------------------------------------------------------*/ 31df278d8fSAlp Dener 32df278d8fSAlp Dener /* Routine for initializing the KSP solver, the BFGS preconditioner, and the initial trust radius estimation */ 33df278d8fSAlp Dener 34c0f10754SAlp Dener PetscErrorCode TaoBNKInitialize(Tao tao, PetscInt initType, PetscBool *needH) 35eb910715SAlp Dener { 36eb910715SAlp Dener PetscErrorCode ierr; 37eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 38eb910715SAlp Dener PC pc; 39eb910715SAlp Dener 400a4511e9SAlp Dener PetscReal f_min, ftrial, prered, actred, kappa, sigma; 41eb910715SAlp Dener PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius; 42e031d6f5SAlp Dener PetscReal resnorm, delta; 43eb910715SAlp Dener 44c0f10754SAlp Dener PetscInt n,N; 45eb910715SAlp Dener 46eb910715SAlp Dener PetscInt i_max = 5; 47eb910715SAlp Dener PetscInt j_max = 1; 48eb910715SAlp Dener PetscInt i, j; 49eb910715SAlp Dener 50eb910715SAlp Dener PetscFunctionBegin; 5128017e9fSAlp Dener /* Project the current point onto the feasible set */ 5228017e9fSAlp Dener ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 53e031d6f5SAlp Dener ierr = TaoSetVariableBounds(bnk->bncg, tao->XL, tao->XU);CHKERRQ(ierr); 5428017e9fSAlp Dener ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr); 5528017e9fSAlp Dener 5628017e9fSAlp Dener /* Project the initial point onto the feasible region */ 5728017e9fSAlp Dener ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr); 5828017e9fSAlp Dener 5928017e9fSAlp Dener /* Check convergence criteria */ 6028017e9fSAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, bnk->unprojected_gradient);CHKERRQ(ierr); 6128017e9fSAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 6208752603SAlp Dener ierr = VecNorm(tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 6328017e9fSAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 6428017e9fSAlp Dener 65c0f10754SAlp Dener /* Test the initial point for convergence */ 66e031d6f5SAlp Dener ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr); 67e031d6f5SAlp Dener ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr); 68e031d6f5SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 69e031d6f5SAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr); 70c0f10754SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 71c0f10754SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 72c0f10754SAlp Dener 73e031d6f5SAlp Dener /* Reset KSP stopping reason counters */ 74eb910715SAlp Dener bnk->ksp_atol = 0; 75eb910715SAlp Dener bnk->ksp_rtol = 0; 76eb910715SAlp Dener bnk->ksp_dtol = 0; 77eb910715SAlp Dener bnk->ksp_ctol = 0; 78eb910715SAlp Dener bnk->ksp_negc = 0; 79eb910715SAlp Dener bnk->ksp_iter = 0; 80eb910715SAlp Dener bnk->ksp_othr = 0; 81eb910715SAlp Dener 82e031d6f5SAlp Dener /* Reset accepted step type counters */ 83e031d6f5SAlp Dener bnk->tot_cg_its = 0; 84e031d6f5SAlp Dener bnk->newt = 0; 85e031d6f5SAlp Dener bnk->bfgs = 0; 86e031d6f5SAlp Dener bnk->sgrad = 0; 87e031d6f5SAlp Dener bnk->grad = 0; 88e031d6f5SAlp Dener 89fed79b8eSAlp Dener /* Initialize the Hessian perturbation */ 90fed79b8eSAlp Dener bnk->pert = bnk->sval; 91fed79b8eSAlp Dener 92*937a31a1SAlp Dener /* Reset initial steplength to zero (this helps BNCG reset its direction internally) */ 93*937a31a1SAlp Dener ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr); 94*937a31a1SAlp Dener 95e031d6f5SAlp Dener /* Allocate the vectors needed for the BFGS approximation */ 96e031d6f5SAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 97e031d6f5SAlp Dener if (!bnk->M) { 98eb910715SAlp Dener ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); 99eb910715SAlp Dener ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); 100eb910715SAlp Dener ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&bnk->M);CHKERRQ(ierr); 101eb910715SAlp Dener ierr = MatLMVMAllocateVectors(bnk->M,tao->solution);CHKERRQ(ierr); 102eb910715SAlp Dener } 103e031d6f5SAlp Dener if (bnk->bfgs_scale_type != BFGS_SCALE_BFGS && !bnk->Diag) { 104e031d6f5SAlp Dener ierr = VecDuplicate(tao->solution,&bnk->Diag);CHKERRQ(ierr); 1055e9b73cbSAlp Dener } 106e031d6f5SAlp Dener } 107e031d6f5SAlp Dener 108e031d6f5SAlp Dener /* Prepare the min/max vectors for safeguarding diagonal scales */ 10962675beeSAlp Dener ierr = VecSet(bnk->Diag_min, bnk->dmin);CHKERRQ(ierr); 11062675beeSAlp Dener ierr = VecSet(bnk->Diag_max, bnk->dmax);CHKERRQ(ierr); 111eb910715SAlp Dener 112eb910715SAlp Dener /* Modify the preconditioner to use the bfgs approximation */ 113eb910715SAlp Dener ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr); 114eb910715SAlp Dener switch(bnk->pc_type) { 115eb910715SAlp Dener case BNK_PC_NONE: 116eb910715SAlp Dener ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr); 117eb910715SAlp Dener ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 118eb910715SAlp Dener break; 119eb910715SAlp Dener 120eb910715SAlp Dener case BNK_PC_AHESS: 121eb910715SAlp Dener ierr = PCSetType(pc, PCJACOBI);CHKERRQ(ierr); 122eb910715SAlp Dener ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 123eb910715SAlp Dener ierr = PCJacobiSetUseAbs(pc,PETSC_TRUE);CHKERRQ(ierr); 124eb910715SAlp Dener break; 125eb910715SAlp Dener 126eb910715SAlp Dener case BNK_PC_BFGS: 127eb910715SAlp Dener ierr = PCSetType(pc, PCSHELL);CHKERRQ(ierr); 128eb910715SAlp Dener ierr = PCSetFromOptions(pc);CHKERRQ(ierr); 129eb910715SAlp Dener ierr = PCShellSetName(pc, "bfgs");CHKERRQ(ierr); 130eb910715SAlp Dener ierr = PCShellSetContext(pc, bnk->M);CHKERRQ(ierr); 131eb910715SAlp Dener ierr = PCShellSetApply(pc, MatLMVMSolveShell);CHKERRQ(ierr); 132eb910715SAlp Dener break; 133eb910715SAlp Dener 134eb910715SAlp Dener default: 135eb910715SAlp Dener /* Use the pc method set by pc_type */ 136eb910715SAlp Dener break; 137eb910715SAlp Dener } 138eb910715SAlp Dener 139eb910715SAlp Dener /* Initialize trust-region radius. The initialization is only performed 140eb910715SAlp Dener when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */ 141c0f10754SAlp Dener *needH = PETSC_TRUE; 142eb910715SAlp Dener if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) { 14362675beeSAlp Dener switch(initType) { 144eb910715SAlp Dener case BNK_INIT_CONSTANT: 145eb910715SAlp Dener /* Use the initial radius specified */ 146c0f10754SAlp Dener tao->trust = tao->trust0; 147eb910715SAlp Dener break; 148eb910715SAlp Dener 149eb910715SAlp Dener case BNK_INIT_INTERPOLATION: 150c0f10754SAlp Dener /* Use interpolation based on the initial Hessian */ 151eb910715SAlp Dener max_radius = 0.0; 15208752603SAlp Dener tao->trust = tao->trust0; 153eb910715SAlp Dener for (j = 0; j < j_max; ++j) { 1540a4511e9SAlp Dener f_min = bnk->f; 155eb910715SAlp Dener sigma = 0.0; 156eb910715SAlp Dener 157c0f10754SAlp Dener if (*needH) { 15862602cfbSAlp Dener /* Compute the Hessian at the new step, and extract the inactive subsystem */ 159e031d6f5SAlp Dener ierr = TaoBNKComputeHessian(tao);CHKERRQ(ierr); 16008752603SAlp Dener ierr = TaoBNKEstimateActiveSet(tao, BNK_AS_NONE);CHKERRQ(ierr); 16128017e9fSAlp Dener if (bnk->inactive_idx) { 1622ab2a32cSAlp Dener ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr); 16328017e9fSAlp Dener } else { 16408752603SAlp Dener ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive);CHKERRQ(ierr); 16528017e9fSAlp Dener } 166c0f10754SAlp Dener *needH = PETSC_FALSE; 167eb910715SAlp Dener } 168eb910715SAlp Dener 169eb910715SAlp Dener for (i = 0; i < i_max; ++i) { 17062602cfbSAlp Dener /* Take a steepest descent step and snap it to bounds */ 17162602cfbSAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 17262602cfbSAlp Dener ierr = VecAXPY(tao->solution, -tao->trust/bnk->gnorm, tao->gradient);CHKERRQ(ierr); 17362602cfbSAlp Dener ierr = VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);CHKERRQ(ierr); 174770b7498SAlp Dener /* Recompute the step after bound snapping so that it can be used in predicted decrease calculation later */ 175eb910715SAlp Dener ierr = VecCopy(tao->solution, bnk->W);CHKERRQ(ierr); 17662602cfbSAlp Dener ierr = VecAXPY(bnk->W, -1.0, bnk->Xold);CHKERRQ(ierr); 17762602cfbSAlp Dener /* Compute the objective at the trial */ 17862602cfbSAlp Dener ierr = TaoComputeObjective(tao, tao->solution, &ftrial);CHKERRQ(ierr); 17962602cfbSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 180eb910715SAlp Dener if (PetscIsInfOrNanReal(ftrial)) { 181eb910715SAlp Dener tau = bnk->gamma1_i; 182eb910715SAlp Dener } else { 1830a4511e9SAlp Dener if (ftrial < f_min) { 1840a4511e9SAlp Dener f_min = ftrial; 185eb910715SAlp Dener sigma = -tao->trust / bnk->gnorm; 186eb910715SAlp Dener } 18708752603SAlp Dener 188770b7498SAlp Dener /* Compute the predicted and actual reduction */ 1892ab2a32cSAlp Dener if (bnk->inactive_idx) { 19008752603SAlp Dener ierr = VecGetSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 19108752603SAlp Dener ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 1922ab2a32cSAlp Dener } else { 19308752603SAlp Dener bnk->X_inactive = bnk->W; 19408752603SAlp Dener bnk->inactive_work = bnk->Xwork; 1952ab2a32cSAlp Dener } 19608752603SAlp Dener ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr); 19708752603SAlp Dener ierr = VecDot(bnk->X_inactive, bnk->inactive_work, &prered);CHKERRQ(ierr); 1982ab2a32cSAlp Dener if (bnk->inactive_idx) { 19908752603SAlp Dener ierr = VecRestoreSubVector(bnk->W, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 20008752603SAlp Dener ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 2012ab2a32cSAlp Dener } 202eb910715SAlp Dener prered = tao->trust * (bnk->gnorm - 0.5 * tao->trust * prered / (bnk->gnorm * bnk->gnorm)); 203eb910715SAlp Dener actred = bnk->f - ftrial; 20408752603SAlp Dener if ((PetscAbsScalar(actred) <= bnk->epsilon) && 20508752603SAlp Dener (PetscAbsScalar(prered) <= bnk->epsilon)) { 206eb910715SAlp Dener kappa = 1.0; 20708752603SAlp Dener } 20808752603SAlp 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; 22308752603SAlp Dener } 22408752603SAlp Dener else if (tau_max > bnk->gamma4_i) { 225eb910715SAlp Dener tau = bnk->gamma4_i; 22608752603SAlp Dener } 22708752603SAlp Dener else { 228eb910715SAlp Dener tau = tau_max; 229eb910715SAlp Dener } 23008752603SAlp Dener } 23108752603SAlp Dener else if (PetscAbsScalar(kappa - 1.0) <= bnk->mu2_i) { 232eb910715SAlp Dener /* Good agreement */ 233eb910715SAlp Dener max_radius = PetscMax(max_radius, tao->trust); 234eb910715SAlp Dener 235eb910715SAlp Dener if (tau_max < bnk->gamma2_i) { 236eb910715SAlp Dener tau = bnk->gamma2_i; 237eb910715SAlp Dener } else if (tau_max > bnk->gamma3_i) { 238eb910715SAlp Dener tau = bnk->gamma3_i; 239eb910715SAlp Dener } else { 240eb910715SAlp Dener tau = tau_max; 241eb910715SAlp Dener } 24208752603SAlp Dener } 24308752603SAlp 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; 25108752603SAlp Dener } else if ((tau_1 >= bnk->gamma1_i) && (tau_1 < 1.0) && 25208752603SAlp Dener ((tau_2 < bnk->gamma1_i) || (tau_2 >= 1.0))) { 253eb910715SAlp Dener tau = tau_1; 25408752603SAlp Dener } else if ((tau_2 >= bnk->gamma1_i) && (tau_2 < 1.0) && 25508752603SAlp Dener ((tau_1 < bnk->gamma1_i) || (tau_2 >= 1.0))) { 256eb910715SAlp Dener tau = tau_2; 257eb910715SAlp Dener } else { 258eb910715SAlp Dener tau = tau_max; 259eb910715SAlp Dener } 260eb910715SAlp Dener } 261eb910715SAlp Dener } 262eb910715SAlp Dener tao->trust = tau * tao->trust; 263eb910715SAlp Dener } 264eb910715SAlp Dener 2650a4511e9SAlp Dener if (f_min < bnk->f) { 266*937a31a1SAlp Dener /* We accidentally found a solution better than the initial, so accept it */ 2670a4511e9SAlp Dener bnk->f = f_min; 268*937a31a1SAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 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); 271*937a31a1SAlp Dener ierr = VecCopy(tao->solution, tao->stepdirection);CHKERRQ(ierr); 272*937a31a1SAlp Dener ierr = VecAXPY(tao->stepdirection, -1.0, bnk->Xold);CHKERRQ(ierr); 27309164190SAlp Dener ierr = TaoComputeGradient(tao,tao->solution,bnk->unprojected_gradient);CHKERRQ(ierr); 27409164190SAlp Dener ierr = VecBoundGradientProjection(bnk->unprojected_gradient,tao->solution,tao->XL,tao->XU,tao->gradient);CHKERRQ(ierr); 275*937a31a1SAlp Dener /* Compute gradient at the new iterate and flip switch to compute the Hessian later */ 276eb910715SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 277eb910715SAlp Dener if (PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN"); 278c0f10754SAlp Dener *needH = PETSC_TRUE; 279*937a31a1SAlp Dener /* Test the new step for convergence */ 280e031d6f5SAlp Dener ierr = VecFischer(tao->solution, bnk->unprojected_gradient, tao->XL, tao->XU, bnk->Gwork);CHKERRQ(ierr); 281e031d6f5SAlp Dener ierr = VecNorm(bnk->Gwork, NORM_2, &resnorm);CHKERRQ(ierr); 282e031d6f5SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,resnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 283e031d6f5SAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,resnorm,0.0,1.0);CHKERRQ(ierr); 284eb910715SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 285eb910715SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 286*937a31a1SAlp Dener /* active BNCG recycling early because we have a stepdirection computed */ 287*937a31a1SAlp Dener ierr = TaoBNCGSetRecycleFlag(bnk->bncg, PETSC_TRUE);CHKERRQ(ierr); 288eb910715SAlp Dener } 289eb910715SAlp Dener } 290eb910715SAlp Dener tao->trust = PetscMax(tao->trust, max_radius); 291e031d6f5SAlp Dener 292e031d6f5SAlp Dener /* Ensure that the trust radius is within the limits */ 293e031d6f5SAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 294e031d6f5SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 295eb910715SAlp Dener break; 296eb910715SAlp Dener 297eb910715SAlp Dener default: 298eb910715SAlp Dener /* Norm of the first direction will initialize radius */ 299eb910715SAlp Dener tao->trust = 0.0; 300eb910715SAlp Dener break; 301eb910715SAlp Dener } 302eb910715SAlp Dener } 303e031d6f5SAlp Dener 304eb910715SAlp Dener /* Set initial scaling for the BFGS preconditioner 305eb910715SAlp Dener This step is done after computing the initial trust-region radius 306eb910715SAlp Dener since the function value may have decreased */ 307eb910715SAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 3089b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 309eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr); 310eb910715SAlp Dener } 311eb910715SAlp Dener PetscFunctionReturn(0); 312eb910715SAlp Dener } 313eb910715SAlp Dener 314df278d8fSAlp Dener /*------------------------------------------------------------*/ 315df278d8fSAlp Dener 31662675beeSAlp Dener /* Routine for computing the Hessian and preparing the preconditioner at the new iterate */ 31762675beeSAlp Dener 31862675beeSAlp Dener PetscErrorCode TaoBNKComputeHessian(Tao tao) 31962675beeSAlp Dener { 32062675beeSAlp Dener PetscErrorCode ierr; 32162675beeSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 32262675beeSAlp Dener 32362675beeSAlp Dener PetscFunctionBegin; 32462675beeSAlp Dener /* Compute the Hessian */ 32562675beeSAlp Dener ierr = TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre);CHKERRQ(ierr); 32662675beeSAlp Dener /* Add a correction to the BFGS preconditioner */ 32762675beeSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 32862675beeSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 32962675beeSAlp Dener /* Update the BFGS diagonal scaling */ 33062675beeSAlp Dener if (BFGS_SCALE_AHESS == bnk->bfgs_scale_type) { 33162675beeSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Diag);CHKERRQ(ierr); 33262675beeSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 33362675beeSAlp Dener ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr); 33462675beeSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 33562675beeSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 33662675beeSAlp Dener } 33762675beeSAlp Dener } 33862675beeSAlp Dener PetscFunctionReturn(0); 33962675beeSAlp Dener } 34062675beeSAlp Dener 34162675beeSAlp Dener /*------------------------------------------------------------*/ 34262675beeSAlp Dener 3432f75a4aaSAlp Dener /* Routine for estimating the active set */ 3442f75a4aaSAlp Dener 34508752603SAlp Dener PetscErrorCode TaoBNKEstimateActiveSet(Tao tao, PetscInt asType) 3462f75a4aaSAlp Dener { 3472f75a4aaSAlp Dener PetscErrorCode ierr; 3482f75a4aaSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 3492f75a4aaSAlp Dener 3502f75a4aaSAlp Dener PetscFunctionBegin; 35108752603SAlp Dener switch (asType) { 3522f75a4aaSAlp Dener case BNK_AS_NONE: 3532f75a4aaSAlp Dener ierr = ISDestroy(&bnk->inactive_idx);CHKERRQ(ierr); 3542f75a4aaSAlp Dener ierr = VecWhichInactive(tao->XL, tao->solution, bnk->unprojected_gradient, tao->XU, PETSC_TRUE, &bnk->inactive_idx);CHKERRQ(ierr); 3552f75a4aaSAlp Dener ierr = ISDestroy(&bnk->active_idx);CHKERRQ(ierr); 3562f75a4aaSAlp Dener ierr = ISComplementVec(bnk->inactive_idx, tao->solution, &bnk->active_idx);CHKERRQ(ierr); 3572f75a4aaSAlp Dener break; 3582f75a4aaSAlp Dener 3592f75a4aaSAlp Dener case BNK_AS_BERTSEKAS: 3602f75a4aaSAlp Dener /* Compute the trial step vector with which we will estimate the active set at the next iteration */ 3612f75a4aaSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { 3622f75a4aaSAlp Dener /* If the BFGS preconditioner matrix is available, we will construct a trial step with it */ 3635e9b73cbSAlp Dener ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr); 3642f75a4aaSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, bnk->W);CHKERRQ(ierr); 3652f75a4aaSAlp Dener } else { 3669b6ef848SAlp Dener /* BFGS preconditioner doesn't exist so let's invert the absolute diagonal of the Hessian instead onto the gradient */ 3672f75a4aaSAlp Dener ierr = MatGetDiagonal(tao->hessian, bnk->Xwork);CHKERRQ(ierr); 3689b6ef848SAlp Dener ierr = VecAbs(bnk->Xwork);CHKERRQ(ierr); 3699b6ef848SAlp Dener ierr = VecMedian(bnk->Diag_min, bnk->Xwork, bnk->Diag_max, bnk->Xwork);CHKERRQ(ierr); 3702f75a4aaSAlp Dener ierr = VecReciprocal(bnk->Xwork);CHKERRQ(ierr);CHKERRQ(ierr); 3712f75a4aaSAlp Dener ierr = VecPointwiseMult(bnk->W, bnk->Xwork, bnk->unprojected_gradient);CHKERRQ(ierr); 3722f75a4aaSAlp Dener } 3732f75a4aaSAlp Dener ierr = VecScale(bnk->W, -1.0);CHKERRQ(ierr); 3740a4511e9SAlp 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); 3752f75a4aaSAlp Dener 3762f75a4aaSAlp Dener default: 3772f75a4aaSAlp Dener break; 3782f75a4aaSAlp Dener } 3792f75a4aaSAlp Dener PetscFunctionReturn(0); 3802f75a4aaSAlp Dener } 3812f75a4aaSAlp Dener 3822f75a4aaSAlp Dener /*------------------------------------------------------------*/ 3832f75a4aaSAlp Dener 3842f75a4aaSAlp Dener /* Routine for bounding the step direction */ 3852f75a4aaSAlp Dener 3862f75a4aaSAlp Dener PetscErrorCode TaoBNKBoundStep(Tao tao, Vec step) 3872f75a4aaSAlp Dener { 3882f75a4aaSAlp Dener PetscErrorCode ierr; 3892f75a4aaSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 3902f75a4aaSAlp Dener 3912f75a4aaSAlp Dener PetscFunctionBegin; 39228017e9fSAlp Dener if (bnk->active_idx) { 3932f75a4aaSAlp Dener switch (bnk->as_type) { 3942f75a4aaSAlp Dener case BNK_AS_NONE: 3952f75a4aaSAlp Dener if (bnk->active_idx) { 3962f75a4aaSAlp Dener ierr = VecGetSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr); 3972f75a4aaSAlp Dener ierr = VecSet(bnk->active_work, 0.0);CHKERRQ(ierr); 3982f75a4aaSAlp Dener ierr = VecRestoreSubVector(step, bnk->active_idx, &bnk->active_work);CHKERRQ(ierr); 3992f75a4aaSAlp Dener } 4002f75a4aaSAlp Dener break; 4012f75a4aaSAlp Dener 4022f75a4aaSAlp Dener case BNK_AS_BERTSEKAS: 4032f75a4aaSAlp Dener ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, bnk->active_lower, bnk->active_upper, bnk->active_fixed, step);CHKERRQ(ierr); 4042f75a4aaSAlp Dener break; 4052f75a4aaSAlp Dener 4062f75a4aaSAlp Dener default: 4072f75a4aaSAlp Dener break; 4082f75a4aaSAlp Dener } 409e465cd6fSAlp Dener } 4102f75a4aaSAlp Dener PetscFunctionReturn(0); 4112f75a4aaSAlp Dener } 4122f75a4aaSAlp Dener 413e031d6f5SAlp Dener /*------------------------------------------------------------*/ 414e031d6f5SAlp Dener 415e031d6f5SAlp Dener /* Routine for taking a finite number of BNCG iterations to 416e031d6f5SAlp Dener accelerate Newton convergence. 417e031d6f5SAlp Dener 418e031d6f5SAlp Dener In practice, this approach simply trades off Hessian evaluations 419e031d6f5SAlp Dener for more gradient evaluations. 420e031d6f5SAlp Dener */ 421e031d6f5SAlp Dener 422c0f10754SAlp Dener PetscErrorCode TaoBNKTakeCGSteps(Tao tao, PetscBool *terminate) 423c0f10754SAlp Dener { 424c0f10754SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 425c0f10754SAlp Dener PetscErrorCode ierr; 426c0f10754SAlp Dener 427c0f10754SAlp Dener PetscFunctionBegin; 428c0f10754SAlp Dener *terminate = PETSC_FALSE; 429c0f10754SAlp Dener if (bnk->max_cg_its > 0) { 430c0f10754SAlp Dener /* Copy the current solution, unprojected gradient and step info into BNCG */ 431c0f10754SAlp Dener bnk->bncg_ctx->f = bnk->f; 432*937a31a1SAlp Dener ierr = VecCopy(tao->solution, bnk->bncg->solution);CHKERRQ(ierr); 433c0f10754SAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->bncg_ctx->unprojected_gradient);CHKERRQ(ierr); 434c0f10754SAlp Dener ierr = VecCopy(tao->stepdirection, bnk->bncg->stepdirection);CHKERRQ(ierr); 435c0f10754SAlp Dener /* Take some small finite number of BNCG iterations */ 436c0f10754SAlp Dener ierr = TaoSolve(bnk->bncg);CHKERRQ(ierr); 437c0f10754SAlp Dener /* Add the number of gradient and function evaluations to the total */ 438c0f10754SAlp Dener tao->nfuncs += bnk->bncg->nfuncs; 439c0f10754SAlp Dener tao->nfuncgrads += bnk->bncg->nfuncgrads; 440c0f10754SAlp Dener tao->ngrads += bnk->bncg->ngrads; 441c0f10754SAlp Dener tao->nhess += bnk->bncg->nhess; 442e031d6f5SAlp Dener bnk->tot_cg_its += bnk->bncg->niter; 443c0f10754SAlp Dener /* Extract the BNCG solution out and save it into BNK */ 444c0f10754SAlp Dener bnk->f = bnk->bncg_ctx->f; 445c0f10754SAlp Dener ierr = VecCopy(bnk->bncg->solution, tao->solution); 446c0f10754SAlp Dener ierr = VecCopy(bnk->bncg_ctx->unprojected_gradient, bnk->unprojected_gradient); 447*937a31a1SAlp Dener ierr = VecCopy(bnk->bncg->gradient, tao->gradient);CHKERRQ(ierr); 448c0f10754SAlp 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) { 449c0f10754SAlp Dener *terminate = PETSC_TRUE; 450c0f10754SAlp Dener } 451c0f10754SAlp Dener } 452c0f10754SAlp Dener PetscFunctionReturn(0); 453c0f10754SAlp Dener } 454c0f10754SAlp Dener 4552f75a4aaSAlp Dener /*------------------------------------------------------------*/ 4562f75a4aaSAlp Dener 457c0f10754SAlp Dener /* Routine for computing the Newton step. */ 458df278d8fSAlp Dener 45962675beeSAlp Dener PetscErrorCode TaoBNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason) 460eb910715SAlp Dener { 461eb910715SAlp Dener PetscErrorCode ierr; 462eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 463eb910715SAlp Dener 464e465cd6fSAlp Dener PetscReal delta; 465eb910715SAlp Dener PetscInt bfgsUpdates = 0; 466eb910715SAlp Dener PetscInt kspits; 467eb910715SAlp Dener 468eb910715SAlp Dener PetscFunctionBegin; 4695e9b73cbSAlp Dener /* Prepare the reduced sub-matrices for the inactive set */ 47008752603SAlp Dener ierr = TaoBNKEstimateActiveSet(tao, bnk->as_type);CHKERRQ(ierr); 4712f75a4aaSAlp Dener if (BNK_PC_BFGS == bnk->pc_type) { ierr = MatLMVMSetInactive(bnk->M, bnk->inactive_idx);CHKERRQ(ierr); } 4722f75a4aaSAlp Dener if (bnk->inactive_idx) { 4735e9b73cbSAlp Dener ierr = MatDestroy(&bnk->H_inactive); 4745e9b73cbSAlp Dener ierr = MatCreateSubMatrix(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->H_inactive);CHKERRQ(ierr); 475eb3ba6a7SAlp Dener if (tao->hessian == tao->hessian_pre) { 476eb3ba6a7SAlp Dener bnk->Hpre_inactive = bnk->H_inactive; 477eb3ba6a7SAlp Dener } else { 4785e9b73cbSAlp Dener ierr = MatDestroy(&bnk->Hpre_inactive); 4795e9b73cbSAlp Dener ierr = MatCreateSubMatrix(tao->hessian_pre, bnk->inactive_idx, bnk->inactive_idx, MAT_INITIAL_MATRIX, &bnk->Hpre_inactive);CHKERRQ(ierr); 480eb3ba6a7SAlp Dener } 4812f75a4aaSAlp Dener } else { 48262675beeSAlp Dener ierr = MatDestroy(&bnk->H_inactive); 48362675beeSAlp Dener ierr = MatDuplicate(tao->hessian, MAT_COPY_VALUES, &bnk->H_inactive); 48462675beeSAlp Dener if (tao->hessian == tao->hessian_pre) { 48562675beeSAlp Dener bnk->Hpre_inactive = bnk->H_inactive; 48662675beeSAlp Dener } else { 48762675beeSAlp Dener ierr = MatDestroy(&bnk->Hpre_inactive); 48862675beeSAlp Dener ierr = MatDuplicate(tao->hessian_pre, MAT_COPY_VALUES, &bnk->Hpre_inactive); 48962675beeSAlp Dener } 49062675beeSAlp Dener } 49162675beeSAlp Dener 49262675beeSAlp Dener /* Shift the reduced Hessian matrix */ 49362675beeSAlp Dener if ((shift) && (bnk->pert > 0)) { 49462675beeSAlp Dener ierr = MatShift(bnk->H_inactive, bnk->pert);CHKERRQ(ierr); 49562675beeSAlp Dener if (bnk->H_inactive != bnk->Hpre_inactive) { 49662675beeSAlp Dener ierr = MatShift(bnk->Hpre_inactive, bnk->pert);CHKERRQ(ierr); 49762675beeSAlp Dener } 49862675beeSAlp Dener } 49962675beeSAlp Dener 50062675beeSAlp Dener /* Update the diagonal scaling for the BFGS preconditioner, this time with the Hessian perturbation */ 50162675beeSAlp Dener if ((BNK_PC_BFGS == bnk->pc_type) && (BFGS_SCALE_PHESS == bnk->bfgs_scale_type)) { 50262675beeSAlp Dener /* Obtain diagonal for the bfgs preconditioner */ 5035e9b73cbSAlp Dener ierr = VecSet(bnk->Diag, 1.0);CHKERRQ(ierr); 5045e9b73cbSAlp Dener if (bnk->inactive_idx) { 5055e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr); 5065e9b73cbSAlp Dener } else { 5075e9b73cbSAlp Dener bnk->Diag_red = bnk->Diag; 5085e9b73cbSAlp Dener } 5095e9b73cbSAlp Dener ierr = MatGetDiagonal(bnk->H_inactive, bnk->Diag_red);CHKERRQ(ierr); 5105e9b73cbSAlp Dener if (bnk->inactive_idx) { 5115e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Diag, bnk->inactive_idx, &bnk->Diag_red);CHKERRQ(ierr); 5125e9b73cbSAlp Dener } 51362675beeSAlp Dener ierr = VecAbs(bnk->Diag);CHKERRQ(ierr); 51462675beeSAlp Dener ierr = VecMedian(bnk->Diag_min, bnk->Diag, bnk->Diag_max, bnk->Diag);CHKERRQ(ierr); 51562675beeSAlp Dener ierr = VecReciprocal(bnk->Diag);CHKERRQ(ierr); 51662675beeSAlp Dener ierr = MatLMVMSetScale(bnk->M,bnk->Diag);CHKERRQ(ierr); 5172f75a4aaSAlp Dener } 51809164190SAlp Dener 519eb910715SAlp Dener /* Solve the Newton system of equations */ 520*937a31a1SAlp Dener tao->ksp_its = 0; 5212f75a4aaSAlp Dener ierr = VecSet(tao->stepdirection, 0.0);CHKERRQ(ierr); 5225e9b73cbSAlp Dener ierr = KSPReset(tao->ksp);CHKERRQ(ierr); 52309164190SAlp Dener ierr = KSPSetOperators(tao->ksp,bnk->H_inactive,bnk->Hpre_inactive);CHKERRQ(ierr); 5245e9b73cbSAlp Dener ierr = VecCopy(bnk->unprojected_gradient, bnk->Gwork);CHKERRQ(ierr); 5255e9b73cbSAlp Dener if (bnk->inactive_idx) { 5265e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 5275e9b73cbSAlp Dener ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 5285e9b73cbSAlp Dener } else { 5295e9b73cbSAlp Dener bnk->G_inactive = bnk->unprojected_gradient; 5305e9b73cbSAlp Dener bnk->X_inactive = tao->stepdirection; 53128017e9fSAlp Dener } 532eb910715SAlp Dener if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) { 533fed79b8eSAlp Dener ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); 5345e9b73cbSAlp Dener ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr); 535eb910715SAlp Dener ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr); 536eb910715SAlp Dener tao->ksp_its+=kspits; 537eb910715SAlp Dener tao->ksp_tot_its+=kspits; 538080d2917SAlp Dener ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr); 539eb910715SAlp Dener 540eb910715SAlp Dener if (0.0 == tao->trust) { 541eb910715SAlp Dener /* Radius was uninitialized; use the norm of the direction */ 542080d2917SAlp Dener if (bnk->dnorm > 0.0) { 543080d2917SAlp Dener tao->trust = bnk->dnorm; 544eb910715SAlp Dener 545eb910715SAlp Dener /* Modify the radius if it is too large or small */ 546eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 547eb910715SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 548eb910715SAlp Dener } else { 549eb910715SAlp Dener /* The direction was bad; set radius to default value and re-solve 550eb910715SAlp Dener the trust-region subproblem to get a direction */ 551eb910715SAlp Dener tao->trust = tao->trust0; 552eb910715SAlp Dener 553eb910715SAlp Dener /* Modify the radius if it is too large or small */ 554eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 555eb910715SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 556eb910715SAlp Dener 557fed79b8eSAlp Dener ierr = KSPCGSetRadius(tao->ksp,tao->trust);CHKERRQ(ierr); 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; 562080d2917SAlp Dener ierr = KSPCGGetNormD(tao->ksp,&bnk->dnorm);CHKERRQ(ierr); 563eb910715SAlp Dener 564080d2917SAlp Dener if (bnk->dnorm == 0.0) SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero"); 565eb910715SAlp Dener } 566eb910715SAlp Dener } 567eb910715SAlp Dener } else { 5685e9b73cbSAlp Dener ierr = KSPSolve(tao->ksp, bnk->G_inactive, bnk->X_inactive);CHKERRQ(ierr); 569eb910715SAlp Dener ierr = KSPGetIterationNumber(tao->ksp, &kspits);CHKERRQ(ierr); 570eb910715SAlp Dener tao->ksp_its += kspits; 571eb910715SAlp Dener tao->ksp_tot_its+=kspits; 572eb910715SAlp Dener } 5735e9b73cbSAlp Dener /* Restore sub vectors back */ 5745e9b73cbSAlp Dener if (bnk->inactive_idx) { 5755e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 5765e9b73cbSAlp Dener ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 5775e9b73cbSAlp Dener } 578770b7498SAlp Dener /* Make sure the safeguarded fall-back step is zero for actively bounded variables */ 579fed79b8eSAlp Dener ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 5802f75a4aaSAlp Dener ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr); 581770b7498SAlp Dener 582770b7498SAlp Dener /* Record convergence reasons */ 583e465cd6fSAlp Dener ierr = KSPGetConvergedReason(tao->ksp, ksp_reason);CHKERRQ(ierr); 584e465cd6fSAlp Dener if (KSP_CONVERGED_ATOL == *ksp_reason) { 585770b7498SAlp Dener ++bnk->ksp_atol; 586e465cd6fSAlp Dener } else if (KSP_CONVERGED_RTOL == *ksp_reason) { 587770b7498SAlp Dener ++bnk->ksp_rtol; 588e465cd6fSAlp Dener } else if (KSP_CONVERGED_CG_CONSTRAINED == *ksp_reason) { 589770b7498SAlp Dener ++bnk->ksp_ctol; 590e465cd6fSAlp Dener } else if (KSP_CONVERGED_CG_NEG_CURVE == *ksp_reason) { 591770b7498SAlp Dener ++bnk->ksp_negc; 592e465cd6fSAlp Dener } else if (KSP_DIVERGED_DTOL == *ksp_reason) { 593770b7498SAlp Dener ++bnk->ksp_dtol; 594e465cd6fSAlp Dener } else if (KSP_DIVERGED_ITS == *ksp_reason) { 595770b7498SAlp Dener ++bnk->ksp_iter; 596770b7498SAlp Dener } else { 597770b7498SAlp Dener ++bnk->ksp_othr; 598770b7498SAlp Dener } 599fed79b8eSAlp Dener 600fed79b8eSAlp Dener /* Make sure the BFGS preconditioner is healthy */ 601fed79b8eSAlp Dener if (bnk->pc_type == BNK_PC_BFGS) { 602fed79b8eSAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 603e465cd6fSAlp Dener if ((KSP_DIVERGED_INDEFINITE_PC == *ksp_reason) && (bfgsUpdates > 1)) { 604fed79b8eSAlp Dener /* Preconditioner is numerically indefinite; reset the approximation. */ 6059b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 606eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M,delta);CHKERRQ(ierr); 607eb910715SAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 60809164190SAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 609eb910715SAlp Dener } 610fed79b8eSAlp Dener } 611e465cd6fSAlp Dener PetscFunctionReturn(0); 612e465cd6fSAlp Dener } 613eb910715SAlp Dener 61462675beeSAlp Dener /*------------------------------------------------------------*/ 61562675beeSAlp Dener 6165e9b73cbSAlp Dener /* Routine for recomputing the predicted reduction for a given step vector */ 6175e9b73cbSAlp Dener 6185e9b73cbSAlp Dener PetscErrorCode TaoBNKRecomputePred(Tao tao, Vec S, PetscReal *prered) 6195e9b73cbSAlp Dener { 6205e9b73cbSAlp Dener PetscErrorCode ierr; 6215e9b73cbSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 6225e9b73cbSAlp Dener 6235e9b73cbSAlp Dener PetscFunctionBegin; 6245e9b73cbSAlp Dener /* Extract subvectors associated with the inactive set */ 6255e9b73cbSAlp Dener if (bnk->inactive_idx){ 6265e9b73cbSAlp Dener ierr = VecGetSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 6275e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 6285e9b73cbSAlp Dener ierr = VecGetSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 6295e9b73cbSAlp Dener } else { 6305e9b73cbSAlp Dener bnk->X_inactive = tao->stepdirection; 6315e9b73cbSAlp Dener bnk->inactive_work = bnk->Xwork; 6325e9b73cbSAlp Dener bnk->G_inactive = bnk->Gwork; 6335e9b73cbSAlp Dener } 6345e9b73cbSAlp Dener /* Recompute the predicted decrease based on the quadratic model */ 6355e9b73cbSAlp Dener ierr = MatMult(bnk->H_inactive, bnk->X_inactive, bnk->inactive_work);CHKERRQ(ierr); 6365e9b73cbSAlp Dener ierr = VecAYPX(bnk->inactive_work, -0.5, bnk->G_inactive);CHKERRQ(ierr); 6375e9b73cbSAlp Dener ierr = VecDot(bnk->inactive_work, bnk->X_inactive, prered); 6385e9b73cbSAlp Dener /* Restore the sub vectors */ 6395e9b73cbSAlp Dener if (bnk->inactive_idx){ 6405e9b73cbSAlp Dener ierr = VecRestoreSubVector(tao->stepdirection, bnk->inactive_idx, &bnk->X_inactive);CHKERRQ(ierr); 6415e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Xwork, bnk->inactive_idx, &bnk->inactive_work);CHKERRQ(ierr); 6425e9b73cbSAlp Dener ierr = VecRestoreSubVector(bnk->Gwork, bnk->inactive_idx, &bnk->G_inactive);CHKERRQ(ierr); 6435e9b73cbSAlp Dener } 6445e9b73cbSAlp Dener PetscFunctionReturn(0); 6455e9b73cbSAlp Dener } 6465e9b73cbSAlp Dener 6475e9b73cbSAlp Dener /*------------------------------------------------------------*/ 6485e9b73cbSAlp Dener 64962675beeSAlp Dener /* Routine for ensuring that the Newton step is a descent direction. 65062675beeSAlp Dener 65162675beeSAlp Dener The step direction falls back onto BFGS, scaled gradient and gradient steps 65262675beeSAlp Dener in the event that the Newton step fails the test. 65362675beeSAlp Dener */ 65462675beeSAlp Dener 655e465cd6fSAlp Dener PetscErrorCode TaoBNKSafeguardStep(Tao tao, KSPConvergedReason ksp_reason, PetscInt *stepType) 656e465cd6fSAlp Dener { 657e465cd6fSAlp Dener PetscErrorCode ierr; 658e465cd6fSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 659e465cd6fSAlp Dener 660e465cd6fSAlp Dener PetscReal gdx, delta, e_min; 661e465cd6fSAlp Dener PetscInt bfgsUpdates; 662e465cd6fSAlp Dener 663e465cd6fSAlp Dener PetscFunctionBegin; 664080d2917SAlp Dener ierr = VecDot(tao->stepdirection, tao->gradient, &gdx);CHKERRQ(ierr); 665eb910715SAlp Dener if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) { 666eb910715SAlp Dener /* Newton step is not descent or direction produced Inf or NaN 667eb910715SAlp Dener Update the perturbation for next time */ 668eb910715SAlp Dener if (bnk->pert <= 0.0) { 669eb910715SAlp Dener /* Initialize the perturbation */ 670eb910715SAlp Dener bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm)); 671eb910715SAlp Dener if (bnk->is_gltr) { 672eb910715SAlp Dener ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr); 673eb910715SAlp Dener bnk->pert = PetscMax(bnk->pert, -e_min); 674eb910715SAlp Dener } 675eb910715SAlp Dener } else { 676eb910715SAlp Dener /* Increase the perturbation */ 677eb910715SAlp Dener bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm)); 678eb910715SAlp Dener } 679eb910715SAlp Dener 680eb910715SAlp Dener if (BNK_PC_BFGS != bnk->pc_type) { 681eb910715SAlp Dener /* We don't have the bfgs matrix around and updated 682eb910715SAlp Dener Must use gradient direction in this case */ 683080d2917SAlp Dener ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr); 684eb910715SAlp Dener *stepType = BNK_GRADIENT; 685eb910715SAlp Dener } else { 686eb910715SAlp Dener /* Attempt to use the BFGS direction */ 6872ab2a32cSAlp Dener ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr); 68809164190SAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 689eb910715SAlp Dener 6908d5ead36SAlp Dener /* Check for success (descent direction) 6918d5ead36SAlp Dener NOTE: Negative gdx here means not a descent direction because 6928d5ead36SAlp Dener the fall-back step is missing a negative sign. */ 693080d2917SAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr); 6948d5ead36SAlp Dener if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) { 695eb910715SAlp Dener /* BFGS direction is not descent or direction produced not a number 696eb910715SAlp Dener We can assert bfgsUpdates > 1 in this case because 697eb910715SAlp Dener the first solve produces the scaled gradient direction, 698eb910715SAlp Dener which is guaranteed to be descent */ 699eb910715SAlp Dener 700eb910715SAlp Dener /* Use steepest descent direction (scaled) */ 7019b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 702eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 703eb910715SAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 70409164190SAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 70509164190SAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 706eb910715SAlp Dener 707eb910715SAlp Dener *stepType = BNK_SCALED_GRADIENT; 708eb910715SAlp Dener } else { 709770b7498SAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 710eb910715SAlp Dener if (1 == bfgsUpdates) { 711eb910715SAlp Dener /* The first BFGS direction is always the scaled gradient */ 712eb910715SAlp Dener *stepType = BNK_SCALED_GRADIENT; 713eb910715SAlp Dener } else { 714eb910715SAlp Dener *stepType = BNK_BFGS; 715eb910715SAlp Dener } 716eb910715SAlp Dener } 717eb910715SAlp Dener } 7188d5ead36SAlp Dener /* Make sure the safeguarded fall-back step is zero for actively bounded variables */ 7198d5ead36SAlp Dener ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 7202f75a4aaSAlp Dener ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr); 721eb910715SAlp Dener } else { 722eb910715SAlp Dener /* Computed Newton step is descent */ 723eb910715SAlp Dener switch (ksp_reason) { 724eb910715SAlp Dener case KSP_DIVERGED_NANORINF: 725eb910715SAlp Dener case KSP_DIVERGED_BREAKDOWN: 726eb910715SAlp Dener case KSP_DIVERGED_INDEFINITE_MAT: 727eb910715SAlp Dener case KSP_DIVERGED_INDEFINITE_PC: 728eb910715SAlp Dener case KSP_CONVERGED_CG_NEG_CURVE: 729eb910715SAlp Dener /* Matrix or preconditioner is indefinite; increase perturbation */ 730eb910715SAlp Dener if (bnk->pert <= 0.0) { 731eb910715SAlp Dener /* Initialize the perturbation */ 732eb910715SAlp Dener bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm)); 733eb910715SAlp Dener if (bnk->is_gltr) { 734eb910715SAlp Dener ierr = KSPCGGLTRGetMinEig(tao->ksp, &e_min);CHKERRQ(ierr); 735eb910715SAlp Dener bnk->pert = PetscMax(bnk->pert, -e_min); 736eb910715SAlp Dener } 737eb910715SAlp Dener } else { 738eb910715SAlp Dener /* Increase the perturbation */ 739eb910715SAlp Dener bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm)); 740eb910715SAlp Dener } 741eb910715SAlp Dener break; 742eb910715SAlp Dener 743eb910715SAlp Dener default: 744eb910715SAlp Dener /* Newton step computation is good; decrease perturbation */ 745eb910715SAlp Dener bnk->pert = PetscMin(bnk->psfac * bnk->pert, bnk->pmsfac * bnk->gnorm); 746eb910715SAlp Dener if (bnk->pert < bnk->pmin) { 747eb910715SAlp Dener bnk->pert = 0.0; 748eb910715SAlp Dener } 749eb910715SAlp Dener break; 750eb910715SAlp Dener } 751fed79b8eSAlp Dener *stepType = BNK_NEWTON; 752eb910715SAlp Dener } 753eb910715SAlp Dener PetscFunctionReturn(0); 754eb910715SAlp Dener } 755eb910715SAlp Dener 756df278d8fSAlp Dener /*------------------------------------------------------------*/ 757df278d8fSAlp Dener 758df278d8fSAlp Dener /* Routine for performing a bound-projected More-Thuente line search. 759df278d8fSAlp Dener 760df278d8fSAlp Dener Includes fallbacks to BFGS, scaled gradient, and unscaled gradient steps if the 761df278d8fSAlp Dener Newton step does not produce a valid step length. 762df278d8fSAlp Dener */ 763df278d8fSAlp Dener 764*937a31a1SAlp Dener PetscErrorCode TaoBNKPerformLineSearch(Tao tao, PetscInt *stepType, PetscReal *steplen, TaoLineSearchConvergedReason *reason) 765c14b763aSAlp Dener { 766c14b763aSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 767c14b763aSAlp Dener PetscErrorCode ierr; 768c14b763aSAlp Dener TaoLineSearchConvergedReason ls_reason; 769c14b763aSAlp Dener 770c14b763aSAlp Dener PetscReal e_min, gdx, delta; 771c14b763aSAlp Dener PetscInt bfgsUpdates; 772c14b763aSAlp Dener 773c14b763aSAlp Dener PetscFunctionBegin; 774c14b763aSAlp Dener /* Perform the linesearch */ 775c14b763aSAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr); 776c14b763aSAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 777c14b763aSAlp Dener 778*937a31a1SAlp Dener while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && *stepType != BNK_GRADIENT) { 779c14b763aSAlp Dener /* Linesearch failed, revert solution */ 780c14b763aSAlp Dener bnk->f = bnk->fold; 781c14b763aSAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 782c14b763aSAlp Dener ierr = VecCopy(bnk->unprojected_gradient_old, bnk->unprojected_gradient);CHKERRQ(ierr); 783c14b763aSAlp Dener 784*937a31a1SAlp Dener switch(*stepType) { 785c14b763aSAlp Dener case BNK_NEWTON: 7868d5ead36SAlp Dener /* Failed to obtain acceptable iterate with Newton step 787c14b763aSAlp Dener Update the perturbation for next time */ 788c14b763aSAlp Dener if (bnk->pert <= 0.0) { 789c14b763aSAlp Dener /* Initialize the perturbation */ 790c14b763aSAlp Dener bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm)); 791c14b763aSAlp Dener if (bnk->is_gltr) { 792c14b763aSAlp Dener ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr); 793c14b763aSAlp Dener bnk->pert = PetscMax(bnk->pert, -e_min); 794c14b763aSAlp Dener } 795c14b763aSAlp Dener } else { 796c14b763aSAlp Dener /* Increase the perturbation */ 797c14b763aSAlp Dener bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm)); 798c14b763aSAlp Dener } 799c14b763aSAlp Dener 800c14b763aSAlp Dener if (BNK_PC_BFGS != bnk->pc_type) { 801c14b763aSAlp Dener /* We don't have the bfgs matrix around and being updated 802c14b763aSAlp Dener Must use gradient direction in this case */ 803*937a31a1SAlp Dener ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 804*937a31a1SAlp Dener *stepType = BNK_GRADIENT; 805c14b763aSAlp Dener } else { 806c14b763aSAlp Dener /* Attempt to use the BFGS direction */ 807*937a31a1SAlp Dener ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr); 808c14b763aSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 8098d5ead36SAlp Dener /* Check for success (descent direction) 8108d5ead36SAlp Dener NOTE: Negative gdx means not a descent direction because the step here is missing a negative sign. */ 811c14b763aSAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr); 812c14b763aSAlp Dener if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) { 813c14b763aSAlp Dener /* BFGS direction is not descent or direction produced not a number 814c14b763aSAlp Dener We can assert bfgsUpdates > 1 in this case 815c14b763aSAlp Dener Use steepest descent direction (scaled) */ 8169b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 817c14b763aSAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 818c14b763aSAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 819c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 820c14b763aSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 821c14b763aSAlp Dener 822c14b763aSAlp Dener bfgsUpdates = 1; 823*937a31a1SAlp Dener *stepType = BNK_SCALED_GRADIENT; 824c14b763aSAlp Dener } else { 825c14b763aSAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 826c14b763aSAlp Dener if (1 == bfgsUpdates) { 827c14b763aSAlp Dener /* The first BFGS direction is always the scaled gradient */ 828*937a31a1SAlp Dener *stepType = BNK_SCALED_GRADIENT; 829c14b763aSAlp Dener } else { 830*937a31a1SAlp Dener *stepType = BNK_BFGS; 831c14b763aSAlp Dener } 832c14b763aSAlp Dener } 833c14b763aSAlp Dener } 834c14b763aSAlp Dener break; 835c14b763aSAlp Dener 836c14b763aSAlp Dener case BNK_BFGS: 837c14b763aSAlp Dener /* Can only enter if pc_type == BNK_PC_BFGS 838c14b763aSAlp Dener Failed to obtain acceptable iterate with BFGS step 839c14b763aSAlp Dener Attempt to use the scaled gradient direction */ 8409b6ef848SAlp Dener delta = 2.0 * PetscMax(1.0, PetscAbsScalar(bnk->f)) / (bnk->gnorm*bnk->gnorm); 841c14b763aSAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 842c14b763aSAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 843c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 844*937a31a1SAlp Dener ierr = MatLMVMSetInactive(bnk->M, NULL);CHKERRQ(ierr); 845c14b763aSAlp Dener ierr = MatLMVMSolve(bnk->M, bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 846c14b763aSAlp Dener 847c14b763aSAlp Dener bfgsUpdates = 1; 848*937a31a1SAlp Dener *stepType = BNK_SCALED_GRADIENT; 849c14b763aSAlp Dener break; 850c14b763aSAlp Dener 851c14b763aSAlp Dener case BNK_SCALED_GRADIENT: 852c14b763aSAlp Dener /* Can only enter if pc_type == BNK_PC_BFGS 853c14b763aSAlp Dener The scaled gradient step did not produce a new iterate; 854*937a31a1SAlp Dener reset the BFGS matrix and attemp to use the gradient direction. */ 855c14b763aSAlp Dener ierr = MatLMVMSetScale(bnk->M,0);CHKERRQ(ierr); 856c14b763aSAlp Dener ierr = MatLMVMSetDelta(bnk->M,1.0);CHKERRQ(ierr); 857c14b763aSAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 858c14b763aSAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 859*937a31a1SAlp Dener ierr = VecCopy(bnk->unprojected_gradient, tao->stepdirection);CHKERRQ(ierr); 860c14b763aSAlp Dener 861c14b763aSAlp Dener bfgsUpdates = 1; 862*937a31a1SAlp Dener *stepType = BNK_GRADIENT; 863c14b763aSAlp Dener break; 864c14b763aSAlp Dener } 8658d5ead36SAlp Dener /* Make sure the safeguarded fall-back step is zero for actively bounded variables */ 8668d5ead36SAlp Dener ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 8672f75a4aaSAlp Dener ierr = TaoBNKBoundStep(tao, tao->stepdirection);CHKERRQ(ierr); 868c14b763aSAlp Dener 8698d5ead36SAlp Dener /* Perform one last line search with the fall-back step */ 870c14b763aSAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, bnk->unprojected_gradient, tao->stepdirection, steplen, &ls_reason);CHKERRQ(ierr); 871c14b763aSAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 872c14b763aSAlp Dener } 873c14b763aSAlp Dener *reason = ls_reason; 874c14b763aSAlp Dener PetscFunctionReturn(0); 875c14b763aSAlp Dener } 876c14b763aSAlp Dener 877df278d8fSAlp Dener /*------------------------------------------------------------*/ 878df278d8fSAlp Dener 879df278d8fSAlp Dener /* Routine for updating the trust radius. 880df278d8fSAlp Dener 881df278d8fSAlp Dener Function features three different update methods: 882df278d8fSAlp Dener 1) Line-search step length based 883df278d8fSAlp Dener 2) Predicted decrease on the CG quadratic model 884df278d8fSAlp Dener 3) Interpolation 885df278d8fSAlp Dener */ 886df278d8fSAlp Dener 88728017e9fSAlp Dener PetscErrorCode TaoBNKUpdateTrustRadius(Tao tao, PetscReal prered, PetscReal actred, PetscInt updateType, PetscInt stepType, PetscBool *accept) 888080d2917SAlp Dener { 889080d2917SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 890080d2917SAlp Dener PetscErrorCode ierr; 891080d2917SAlp Dener 892b1c2d0e3SAlp Dener PetscReal step, kappa; 893080d2917SAlp Dener PetscReal gdx, tau_1, tau_2, tau_min, tau_max; 894080d2917SAlp Dener 895080d2917SAlp Dener PetscFunctionBegin; 896080d2917SAlp Dener /* Update trust region radius */ 897080d2917SAlp Dener *accept = PETSC_FALSE; 89828017e9fSAlp Dener switch(updateType) { 899080d2917SAlp Dener case BNK_UPDATE_STEP: 900c14b763aSAlp Dener *accept = PETSC_TRUE; /* always accept here because line search succeeded */ 901080d2917SAlp Dener if (stepType == BNK_NEWTON) { 902080d2917SAlp Dener ierr = TaoLineSearchGetStepLength(tao->linesearch, &step);CHKERRQ(ierr); 903080d2917SAlp Dener if (step < bnk->nu1) { 904080d2917SAlp Dener /* Very bad step taken; reduce radius */ 905080d2917SAlp Dener tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust); 906080d2917SAlp Dener } else if (step < bnk->nu2) { 907080d2917SAlp Dener /* Reasonably bad step taken; reduce radius */ 908080d2917SAlp Dener tao->trust = bnk->omega2 * PetscMin(bnk->dnorm, tao->trust); 909080d2917SAlp Dener } else if (step < bnk->nu3) { 910080d2917SAlp Dener /* Reasonable step was taken; leave radius alone */ 911080d2917SAlp Dener if (bnk->omega3 < 1.0) { 912080d2917SAlp Dener tao->trust = bnk->omega3 * PetscMin(bnk->dnorm, tao->trust); 913080d2917SAlp Dener } else if (bnk->omega3 > 1.0) { 914080d2917SAlp Dener tao->trust = PetscMax(bnk->omega3 * bnk->dnorm, tao->trust); 915080d2917SAlp Dener } 916080d2917SAlp Dener } else if (step < bnk->nu4) { 917080d2917SAlp Dener /* Full step taken; increase the radius */ 918080d2917SAlp Dener tao->trust = PetscMax(bnk->omega4 * bnk->dnorm, tao->trust); 919080d2917SAlp Dener } else { 920080d2917SAlp Dener /* More than full step taken; increase the radius */ 921080d2917SAlp Dener tao->trust = PetscMax(bnk->omega5 * bnk->dnorm, tao->trust); 922080d2917SAlp Dener } 923080d2917SAlp Dener } else { 924080d2917SAlp Dener /* Newton step was not good; reduce the radius */ 925080d2917SAlp Dener tao->trust = bnk->omega1 * PetscMin(bnk->dnorm, tao->trust); 926080d2917SAlp Dener } 927080d2917SAlp Dener break; 928080d2917SAlp Dener 929080d2917SAlp Dener case BNK_UPDATE_REDUCTION: 930080d2917SAlp Dener if (stepType == BNK_NEWTON) { 931b1c2d0e3SAlp Dener if (prered < 0.0) { 932fed79b8eSAlp Dener /* The predicted reduction has the wrong sign. This cannot 933fed79b8eSAlp Dener happen in infinite precision arithmetic. Step should 934fed79b8eSAlp Dener be rejected! */ 935080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm); 936fed79b8eSAlp Dener } 937fed79b8eSAlp Dener else { 938b1c2d0e3SAlp Dener if (PetscIsInfOrNanReal(actred)) { 939080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm); 940080d2917SAlp Dener } else { 9410a4511e9SAlp Dener if ((PetscAbsScalar(actred) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon) && 9420a4511e9SAlp Dener (PetscAbsScalar(prered) <= PetscMax(1.0, PetscAbsScalar(bnk->f))*bnk->epsilon)) { 943080d2917SAlp Dener kappa = 1.0; 944fed79b8eSAlp Dener } 945fed79b8eSAlp Dener else { 946080d2917SAlp Dener kappa = actred / prered; 947080d2917SAlp Dener } 948fed79b8eSAlp Dener 949fed79b8eSAlp Dener /* Accept or reject the step and update radius */ 950080d2917SAlp Dener if (kappa < bnk->eta1) { 951fed79b8eSAlp Dener /* Reject the step */ 952080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, bnk->dnorm); 953fed79b8eSAlp Dener } 954fed79b8eSAlp Dener else { 955fed79b8eSAlp Dener /* Accept the step */ 956c133c014SAlp Dener *accept = PETSC_TRUE; 957c133c014SAlp Dener /* Update the trust region radius only if the computed step is at the trust radius boundary */ 9588d5ead36SAlp Dener if (bnk->dnorm == tao->trust) { 959080d2917SAlp Dener if (kappa < bnk->eta2) { 960080d2917SAlp Dener /* Marginal bad step */ 961c133c014SAlp Dener tao->trust = bnk->alpha2 * tao->trust; 962080d2917SAlp Dener } 963fed79b8eSAlp Dener else if (kappa < bnk->eta3) { 964fed79b8eSAlp Dener /* Reasonable step */ 965fed79b8eSAlp Dener tao->trust = bnk->alpha3 * tao->trust; 966fed79b8eSAlp Dener } 967fed79b8eSAlp Dener else if (kappa < bnk->eta4) { 968080d2917SAlp Dener /* Good step */ 969c133c014SAlp Dener tao->trust = bnk->alpha4 * tao->trust; 970fed79b8eSAlp Dener } 971fed79b8eSAlp Dener else { 972080d2917SAlp Dener /* Very good step */ 973c133c014SAlp Dener tao->trust = bnk->alpha5 * tao->trust; 974080d2917SAlp Dener } 975c133c014SAlp Dener } 976080d2917SAlp Dener } 977080d2917SAlp Dener } 978080d2917SAlp Dener } 979080d2917SAlp Dener } else { 980080d2917SAlp Dener /* Newton step was not good; reduce the radius */ 981080d2917SAlp Dener tao->trust = bnk->alpha1 * PetscMin(bnk->dnorm, tao->trust); 982080d2917SAlp Dener } 983080d2917SAlp Dener break; 984080d2917SAlp Dener 985080d2917SAlp Dener default: 986080d2917SAlp Dener if (stepType == BNK_NEWTON) { 987b1c2d0e3SAlp Dener if (prered < 0.0) { 988080d2917SAlp Dener /* The predicted reduction has the wrong sign. This cannot */ 989080d2917SAlp Dener /* happen in infinite precision arithmetic. Step should */ 990080d2917SAlp Dener /* be rejected! */ 991080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 992080d2917SAlp Dener } else { 993b1c2d0e3SAlp Dener if (PetscIsInfOrNanReal(actred)) { 994080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 995080d2917SAlp Dener } else { 996080d2917SAlp Dener if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) { 997080d2917SAlp Dener kappa = 1.0; 998080d2917SAlp Dener } else { 999080d2917SAlp Dener kappa = actred / prered; 1000080d2917SAlp Dener } 1001080d2917SAlp Dener 1002080d2917SAlp Dener ierr = VecDot(tao->gradient, tao->stepdirection, &gdx);CHKERRQ(ierr); 1003080d2917SAlp Dener tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred); 1004080d2917SAlp Dener tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred); 1005080d2917SAlp Dener tau_min = PetscMin(tau_1, tau_2); 1006080d2917SAlp Dener tau_max = PetscMax(tau_1, tau_2); 1007080d2917SAlp Dener 1008080d2917SAlp Dener if (kappa >= 1.0 - bnk->mu1) { 1009080d2917SAlp Dener /* Great agreement */ 1010080d2917SAlp Dener *accept = PETSC_TRUE; 1011080d2917SAlp Dener if (tau_max < 1.0) { 1012080d2917SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm); 1013080d2917SAlp Dener } else if (tau_max > bnk->gamma4) { 1014080d2917SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma4 * bnk->dnorm); 1015080d2917SAlp Dener } else { 1016080d2917SAlp Dener tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm); 1017080d2917SAlp Dener } 1018080d2917SAlp Dener } else if (kappa >= 1.0 - bnk->mu2) { 1019080d2917SAlp Dener /* Good agreement */ 1020080d2917SAlp Dener *accept = PETSC_TRUE; 1021080d2917SAlp Dener if (tau_max < bnk->gamma2) { 1022080d2917SAlp Dener tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm); 1023080d2917SAlp Dener } else if (tau_max > bnk->gamma3) { 1024080d2917SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma3 * bnk->dnorm); 1025080d2917SAlp Dener } else if (tau_max < 1.0) { 1026080d2917SAlp Dener tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm); 1027080d2917SAlp Dener } else { 1028080d2917SAlp Dener tao->trust = PetscMax(tao->trust, tau_max * bnk->dnorm); 1029080d2917SAlp Dener } 1030080d2917SAlp Dener } else { 1031080d2917SAlp Dener /* Not good agreement */ 1032080d2917SAlp Dener if (tau_min > 1.0) { 1033080d2917SAlp Dener tao->trust = bnk->gamma2 * PetscMin(tao->trust, bnk->dnorm); 1034080d2917SAlp Dener } else if (tau_max < bnk->gamma1) { 1035080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 1036080d2917SAlp Dener } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) { 1037080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, bnk->dnorm); 1038080d2917SAlp Dener } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) { 1039080d2917SAlp Dener tao->trust = tau_1 * PetscMin(tao->trust, bnk->dnorm); 1040080d2917SAlp Dener } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) { 1041080d2917SAlp Dener tao->trust = tau_2 * PetscMin(tao->trust, bnk->dnorm); 1042080d2917SAlp Dener } else { 1043080d2917SAlp Dener tao->trust = tau_max * PetscMin(tao->trust, bnk->dnorm); 1044080d2917SAlp Dener } 1045080d2917SAlp Dener } 1046080d2917SAlp Dener } 1047080d2917SAlp Dener } 1048080d2917SAlp Dener } else { 1049080d2917SAlp Dener /* Newton step was not good; reduce the radius */ 1050080d2917SAlp Dener tao->trust = bnk->gamma1 * PetscMin(bnk->dnorm, tao->trust); 1051080d2917SAlp Dener } 105228017e9fSAlp Dener break; 1053080d2917SAlp Dener } 1054c133c014SAlp Dener /* Make sure the radius does not violate min and max settings */ 1055c133c014SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 1056fed79b8eSAlp Dener tao->trust = PetscMax(tao->trust, bnk->min_radius); 1057080d2917SAlp Dener PetscFunctionReturn(0); 1058080d2917SAlp Dener } 1059080d2917SAlp Dener 1060eb910715SAlp Dener /* ---------------------------------------------------------- */ 1061df278d8fSAlp Dener 106262675beeSAlp Dener PetscErrorCode TaoBNKAddStepCounts(Tao tao, PetscInt stepType) 106362675beeSAlp Dener { 106462675beeSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 106562675beeSAlp Dener 106662675beeSAlp Dener PetscFunctionBegin; 106762675beeSAlp Dener switch (stepType) { 106862675beeSAlp Dener case BNK_NEWTON: 106962675beeSAlp Dener ++bnk->newt; 107062675beeSAlp Dener break; 107162675beeSAlp Dener case BNK_BFGS: 107262675beeSAlp Dener ++bnk->bfgs; 107362675beeSAlp Dener break; 107462675beeSAlp Dener case BNK_SCALED_GRADIENT: 107562675beeSAlp Dener ++bnk->sgrad; 107662675beeSAlp Dener break; 107762675beeSAlp Dener case BNK_GRADIENT: 107862675beeSAlp Dener ++bnk->grad; 107962675beeSAlp Dener break; 108062675beeSAlp Dener default: 108162675beeSAlp Dener break; 108262675beeSAlp Dener } 108362675beeSAlp Dener PetscFunctionReturn(0); 108462675beeSAlp Dener } 108562675beeSAlp Dener 108662675beeSAlp Dener /* ---------------------------------------------------------- */ 108762675beeSAlp Dener 10889b6ef848SAlp Dener PetscErrorCode TaoSetUp_BNK(Tao tao) 1089eb910715SAlp Dener { 1090eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1091eb910715SAlp Dener PetscErrorCode ierr; 10929b6ef848SAlp Dener KSPType ksp_type; 1093e031d6f5SAlp Dener PetscInt i; 1094eb910715SAlp Dener 1095eb910715SAlp Dener PetscFunctionBegin; 1096eb910715SAlp Dener if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr);} 1097eb910715SAlp Dener if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr);} 1098eb910715SAlp Dener if (!bnk->W) {ierr = VecDuplicate(tao->solution,&bnk->W);CHKERRQ(ierr);} 1099eb910715SAlp Dener if (!bnk->Xold) {ierr = VecDuplicate(tao->solution,&bnk->Xold);CHKERRQ(ierr);} 1100eb910715SAlp Dener if (!bnk->Gold) {ierr = VecDuplicate(tao->solution,&bnk->Gold);CHKERRQ(ierr);} 110109164190SAlp Dener if (!bnk->Xwork) {ierr = VecDuplicate(tao->solution,&bnk->Xwork);CHKERRQ(ierr);} 110209164190SAlp Dener if (!bnk->Gwork) {ierr = VecDuplicate(tao->solution,&bnk->Gwork);CHKERRQ(ierr);} 110309164190SAlp Dener if (!bnk->unprojected_gradient) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient);CHKERRQ(ierr);} 110409164190SAlp Dener if (!bnk->unprojected_gradient_old) {ierr = VecDuplicate(tao->solution,&bnk->unprojected_gradient_old);CHKERRQ(ierr);} 11055e9b73cbSAlp Dener if (!bnk->Diag_min) {ierr = VecDuplicate(tao->solution,&bnk->Diag_min);CHKERRQ(ierr);} 11065e9b73cbSAlp Dener if (!bnk->Diag_max) {ierr = VecDuplicate(tao->solution,&bnk->Diag_max);CHKERRQ(ierr);} 1107e031d6f5SAlp Dener if (bnk->max_cg_its > 0) { 1108e031d6f5SAlp Dener if (!bnk->bncg_sol) {ierr = VecDuplicate(tao->solution,&bnk->bncg_sol);CHKERRQ(ierr);} 1109e031d6f5SAlp Dener ierr = TaoSetInitialVector(bnk->bncg, bnk->bncg_sol);CHKERRQ(ierr); 1110e031d6f5SAlp Dener ierr = TaoSetMaximumIterations(bnk->bncg, bnk->max_cg_its);CHKERRQ(ierr); 1111e031d6f5SAlp Dener ierr = TaoSetTolerances(bnk->bncg, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr); 1112e031d6f5SAlp Dener ierr = TaoSetFunctionLowerBound(bnk->bncg, tao->fmin);CHKERRQ(ierr); 1113e031d6f5SAlp Dener 1114*937a31a1SAlp Dener ierr = TaoSetConvergenceTest(bnk->bncg, tao->ops->convergencetest, tao->cnvP);CHKERRQ(ierr); 1115e031d6f5SAlp Dener ierr = TaoSetObjectiveRoutine(bnk->bncg, tao->ops->computeobjective, tao->user_objP);CHKERRQ(ierr); 1116e031d6f5SAlp Dener ierr = TaoSetGradientRoutine(bnk->bncg, tao->ops->computegradient, tao->user_gradP);CHKERRQ(ierr); 1117e031d6f5SAlp Dener ierr = TaoSetObjectiveAndGradientRoutine(bnk->bncg, tao->ops->computeobjectiveandgradient, tao->user_objgradP);CHKERRQ(ierr); 1118e031d6f5SAlp Dener ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)tao, (PetscObject)(bnk->bncg));CHKERRQ(ierr); 1119e031d6f5SAlp Dener for (i=0; i<tao->numbermonitors; i++) { 1120e031d6f5SAlp Dener ierr = TaoSetMonitor(bnk->bncg, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr); 1121e031d6f5SAlp Dener ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr); 1122e031d6f5SAlp Dener } 1123*937a31a1SAlp Dener ierr = TaoSetUp(bnk->bncg);CHKERRQ(ierr); 1124e031d6f5SAlp Dener bnk->bncg_ctx = (TAO_BNCG *)bnk->bncg->data; 1125e031d6f5SAlp Dener } 1126eb910715SAlp Dener bnk->Diag = 0; 1127c0f10754SAlp Dener bnk->Diag_red = 0; 1128c0f10754SAlp Dener bnk->X_inactive = 0; 1129c0f10754SAlp Dener bnk->G_inactive = 0; 113062675beeSAlp Dener bnk->inactive_work = 0; 113162675beeSAlp Dener bnk->active_work = 0; 113262675beeSAlp Dener bnk->inactive_idx = 0; 113362675beeSAlp Dener bnk->active_idx = 0; 113462675beeSAlp Dener bnk->active_lower = 0; 113562675beeSAlp Dener bnk->active_upper = 0; 113662675beeSAlp Dener bnk->active_fixed = 0; 1137eb910715SAlp Dener bnk->M = 0; 113809164190SAlp Dener bnk->H_inactive = 0; 113909164190SAlp Dener bnk->Hpre_inactive = 0; 11409b6ef848SAlp Dener ierr = KSPGetType(tao->ksp,&ksp_type);CHKERRQ(ierr); 11419b6ef848SAlp Dener ierr = PetscStrcmp(ksp_type,KSPCGNASH,&bnk->is_nash);CHKERRQ(ierr); 11429b6ef848SAlp Dener ierr = PetscStrcmp(ksp_type,KSPCGSTCG,&bnk->is_stcg);CHKERRQ(ierr); 11439b6ef848SAlp Dener ierr = PetscStrcmp(ksp_type,KSPCGGLTR,&bnk->is_gltr);CHKERRQ(ierr); 1144eb910715SAlp Dener PetscFunctionReturn(0); 1145eb910715SAlp Dener } 1146eb910715SAlp Dener 1147eb910715SAlp Dener /*------------------------------------------------------------*/ 1148df278d8fSAlp Dener 1149eb910715SAlp Dener static PetscErrorCode TaoDestroy_BNK(Tao tao) 1150eb910715SAlp Dener { 1151eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1152eb910715SAlp Dener PetscErrorCode ierr; 1153eb910715SAlp Dener 1154eb910715SAlp Dener PetscFunctionBegin; 1155eb910715SAlp Dener if (tao->setupcalled) { 1156eb910715SAlp Dener ierr = VecDestroy(&bnk->W);CHKERRQ(ierr); 1157eb910715SAlp Dener ierr = VecDestroy(&bnk->Xold);CHKERRQ(ierr); 1158eb910715SAlp Dener ierr = VecDestroy(&bnk->Gold);CHKERRQ(ierr); 115909164190SAlp Dener ierr = VecDestroy(&bnk->Xwork);CHKERRQ(ierr); 116009164190SAlp Dener ierr = VecDestroy(&bnk->Gwork);CHKERRQ(ierr); 116109164190SAlp Dener ierr = VecDestroy(&bnk->unprojected_gradient);CHKERRQ(ierr); 116209164190SAlp Dener ierr = VecDestroy(&bnk->unprojected_gradient_old);CHKERRQ(ierr); 116362675beeSAlp Dener ierr = VecDestroy(&bnk->Diag_min);CHKERRQ(ierr); 116462675beeSAlp Dener ierr = VecDestroy(&bnk->Diag_max);CHKERRQ(ierr); 1165c0f10754SAlp Dener if (bnk->max_cg_its > 0) { 1166c0f10754SAlp Dener ierr = TaoDestroy(&bnk->bncg);CHKERRQ(ierr); 1167c0f10754SAlp Dener ierr = VecDestroy(&bnk->bncg_sol);CHKERRQ(ierr); 1168c0f10754SAlp Dener } 11695e9b73cbSAlp Dener } 11705e9b73cbSAlp Dener ierr = VecDestroy(&bnk->Diag);CHKERRQ(ierr); 1171eb910715SAlp Dener ierr = MatDestroy(&bnk->M);CHKERRQ(ierr); 1172c0f10754SAlp Dener if (bnk->Hpre_inactive != tao->hessian_pre && bnk->Hpre_inactive != bnk->H_inactive) {ierr = MatDestroy(&bnk->Hpre_inactive);CHKERRQ(ierr);} 1173c0f10754SAlp Dener if (bnk->H_inactive != tao->hessian) {ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr);} 1174eb910715SAlp Dener ierr = PetscFree(tao->data);CHKERRQ(ierr); 1175eb910715SAlp Dener PetscFunctionReturn(0); 1176eb910715SAlp Dener } 1177eb910715SAlp Dener 1178eb910715SAlp Dener /*------------------------------------------------------------*/ 1179df278d8fSAlp Dener 1180eb910715SAlp Dener static PetscErrorCode TaoSetFromOptions_BNK(PetscOptionItems *PetscOptionsObject,Tao tao) 1181eb910715SAlp Dener { 1182eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1183eb910715SAlp Dener PetscErrorCode ierr; 1184eb910715SAlp Dener 1185eb910715SAlp Dener PetscFunctionBegin; 1186eb910715SAlp Dener ierr = PetscOptionsHead(PetscOptionsObject,"Newton line search method for unconstrained optimization");CHKERRQ(ierr); 11878d5ead36SAlp 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); 11888d5ead36SAlp 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); 11898d5ead36SAlp 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); 11908d5ead36SAlp 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); 11912f75a4aaSAlp 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); 11928d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_sval", "perturbation starting value", "", bnk->sval, &bnk->sval,NULL);CHKERRQ(ierr); 11938d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_imin", "minimum initial perturbation", "", bnk->imin, &bnk->imin,NULL);CHKERRQ(ierr); 11948d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_imax", "maximum initial perturbation", "", bnk->imax, &bnk->imax,NULL);CHKERRQ(ierr); 11958d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_imfac", "initial merit factor", "", bnk->imfac, &bnk->imfac,NULL);CHKERRQ(ierr); 11968d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmin", "minimum perturbation", "", bnk->pmin, &bnk->pmin,NULL);CHKERRQ(ierr); 11978d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmax", "maximum perturbation", "", bnk->pmax, &bnk->pmax,NULL);CHKERRQ(ierr); 11988d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pgfac", "growth factor", "", bnk->pgfac, &bnk->pgfac,NULL);CHKERRQ(ierr); 11998d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_psfac", "shrink factor", "", bnk->psfac, &bnk->psfac,NULL);CHKERRQ(ierr); 12008d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmgfac", "merit growth factor", "", bnk->pmgfac, &bnk->pmgfac,NULL);CHKERRQ(ierr); 12018d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_pmsfac", "merit shrink factor", "", bnk->pmsfac, &bnk->pmsfac,NULL);CHKERRQ(ierr); 12028d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta1", "poor steplength; reduce radius", "", bnk->eta1, &bnk->eta1,NULL);CHKERRQ(ierr); 12038d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta2", "reasonable steplength; leave radius alone", "", bnk->eta2, &bnk->eta2,NULL);CHKERRQ(ierr); 12048d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta3", "good steplength; increase radius", "", bnk->eta3, &bnk->eta3,NULL);CHKERRQ(ierr); 12058d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_eta4", "excellent steplength; greatly increase radius", "", bnk->eta4, &bnk->eta4,NULL);CHKERRQ(ierr); 12068d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha1", "", "", bnk->alpha1, &bnk->alpha1,NULL);CHKERRQ(ierr); 12078d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha2", "", "", bnk->alpha2, &bnk->alpha2,NULL);CHKERRQ(ierr); 12088d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha3", "", "", bnk->alpha3, &bnk->alpha3,NULL);CHKERRQ(ierr); 12098d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha4", "", "", bnk->alpha4, &bnk->alpha4,NULL);CHKERRQ(ierr); 12108d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_alpha5", "", "", bnk->alpha5, &bnk->alpha5,NULL);CHKERRQ(ierr); 12118d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu1", "poor steplength; reduce radius", "", bnk->nu1, &bnk->nu1,NULL);CHKERRQ(ierr); 12128d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu2", "reasonable steplength; leave radius alone", "", bnk->nu2, &bnk->nu2,NULL);CHKERRQ(ierr); 12138d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu3", "good steplength; increase radius", "", bnk->nu3, &bnk->nu3,NULL);CHKERRQ(ierr); 12148d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_nu4", "excellent steplength; greatly increase radius", "", bnk->nu4, &bnk->nu4,NULL);CHKERRQ(ierr); 12158d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega1", "", "", bnk->omega1, &bnk->omega1,NULL);CHKERRQ(ierr); 12168d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega2", "", "", bnk->omega2, &bnk->omega2,NULL);CHKERRQ(ierr); 12178d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega3", "", "", bnk->omega3, &bnk->omega3,NULL);CHKERRQ(ierr); 12188d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega4", "", "", bnk->omega4, &bnk->omega4,NULL);CHKERRQ(ierr); 12198d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_omega5", "", "", bnk->omega5, &bnk->omega5,NULL);CHKERRQ(ierr); 12208d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu1_i", "", "", bnk->mu1_i, &bnk->mu1_i,NULL);CHKERRQ(ierr); 12218d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu2_i", "", "", bnk->mu2_i, &bnk->mu2_i,NULL);CHKERRQ(ierr); 12228d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma1_i", "", "", bnk->gamma1_i, &bnk->gamma1_i,NULL);CHKERRQ(ierr); 12238d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma2_i", "", "", bnk->gamma2_i, &bnk->gamma2_i,NULL);CHKERRQ(ierr); 12248d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma3_i", "", "", bnk->gamma3_i, &bnk->gamma3_i,NULL);CHKERRQ(ierr); 12258d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma4_i", "", "", bnk->gamma4_i, &bnk->gamma4_i,NULL);CHKERRQ(ierr); 12268d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_theta_i", "", "", bnk->theta_i, &bnk->theta_i,NULL);CHKERRQ(ierr); 12278d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu1", "", "", bnk->mu1, &bnk->mu1,NULL);CHKERRQ(ierr); 12288d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_mu2", "", "", bnk->mu2, &bnk->mu2,NULL);CHKERRQ(ierr); 12298d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma1", "", "", bnk->gamma1, &bnk->gamma1,NULL);CHKERRQ(ierr); 12308d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma2", "", "", bnk->gamma2, &bnk->gamma2,NULL);CHKERRQ(ierr); 12318d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma3", "", "", bnk->gamma3, &bnk->gamma3,NULL);CHKERRQ(ierr); 12328d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_gamma4", "", "", bnk->gamma4, &bnk->gamma4,NULL);CHKERRQ(ierr); 12338d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_theta", "", "", bnk->theta, &bnk->theta,NULL);CHKERRQ(ierr); 12348d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_min_radius", "lower bound on initial radius", "", bnk->min_radius, &bnk->min_radius,NULL);CHKERRQ(ierr); 12358d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_max_radius", "upper bound on radius", "", bnk->max_radius, &bnk->max_radius,NULL);CHKERRQ(ierr); 12368d5ead36SAlp Dener ierr = PetscOptionsReal("-tao_bnk_epsilon", "tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon,NULL);CHKERRQ(ierr); 12370a4511e9SAlp Dener ierr = PetscOptionsReal("-tao_bnk_as_tol", "initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol,NULL);CHKERRQ(ierr); 12380a4511e9SAlp Dener ierr = PetscOptionsReal("-tao_bnk_as_step", "step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step,NULL);CHKERRQ(ierr); 1239c0f10754SAlp 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); 1240eb910715SAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 1241e031d6f5SAlp Dener ierr = TaoSetFromOptions(bnk->bncg); 1242eb910715SAlp Dener ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr); 1243eb910715SAlp Dener ierr = KSPSetFromOptions(tao->ksp);CHKERRQ(ierr); 1244eb910715SAlp Dener PetscFunctionReturn(0); 1245eb910715SAlp Dener } 1246eb910715SAlp Dener 1247eb910715SAlp Dener /*------------------------------------------------------------*/ 1248df278d8fSAlp Dener 1249eb910715SAlp Dener static PetscErrorCode TaoView_BNK(Tao tao, PetscViewer viewer) 1250eb910715SAlp Dener { 1251eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 1252eb910715SAlp Dener PetscInt nrejects; 1253eb910715SAlp Dener PetscBool isascii; 1254eb910715SAlp Dener PetscErrorCode ierr; 1255eb910715SAlp Dener 1256eb910715SAlp Dener PetscFunctionBegin; 1257eb910715SAlp Dener ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 1258eb910715SAlp Dener if (isascii) { 1259eb910715SAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 1260eb910715SAlp Dener if (BNK_PC_BFGS == bnk->pc_type && bnk->M) { 1261eb910715SAlp Dener ierr = MatLMVMGetRejects(bnk->M,&nrejects);CHKERRQ(ierr); 1262eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects);CHKERRQ(ierr); 1263eb910715SAlp Dener } 1264e031d6f5SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "CG steps: %D\n", bnk->tot_cg_its);CHKERRQ(ierr); 1265eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", bnk->newt);CHKERRQ(ierr); 1266eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", bnk->bfgs);CHKERRQ(ierr); 1267eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", bnk->sgrad);CHKERRQ(ierr); 1268eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", bnk->grad);CHKERRQ(ierr); 1269eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, "KSP termination reasons:\n");CHKERRQ(ierr); 1270eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " atol: %D\n", bnk->ksp_atol);CHKERRQ(ierr); 1271eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " rtol: %D\n", bnk->ksp_rtol);CHKERRQ(ierr); 1272eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " ctol: %D\n", bnk->ksp_ctol);CHKERRQ(ierr); 1273eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " negc: %D\n", bnk->ksp_negc);CHKERRQ(ierr); 1274eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " dtol: %D\n", bnk->ksp_dtol);CHKERRQ(ierr); 1275eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " iter: %D\n", bnk->ksp_iter);CHKERRQ(ierr); 1276eb910715SAlp Dener ierr = PetscViewerASCIIPrintf(viewer, " othr: %D\n", bnk->ksp_othr);CHKERRQ(ierr); 1277eb910715SAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 1278eb910715SAlp Dener } 1279eb910715SAlp Dener PetscFunctionReturn(0); 1280eb910715SAlp Dener } 1281eb910715SAlp Dener 1282eb910715SAlp Dener /* ---------------------------------------------------------- */ 1283df278d8fSAlp Dener 1284eb910715SAlp Dener /*MC 1285eb910715SAlp Dener TAOBNK - Shared base-type for Bounded Newton-Krylov type algorithms. 128666ed3702SAlp Dener At each iteration, the BNK methods solve the symmetric 1287eb910715SAlp Dener system of equations to obtain the step diretion dk: 1288eb910715SAlp Dener Hk dk = -gk 12892b97c8d8SAlp Dener for free variables only. The step can be globalized either through 12902b97c8d8SAlp Dener trust-region methods, or a line search, or a heuristic mixture of both. 1291eb910715SAlp Dener 1292eb910715SAlp Dener Options Database Keys: 12938d5ead36SAlp Dener + -tao_bnk_pc_type - "none","ahess","bfgs","petsc" 12948d5ead36SAlp Dener . -tao_bnk_bfgs_scale_type - "ahess","phess","bfgs" 12958d5ead36SAlp Dener . -tao_bnk_init_type - "constant","direction","interpolation" 12968d5ead36SAlp Dener . -tao_bnk_update_type - "step","direction","interpolation" 12972f75a4aaSAlp Dener . -tao_bnk_as_type - "none","bertsekas" 12988d5ead36SAlp Dener . -tao_bnk_sval - perturbation starting value 12998d5ead36SAlp Dener . -tao_bnk_imin - minimum initial perturbation 13008d5ead36SAlp Dener . -tao_bnk_imax - maximum initial perturbation 13018d5ead36SAlp Dener . -tao_bnk_pmin - minimum perturbation 13028d5ead36SAlp Dener . -tao_bnk_pmax - maximum perturbation 13038d5ead36SAlp Dener . -tao_bnk_pgfac - growth factor 13048d5ead36SAlp Dener . -tao_bnk_psfac - shrink factor 13058d5ead36SAlp Dener . -tao_bnk_imfac - initial merit factor 13068d5ead36SAlp Dener . -tao_bnk_pmgfac - merit growth factor 13078d5ead36SAlp Dener . -tao_bnk_pmsfac - merit shrink factor 13088d5ead36SAlp Dener . -tao_bnk_eta1 - poor steplength; reduce radius 13098d5ead36SAlp Dener . -tao_bnk_eta2 - reasonable steplength; leave radius 13108d5ead36SAlp Dener . -tao_bnk_eta3 - good steplength; increase readius 13118d5ead36SAlp Dener . -tao_bnk_eta4 - excellent steplength; greatly increase radius 13128d5ead36SAlp Dener . -tao_bnk_alpha1 - alpha1 reduction 13138d5ead36SAlp Dener . -tao_bnk_alpha2 - alpha2 reduction 13148d5ead36SAlp Dener . -tao_bnk_alpha3 - alpha3 reduction 13158d5ead36SAlp Dener . -tao_bnk_alpha4 - alpha4 reduction 13168d5ead36SAlp Dener . -tao_bnk_alpha - alpha5 reduction 13178d5ead36SAlp Dener . -tao_bnk_mu1 - mu1 interpolation update 13188d5ead36SAlp Dener . -tao_bnk_mu2 - mu2 interpolation update 13198d5ead36SAlp Dener . -tao_bnk_gamma1 - gamma1 interpolation update 13208d5ead36SAlp Dener . -tao_bnk_gamma2 - gamma2 interpolation update 13218d5ead36SAlp Dener . -tao_bnk_gamma3 - gamma3 interpolation update 13228d5ead36SAlp Dener . -tao_bnk_gamma4 - gamma4 interpolation update 13238d5ead36SAlp Dener . -tao_bnk_theta - theta interpolation update 13248d5ead36SAlp Dener . -tao_bnk_omega1 - omega1 step update 13258d5ead36SAlp Dener . -tao_bnk_omega2 - omega2 step update 13268d5ead36SAlp Dener . -tao_bnk_omega3 - omega3 step update 13278d5ead36SAlp Dener . -tao_bnk_omega4 - omega4 step update 13288d5ead36SAlp Dener . -tao_bnk_omega5 - omega5 step update 13298d5ead36SAlp Dener . -tao_bnk_mu1_i - mu1 interpolation init factor 13308d5ead36SAlp Dener . -tao_bnk_mu2_i - mu2 interpolation init factor 13318d5ead36SAlp Dener . -tao_bnk_gamma1_i - gamma1 interpolation init factor 13328d5ead36SAlp Dener . -tao_bnk_gamma2_i - gamma2 interpolation init factor 13338d5ead36SAlp Dener . -tao_bnk_gamma3_i - gamma3 interpolation init factor 13348d5ead36SAlp Dener . -tao_bnk_gamma4_i - gamma4 interpolation init factor 13352f75a4aaSAlp Dener . -tao_bnk_theta_i - theta interpolation init factor 13362f75a4aaSAlp Dener - -tao_bnk_bound_tol - initial tolerance used in estimating bounded active variables 1337eb910715SAlp Dener 1338eb910715SAlp Dener Level: beginner 1339eb910715SAlp Dener M*/ 1340eb910715SAlp Dener 1341eb910715SAlp Dener PetscErrorCode TaoCreate_BNK(Tao tao) 1342eb910715SAlp Dener { 1343eb910715SAlp Dener TAO_BNK *bnk; 1344eb910715SAlp Dener const char *morethuente_type = TAOLINESEARCHMT; 1345eb910715SAlp Dener PetscErrorCode ierr; 1346eb910715SAlp Dener 1347eb910715SAlp Dener PetscFunctionBegin; 1348eb910715SAlp Dener ierr = PetscNewLog(tao,&bnk);CHKERRQ(ierr); 1349eb910715SAlp Dener 1350eb910715SAlp Dener tao->ops->setup = TaoSetUp_BNK; 1351eb910715SAlp Dener tao->ops->view = TaoView_BNK; 1352eb910715SAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_BNK; 1353eb910715SAlp Dener tao->ops->destroy = TaoDestroy_BNK; 1354eb910715SAlp Dener 1355eb910715SAlp Dener /* Override default settings (unless already changed) */ 1356eb910715SAlp Dener if (!tao->max_it_changed) tao->max_it = 50; 1357eb910715SAlp Dener if (!tao->trust0_changed) tao->trust0 = 100.0; 1358eb910715SAlp Dener 1359eb910715SAlp Dener tao->data = (void*)bnk; 1360eb910715SAlp Dener 136166ed3702SAlp Dener /* Hessian shifting parameters */ 1362eb910715SAlp Dener bnk->sval = 0.0; 1363eb910715SAlp Dener bnk->imin = 1.0e-4; 1364eb910715SAlp Dener bnk->imax = 1.0e+2; 1365eb910715SAlp Dener bnk->imfac = 1.0e-1; 1366eb910715SAlp Dener 1367eb910715SAlp Dener bnk->pmin = 1.0e-12; 1368eb910715SAlp Dener bnk->pmax = 1.0e+2; 1369eb910715SAlp Dener bnk->pgfac = 1.0e+1; 1370eb910715SAlp Dener bnk->psfac = 4.0e-1; 1371eb910715SAlp Dener bnk->pmgfac = 1.0e-1; 1372eb910715SAlp Dener bnk->pmsfac = 1.0e-1; 1373eb910715SAlp Dener 1374eb910715SAlp Dener /* Default values for trust-region radius update based on steplength */ 1375eb910715SAlp Dener bnk->nu1 = 0.25; 1376eb910715SAlp Dener bnk->nu2 = 0.50; 1377eb910715SAlp Dener bnk->nu3 = 1.00; 1378eb910715SAlp Dener bnk->nu4 = 1.25; 1379eb910715SAlp Dener 1380eb910715SAlp Dener bnk->omega1 = 0.25; 1381eb910715SAlp Dener bnk->omega2 = 0.50; 1382eb910715SAlp Dener bnk->omega3 = 1.00; 1383eb910715SAlp Dener bnk->omega4 = 2.00; 1384eb910715SAlp Dener bnk->omega5 = 4.00; 1385eb910715SAlp Dener 1386eb910715SAlp Dener /* Default values for trust-region radius update based on reduction */ 1387eb910715SAlp Dener bnk->eta1 = 1.0e-4; 1388eb910715SAlp Dener bnk->eta2 = 0.25; 1389eb910715SAlp Dener bnk->eta3 = 0.50; 1390eb910715SAlp Dener bnk->eta4 = 0.90; 1391eb910715SAlp Dener 1392eb910715SAlp Dener bnk->alpha1 = 0.25; 1393eb910715SAlp Dener bnk->alpha2 = 0.50; 1394eb910715SAlp Dener bnk->alpha3 = 1.00; 1395eb910715SAlp Dener bnk->alpha4 = 2.00; 1396eb910715SAlp Dener bnk->alpha5 = 4.00; 1397eb910715SAlp Dener 1398eb910715SAlp Dener /* Default values for trust-region radius update based on interpolation */ 1399eb910715SAlp Dener bnk->mu1 = 0.10; 1400eb910715SAlp Dener bnk->mu2 = 0.50; 1401eb910715SAlp Dener 1402eb910715SAlp Dener bnk->gamma1 = 0.25; 1403eb910715SAlp Dener bnk->gamma2 = 0.50; 1404eb910715SAlp Dener bnk->gamma3 = 2.00; 1405eb910715SAlp Dener bnk->gamma4 = 4.00; 1406eb910715SAlp Dener 1407eb910715SAlp Dener bnk->theta = 0.05; 1408eb910715SAlp Dener 1409eb910715SAlp Dener /* Default values for trust region initialization based on interpolation */ 1410eb910715SAlp Dener bnk->mu1_i = 0.35; 1411eb910715SAlp Dener bnk->mu2_i = 0.50; 1412eb910715SAlp Dener 1413eb910715SAlp Dener bnk->gamma1_i = 0.0625; 1414eb910715SAlp Dener bnk->gamma2_i = 0.5; 1415eb910715SAlp Dener bnk->gamma3_i = 2.0; 1416eb910715SAlp Dener bnk->gamma4_i = 5.0; 1417eb910715SAlp Dener 1418eb910715SAlp Dener bnk->theta_i = 0.25; 1419eb910715SAlp Dener 1420eb910715SAlp Dener /* Remaining parameters */ 1421c0f10754SAlp Dener bnk->max_cg_its = 0; 1422eb910715SAlp Dener bnk->min_radius = 1.0e-10; 1423eb910715SAlp Dener bnk->max_radius = 1.0e10; 1424770b7498SAlp Dener bnk->epsilon = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0); 14250a4511e9SAlp Dener bnk->as_tol = 1.0e-3; 14260a4511e9SAlp Dener bnk->as_step = 1.0e-3; 142762675beeSAlp Dener bnk->dmin = 1.0e-6; 142862675beeSAlp Dener bnk->dmax = 1.0e6; 1429eb910715SAlp Dener 1430e031d6f5SAlp Dener bnk->pc_type = BNK_PC_AHESS; 1431eb910715SAlp Dener bnk->bfgs_scale_type = BFGS_SCALE_PHESS; 1432eb910715SAlp Dener bnk->init_type = BNK_INIT_INTERPOLATION; 1433fed79b8eSAlp Dener bnk->update_type = BNK_UPDATE_INTERPOLATION; 14342f75a4aaSAlp Dener bnk->as_type = BNK_AS_BERTSEKAS; 1435eb910715SAlp Dener 1436e031d6f5SAlp Dener /* Create the embedded BNCG solver */ 1437e031d6f5SAlp Dener ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &bnk->bncg);CHKERRQ(ierr); 1438e031d6f5SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)bnk->bncg, (PetscObject)tao, 1);CHKERRQ(ierr); 1439e031d6f5SAlp Dener ierr = TaoSetOptionsPrefix(bnk->bncg, "tao_bnk_");CHKERRQ(ierr); 1440e031d6f5SAlp Dener ierr = TaoSetType(bnk->bncg, TAOBNCG);CHKERRQ(ierr); 1441e031d6f5SAlp Dener 1442c0f10754SAlp Dener /* Create the line search */ 1443eb910715SAlp Dener ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch);CHKERRQ(ierr); 1444eb910715SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr); 1445e031d6f5SAlp Dener ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr); 1446eb910715SAlp Dener ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type);CHKERRQ(ierr); 1447eb910715SAlp Dener ierr = TaoLineSearchUseTaoRoutines(tao->linesearch,tao);CHKERRQ(ierr); 1448eb910715SAlp Dener 1449eb910715SAlp Dener /* Set linear solver to default for symmetric matrices */ 1450eb910715SAlp Dener ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp);CHKERRQ(ierr); 1451eb910715SAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1);CHKERRQ(ierr); 1452eb910715SAlp Dener ierr = KSPSetOptionsPrefix(tao->ksp,tao->hdr.prefix);CHKERRQ(ierr); 1453eb910715SAlp Dener ierr = KSPSetType(tao->ksp,KSPCGSTCG);CHKERRQ(ierr); 1454eb910715SAlp Dener PetscFunctionReturn(0); 1455eb910715SAlp Dener } 1456