1*eb910715SAlp Dener #include <../src/tao/bound/impls/bnk/bnk.h> 2*eb910715SAlp Dener #include <petscksp.h> 3*eb910715SAlp Dener 4*eb910715SAlp Dener /* 5*eb910715SAlp Dener Implements Newton's Method with a line search approach for solving 6*eb910715SAlp Dener unconstrained minimization problems. A More'-Thuente line search 7*eb910715SAlp Dener is used to guarantee that the bfgs preconditioner remains positive 8*eb910715SAlp Dener definite. 9*eb910715SAlp Dener 10*eb910715SAlp Dener The method can shift the Hessian matrix. The shifting procedure is 11*eb910715SAlp Dener adapted from the PATH algorithm for solving complementarity 12*eb910715SAlp Dener problems. 13*eb910715SAlp Dener 14*eb910715SAlp Dener The linear system solve should be done with a conjugate gradient 15*eb910715SAlp Dener method, although any method can be used. 16*eb910715SAlp Dener */ 17*eb910715SAlp Dener 18*eb910715SAlp Dener static PetscErrorCode TaoSolve_BNLS(Tao tao) 19*eb910715SAlp Dener { 20*eb910715SAlp Dener PetscErrorCode ierr; 21*eb910715SAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 22*eb910715SAlp Dener TaoLineSearchConvergedReason ls_reason; 23*eb910715SAlp Dener 24*eb910715SAlp Dener PetscReal prered, actred, kappa; 25*eb910715SAlp Dener PetscReal tau_1, tau_2, tau_max, tau_min; 26*eb910715SAlp Dener PetscReal f_full, fold, gdx; 27*eb910715SAlp Dener PetscReal step = 1.0; 28*eb910715SAlp Dener PetscReal delta; 29*eb910715SAlp Dener PetscReal norm_d = 0.0, e_min; 30*eb910715SAlp Dener 31*eb910715SAlp Dener PetscInt stepType; 32*eb910715SAlp Dener PetscInt bfgsUpdates = 0; 33*eb910715SAlp Dener PetscInt needH = 1; 34*eb910715SAlp Dener 35*eb910715SAlp Dener PetscFunctionBegin; 36*eb910715SAlp Dener if (tao->XL || tao->XU || tao->ops->computebounds) { 37*eb910715SAlp Dener ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by nls algorithm\n");CHKERRQ(ierr); 38*eb910715SAlp Dener } 39*eb910715SAlp Dener 40*eb910715SAlp Dener /* Check convergence criteria */ 41*eb910715SAlp Dener ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &bnk->f, tao->gradient);CHKERRQ(ierr); 42*eb910715SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 43*eb910715SAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 44*eb910715SAlp Dener 45*eb910715SAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 46*eb910715SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 47*eb910715SAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,step);CHKERRQ(ierr); 48*eb910715SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 49*eb910715SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 50*eb910715SAlp Dener 51*eb910715SAlp Dener /* Initialize the preconditioner and trust radius */ 52*eb910715SAlp Dener ierr = TaoBNKInitialize(tao);CHKERRQ(ierr); 53*eb910715SAlp Dener 54*eb910715SAlp Dener /* Have not converged; continue with Newton method */ 55*eb910715SAlp Dener while (tao->reason == TAO_CONTINUE_ITERATING) { 56*eb910715SAlp Dener ++tao->niter; 57*eb910715SAlp Dener tao->ksp_its=0; 58*eb910715SAlp Dener 59*eb910715SAlp Dener /* Use the common BNK kernel to compute the step */ 60*eb910715SAlp Dener ierr = TaoBNKComputeStep(tao, &stepType);CHKERRQ(ierr); 61*eb910715SAlp Dener 62*eb910715SAlp Dener /* Perform the linesearch */ 63*eb910715SAlp Dener fold = bnk->f; 64*eb910715SAlp Dener ierr = VecCopy(tao->solution, bnk->Xold);CHKERRQ(ierr); 65*eb910715SAlp Dener ierr = VecCopy(tao->gradient, bnk->Gold);CHKERRQ(ierr); 66*eb910715SAlp Dener 67*eb910715SAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, tao->gradient, bnk->D, &step, &ls_reason);CHKERRQ(ierr); 68*eb910715SAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 69*eb910715SAlp Dener 70*eb910715SAlp Dener while (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER && stepType != BNK_GRADIENT) { 71*eb910715SAlp Dener /* Linesearch failed, revert solution */ 72*eb910715SAlp Dener bnk->f = fold; 73*eb910715SAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 74*eb910715SAlp Dener ierr = VecCopy(bnk->Gold, tao->gradient);CHKERRQ(ierr); 75*eb910715SAlp Dener 76*eb910715SAlp Dener switch(stepType) { 77*eb910715SAlp Dener case BNK_NEWTON: 78*eb910715SAlp Dener /* Failed to obtain acceptable iterate with Newton 1step 79*eb910715SAlp Dener Update the perturbation for next time */ 80*eb910715SAlp Dener if (bnk->pert <= 0.0) { 81*eb910715SAlp Dener /* Initialize the perturbation */ 82*eb910715SAlp Dener bnk->pert = PetscMin(bnk->imax, PetscMax(bnk->imin, bnk->imfac * bnk->gnorm)); 83*eb910715SAlp Dener if (bnk->is_gltr) { 84*eb910715SAlp Dener ierr = KSPCGGLTRGetMinEig(tao->ksp,&e_min);CHKERRQ(ierr); 85*eb910715SAlp Dener bnk->pert = PetscMax(bnk->pert, -e_min); 86*eb910715SAlp Dener } 87*eb910715SAlp Dener } else { 88*eb910715SAlp Dener /* Increase the perturbation */ 89*eb910715SAlp Dener bnk->pert = PetscMin(bnk->pmax, PetscMax(bnk->pgfac * bnk->pert, bnk->pmgfac * bnk->gnorm)); 90*eb910715SAlp Dener } 91*eb910715SAlp Dener 92*eb910715SAlp Dener if (BNK_PC_BFGS != bnk->pc_type) { 93*eb910715SAlp Dener /* We don't have the bfgs matrix around and being updated 94*eb910715SAlp Dener Must use gradient direction in this case */ 95*eb910715SAlp Dener ierr = VecCopy(tao->gradient, bnk->D);CHKERRQ(ierr); 96*eb910715SAlp Dener ++bnk->grad; 97*eb910715SAlp Dener stepType = BNK_GRADIENT; 98*eb910715SAlp Dener } else { 99*eb910715SAlp Dener /* Attempt to use the BFGS direction */ 100*eb910715SAlp Dener ierr = MatLMVMSolve(bnk->M, tao->gradient, bnk->D);CHKERRQ(ierr); 101*eb910715SAlp Dener /* Check for success (descent direction) */ 102*eb910715SAlp Dener ierr = VecDot(tao->solution, bnk->D, &gdx);CHKERRQ(ierr); 103*eb910715SAlp Dener if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) { 104*eb910715SAlp Dener /* BFGS direction is not descent or direction produced not a number 105*eb910715SAlp Dener We can assert bfgsUpdates > 1 in this case 106*eb910715SAlp Dener Use steepest descent direction (scaled) */ 107*eb910715SAlp Dener 108*eb910715SAlp Dener if (bnk->f != 0.0) { 109*eb910715SAlp Dener delta = 2.0 * PetscAbsScalar(bnk->f) / (bnk->gnorm*bnk->gnorm); 110*eb910715SAlp Dener } else { 111*eb910715SAlp Dener delta = 2.0 / (bnk->gnorm*bnk->gnorm); 112*eb910715SAlp Dener } 113*eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 114*eb910715SAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 115*eb910715SAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, tao->gradient);CHKERRQ(ierr); 116*eb910715SAlp Dener ierr = MatLMVMSolve(bnk->M, tao->gradient, bnk->D);CHKERRQ(ierr); 117*eb910715SAlp Dener 118*eb910715SAlp Dener bfgsUpdates = 1; 119*eb910715SAlp Dener ++bnk->sgrad; 120*eb910715SAlp Dener stepType = BNK_SCALED_GRADIENT; 121*eb910715SAlp Dener } else { 122*eb910715SAlp Dener ierr = MatLMVMGetUpdates(bnk->M, &bfgsUpdates);CHKERRQ(ierr); 123*eb910715SAlp Dener if (1 == bfgsUpdates) { 124*eb910715SAlp Dener /* The first BFGS direction is always the scaled gradient */ 125*eb910715SAlp Dener ++bnk->sgrad; 126*eb910715SAlp Dener stepType = BNK_SCALED_GRADIENT; 127*eb910715SAlp Dener } else { 128*eb910715SAlp Dener ++bnk->bfgs; 129*eb910715SAlp Dener stepType = BNK_BFGS; 130*eb910715SAlp Dener } 131*eb910715SAlp Dener } 132*eb910715SAlp Dener } 133*eb910715SAlp Dener break; 134*eb910715SAlp Dener 135*eb910715SAlp Dener case BNK_BFGS: 136*eb910715SAlp Dener /* Can only enter if pc_type == BNK_PC_BFGS 137*eb910715SAlp Dener Failed to obtain acceptable iterate with BFGS step 138*eb910715SAlp Dener Attempt to use the scaled gradient direction */ 139*eb910715SAlp Dener 140*eb910715SAlp Dener if (bnk->f != 0.0) { 141*eb910715SAlp Dener delta = 2.0 * PetscAbsScalar(bnk->f) / (bnk->gnorm*bnk->gnorm); 142*eb910715SAlp Dener } else { 143*eb910715SAlp Dener delta = 2.0 / (bnk->gnorm*bnk->gnorm); 144*eb910715SAlp Dener } 145*eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M, delta);CHKERRQ(ierr); 146*eb910715SAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 147*eb910715SAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, tao->gradient);CHKERRQ(ierr); 148*eb910715SAlp Dener ierr = MatLMVMSolve(bnk->M, tao->gradient, bnk->D);CHKERRQ(ierr); 149*eb910715SAlp Dener 150*eb910715SAlp Dener bfgsUpdates = 1; 151*eb910715SAlp Dener ++bnk->sgrad; 152*eb910715SAlp Dener stepType = BNK_SCALED_GRADIENT; 153*eb910715SAlp Dener break; 154*eb910715SAlp Dener 155*eb910715SAlp Dener case BNK_SCALED_GRADIENT: 156*eb910715SAlp Dener /* Can only enter if pc_type == BNK_PC_BFGS 157*eb910715SAlp Dener The scaled gradient step did not produce a new iterate; 158*eb910715SAlp Dener attemp to use the gradient direction. 159*eb910715SAlp Dener Need to make sure we are not using a different diagonal scaling */ 160*eb910715SAlp Dener 161*eb910715SAlp Dener ierr = MatLMVMSetScale(bnk->M,0);CHKERRQ(ierr); 162*eb910715SAlp Dener ierr = MatLMVMSetDelta(bnk->M,1.0);CHKERRQ(ierr); 163*eb910715SAlp Dener ierr = MatLMVMReset(bnk->M);CHKERRQ(ierr); 164*eb910715SAlp Dener ierr = MatLMVMUpdate(bnk->M, tao->solution, tao->gradient);CHKERRQ(ierr); 165*eb910715SAlp Dener ierr = MatLMVMSolve(bnk->M, tao->gradient, bnk->D);CHKERRQ(ierr); 166*eb910715SAlp Dener 167*eb910715SAlp Dener bfgsUpdates = 1; 168*eb910715SAlp Dener ++bnk->grad; 169*eb910715SAlp Dener stepType = BNK_GRADIENT; 170*eb910715SAlp Dener break; 171*eb910715SAlp Dener } 172*eb910715SAlp Dener ierr = VecScale(bnk->D, -1.0);CHKERRQ(ierr); 173*eb910715SAlp Dener 174*eb910715SAlp Dener ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &bnk->f, tao->gradient, bnk->D, &step, &ls_reason);CHKERRQ(ierr); 175*eb910715SAlp Dener ierr = TaoLineSearchGetFullStepObjective(tao->linesearch, &f_full);CHKERRQ(ierr); 176*eb910715SAlp Dener ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 177*eb910715SAlp Dener } 178*eb910715SAlp Dener 179*eb910715SAlp Dener if (ls_reason != TAOLINESEARCH_SUCCESS && ls_reason != TAOLINESEARCH_SUCCESS_USER) { 180*eb910715SAlp Dener /* Failed to find an improving point */ 181*eb910715SAlp Dener bnk->f = fold; 182*eb910715SAlp Dener ierr = VecCopy(bnk->Xold, tao->solution);CHKERRQ(ierr); 183*eb910715SAlp Dener ierr = VecCopy(bnk->Gold, tao->gradient);CHKERRQ(ierr); 184*eb910715SAlp Dener step = 0.0; 185*eb910715SAlp Dener tao->reason = TAO_DIVERGED_LS_FAILURE; 186*eb910715SAlp Dener break; 187*eb910715SAlp Dener } 188*eb910715SAlp Dener 189*eb910715SAlp Dener /* Update trust region radius */ 190*eb910715SAlp Dener if (bnk->is_nash || bnk->is_stcg || bnk->is_gltr) { 191*eb910715SAlp Dener switch(bnk->update_type) { 192*eb910715SAlp Dener case BNK_UPDATE_STEP: 193*eb910715SAlp Dener if (stepType == BNK_NEWTON) { 194*eb910715SAlp Dener if (step < bnk->nu1) { 195*eb910715SAlp Dener /* Very bad step taken; reduce radius */ 196*eb910715SAlp Dener tao->trust = bnk->omega1 * PetscMin(norm_d, tao->trust); 197*eb910715SAlp Dener } else if (step < bnk->nu2) { 198*eb910715SAlp Dener /* Reasonably bad step taken; reduce radius */ 199*eb910715SAlp Dener tao->trust = bnk->omega2 * PetscMin(norm_d, tao->trust); 200*eb910715SAlp Dener } else if (step < bnk->nu3) { 201*eb910715SAlp Dener /* Reasonable step was taken; leave radius alone */ 202*eb910715SAlp Dener if (bnk->omega3 < 1.0) { 203*eb910715SAlp Dener tao->trust = bnk->omega3 * PetscMin(norm_d, tao->trust); 204*eb910715SAlp Dener } else if (bnk->omega3 > 1.0) { 205*eb910715SAlp Dener tao->trust = PetscMax(bnk->omega3 * norm_d, tao->trust); 206*eb910715SAlp Dener } 207*eb910715SAlp Dener } else if (step < bnk->nu4) { 208*eb910715SAlp Dener /* Full step taken; increase the radius */ 209*eb910715SAlp Dener tao->trust = PetscMax(bnk->omega4 * norm_d, tao->trust); 210*eb910715SAlp Dener } else { 211*eb910715SAlp Dener /* More than full step taken; increase the radius */ 212*eb910715SAlp Dener tao->trust = PetscMax(bnk->omega5 * norm_d, tao->trust); 213*eb910715SAlp Dener } 214*eb910715SAlp Dener } else { 215*eb910715SAlp Dener /* Newton step was not good; reduce the radius */ 216*eb910715SAlp Dener tao->trust = bnk->omega1 * PetscMin(norm_d, tao->trust); 217*eb910715SAlp Dener } 218*eb910715SAlp Dener break; 219*eb910715SAlp Dener 220*eb910715SAlp Dener case BNK_UPDATE_REDUCTION: 221*eb910715SAlp Dener if (stepType == BNK_NEWTON) { 222*eb910715SAlp Dener /* Get predicted reduction */ 223*eb910715SAlp Dener ierr = KSPCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); 224*eb910715SAlp Dener if (prered >= 0.0) { 225*eb910715SAlp Dener /* The predicted reduction has the wrong sign. This cannot */ 226*eb910715SAlp Dener /* happen in infinite precision arithmetic. Step should */ 227*eb910715SAlp Dener /* be rejected! */ 228*eb910715SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, norm_d); 229*eb910715SAlp Dener } else { 230*eb910715SAlp Dener if (PetscIsInfOrNanReal(f_full)) { 231*eb910715SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, norm_d); 232*eb910715SAlp Dener } else { 233*eb910715SAlp Dener /* Compute and actual reduction */ 234*eb910715SAlp Dener actred = fold - f_full; 235*eb910715SAlp Dener prered = -prered; 236*eb910715SAlp Dener if ((PetscAbsScalar(actred) <= bnk->epsilon) && 237*eb910715SAlp Dener (PetscAbsScalar(prered) <= bnk->epsilon)) { 238*eb910715SAlp Dener kappa = 1.0; 239*eb910715SAlp Dener } else { 240*eb910715SAlp Dener kappa = actred / prered; 241*eb910715SAlp Dener } 242*eb910715SAlp Dener 243*eb910715SAlp Dener /* Accept of reject the step and update radius */ 244*eb910715SAlp Dener if (kappa < bnk->eta1) { 245*eb910715SAlp Dener /* Very bad step */ 246*eb910715SAlp Dener tao->trust = bnk->alpha1 * PetscMin(tao->trust, norm_d); 247*eb910715SAlp Dener } else if (kappa < bnk->eta2) { 248*eb910715SAlp Dener /* Marginal bad step */ 249*eb910715SAlp Dener tao->trust = bnk->alpha2 * PetscMin(tao->trust, norm_d); 250*eb910715SAlp Dener } else if (kappa < bnk->eta3) { 251*eb910715SAlp Dener /* Reasonable step */ 252*eb910715SAlp Dener if (bnk->alpha3 < 1.0) { 253*eb910715SAlp Dener tao->trust = bnk->alpha3 * PetscMin(norm_d, tao->trust); 254*eb910715SAlp Dener } else if (bnk->alpha3 > 1.0) { 255*eb910715SAlp Dener tao->trust = PetscMax(bnk->alpha3 * norm_d, tao->trust); 256*eb910715SAlp Dener } 257*eb910715SAlp Dener } else if (kappa < bnk->eta4) { 258*eb910715SAlp Dener /* Good step */ 259*eb910715SAlp Dener tao->trust = PetscMax(bnk->alpha4 * norm_d, tao->trust); 260*eb910715SAlp Dener } else { 261*eb910715SAlp Dener /* Very good step */ 262*eb910715SAlp Dener tao->trust = PetscMax(bnk->alpha5 * norm_d, tao->trust); 263*eb910715SAlp Dener } 264*eb910715SAlp Dener } 265*eb910715SAlp Dener } 266*eb910715SAlp Dener } else { 267*eb910715SAlp Dener /* Newton step was not good; reduce the radius */ 268*eb910715SAlp Dener tao->trust = bnk->alpha1 * PetscMin(norm_d, tao->trust); 269*eb910715SAlp Dener } 270*eb910715SAlp Dener break; 271*eb910715SAlp Dener 272*eb910715SAlp Dener default: 273*eb910715SAlp Dener if (stepType == BNK_NEWTON) { 274*eb910715SAlp Dener ierr = KSPCGGetObjFcn(tao->ksp,&prered);CHKERRQ(ierr); 275*eb910715SAlp Dener if (prered >= 0.0) { 276*eb910715SAlp Dener /* The predicted reduction has the wrong sign. This cannot */ 277*eb910715SAlp Dener /* happen in infinite precision arithmetic. Step should */ 278*eb910715SAlp Dener /* be rejected! */ 279*eb910715SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, norm_d); 280*eb910715SAlp Dener } else { 281*eb910715SAlp Dener if (PetscIsInfOrNanReal(f_full)) { 282*eb910715SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, norm_d); 283*eb910715SAlp Dener } else { 284*eb910715SAlp Dener actred = fold - f_full; 285*eb910715SAlp Dener prered = -prered; 286*eb910715SAlp Dener if ((PetscAbsScalar(actred) <= bnk->epsilon) && (PetscAbsScalar(prered) <= bnk->epsilon)) { 287*eb910715SAlp Dener kappa = 1.0; 288*eb910715SAlp Dener } else { 289*eb910715SAlp Dener kappa = actred / prered; 290*eb910715SAlp Dener } 291*eb910715SAlp Dener 292*eb910715SAlp Dener tau_1 = bnk->theta * gdx / (bnk->theta * gdx - (1.0 - bnk->theta) * prered + actred); 293*eb910715SAlp Dener tau_2 = bnk->theta * gdx / (bnk->theta * gdx + (1.0 + bnk->theta) * prered - actred); 294*eb910715SAlp Dener tau_min = PetscMin(tau_1, tau_2); 295*eb910715SAlp Dener tau_max = PetscMax(tau_1, tau_2); 296*eb910715SAlp Dener 297*eb910715SAlp Dener if (kappa >= 1.0 - bnk->mu1) { 298*eb910715SAlp Dener /* Great agreement */ 299*eb910715SAlp Dener if (tau_max < 1.0) { 300*eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma3 * norm_d); 301*eb910715SAlp Dener } else if (tau_max > bnk->gamma4) { 302*eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma4 * norm_d); 303*eb910715SAlp Dener } else { 304*eb910715SAlp Dener tao->trust = PetscMax(tao->trust, tau_max * norm_d); 305*eb910715SAlp Dener } 306*eb910715SAlp Dener } else if (kappa >= 1.0 - bnk->mu2) { 307*eb910715SAlp Dener /* Good agreement */ 308*eb910715SAlp Dener 309*eb910715SAlp Dener if (tau_max < bnk->gamma2) { 310*eb910715SAlp Dener tao->trust = bnk->gamma2 * PetscMin(tao->trust, norm_d); 311*eb910715SAlp Dener } else if (tau_max > bnk->gamma3) { 312*eb910715SAlp Dener tao->trust = PetscMax(tao->trust, bnk->gamma3 * norm_d); 313*eb910715SAlp Dener } else if (tau_max < 1.0) { 314*eb910715SAlp Dener tao->trust = tau_max * PetscMin(tao->trust, norm_d); 315*eb910715SAlp Dener } else { 316*eb910715SAlp Dener tao->trust = PetscMax(tao->trust, tau_max * norm_d); 317*eb910715SAlp Dener } 318*eb910715SAlp Dener } else { 319*eb910715SAlp Dener /* Not good agreement */ 320*eb910715SAlp Dener if (tau_min > 1.0) { 321*eb910715SAlp Dener tao->trust = bnk->gamma2 * PetscMin(tao->trust, norm_d); 322*eb910715SAlp Dener } else if (tau_max < bnk->gamma1) { 323*eb910715SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, norm_d); 324*eb910715SAlp Dener } else if ((tau_min < bnk->gamma1) && (tau_max >= 1.0)) { 325*eb910715SAlp Dener tao->trust = bnk->gamma1 * PetscMin(tao->trust, norm_d); 326*eb910715SAlp Dener } else if ((tau_1 >= bnk->gamma1) && (tau_1 < 1.0) && ((tau_2 < bnk->gamma1) || (tau_2 >= 1.0))) { 327*eb910715SAlp Dener tao->trust = tau_1 * PetscMin(tao->trust, norm_d); 328*eb910715SAlp Dener } else if ((tau_2 >= bnk->gamma1) && (tau_2 < 1.0) && ((tau_1 < bnk->gamma1) || (tau_2 >= 1.0))) { 329*eb910715SAlp Dener tao->trust = tau_2 * PetscMin(tao->trust, norm_d); 330*eb910715SAlp Dener } else { 331*eb910715SAlp Dener tao->trust = tau_max * PetscMin(tao->trust, norm_d); 332*eb910715SAlp Dener } 333*eb910715SAlp Dener } 334*eb910715SAlp Dener } 335*eb910715SAlp Dener } 336*eb910715SAlp Dener } else { 337*eb910715SAlp Dener /* Newton step was not good; reduce the radius */ 338*eb910715SAlp Dener tao->trust = bnk->gamma1 * PetscMin(norm_d, tao->trust); 339*eb910715SAlp Dener } 340*eb910715SAlp Dener break; 341*eb910715SAlp Dener } 342*eb910715SAlp Dener 343*eb910715SAlp Dener /* The radius may have been increased; modify if it is too large */ 344*eb910715SAlp Dener tao->trust = PetscMin(tao->trust, bnk->max_radius); 345*eb910715SAlp Dener } 346*eb910715SAlp Dener 347*eb910715SAlp Dener /* Check for termination */ 348*eb910715SAlp Dener ierr = TaoGradientNorm(tao, tao->gradient,NORM_2,&bnk->gnorm);CHKERRQ(ierr); 349*eb910715SAlp Dener if (PetscIsInfOrNanReal(bnk->f) || PetscIsInfOrNanReal(bnk->gnorm)) SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number"); 350*eb910715SAlp Dener needH = 1; 351*eb910715SAlp Dener ierr = TaoLogConvergenceHistory(tao,bnk->f,bnk->gnorm,0.0,tao->ksp_its);CHKERRQ(ierr); 352*eb910715SAlp Dener ierr = TaoMonitor(tao,tao->niter,bnk->f,bnk->gnorm,0.0,step);CHKERRQ(ierr); 353*eb910715SAlp Dener ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 354*eb910715SAlp Dener } 355*eb910715SAlp Dener PetscFunctionReturn(0); 356*eb910715SAlp Dener } 357*eb910715SAlp Dener 358*eb910715SAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BNLS(Tao tao) 359*eb910715SAlp Dener { 360*eb910715SAlp Dener PetscErrorCode ierr; 361*eb910715SAlp Dener 362*eb910715SAlp Dener PetscFunctionBegin; 363*eb910715SAlp Dener ierr = TaoCreate_BNK(tao);CHKERRQ(ierr); 364*eb910715SAlp Dener tao->ops->solve=TaoSolve_BNLS; 365*eb910715SAlp Dener PetscFunctionReturn(0); 366*eb910715SAlp Dener }