1*a7e14dcfSSatish Balay #include "src/matrix/lmvmmat.h" 2*a7e14dcfSSatish Balay #include "ntr.h" 3*a7e14dcfSSatish Balay 4*a7e14dcfSSatish Balay #include "petscksp.h" 5*a7e14dcfSSatish Balay #include "petscpc.h" 6*a7e14dcfSSatish Balay #include "petsc-private/kspimpl.h" 7*a7e14dcfSSatish Balay #include "petsc-private/pcimpl.h" 8*a7e14dcfSSatish Balay 9*a7e14dcfSSatish Balay #define NTR_KSP_NASH 0 10*a7e14dcfSSatish Balay #define NTR_KSP_STCG 1 11*a7e14dcfSSatish Balay #define NTR_KSP_GLTR 2 12*a7e14dcfSSatish Balay #define NTR_KSP_TYPES 3 13*a7e14dcfSSatish Balay 14*a7e14dcfSSatish Balay #define NTR_PC_NONE 0 15*a7e14dcfSSatish Balay #define NTR_PC_AHESS 1 16*a7e14dcfSSatish Balay #define NTR_PC_BFGS 2 17*a7e14dcfSSatish Balay #define NTR_PC_PETSC 3 18*a7e14dcfSSatish Balay #define NTR_PC_TYPES 4 19*a7e14dcfSSatish Balay 20*a7e14dcfSSatish Balay #define BFGS_SCALE_AHESS 0 21*a7e14dcfSSatish Balay #define BFGS_SCALE_BFGS 1 22*a7e14dcfSSatish Balay #define BFGS_SCALE_TYPES 2 23*a7e14dcfSSatish Balay 24*a7e14dcfSSatish Balay #define NTR_INIT_CONSTANT 0 25*a7e14dcfSSatish Balay #define NTR_INIT_DIRECTION 1 26*a7e14dcfSSatish Balay #define NTR_INIT_INTERPOLATION 2 27*a7e14dcfSSatish Balay #define NTR_INIT_TYPES 3 28*a7e14dcfSSatish Balay 29*a7e14dcfSSatish Balay #define NTR_UPDATE_REDUCTION 0 30*a7e14dcfSSatish Balay #define NTR_UPDATE_INTERPOLATION 1 31*a7e14dcfSSatish Balay #define NTR_UPDATE_TYPES 2 32*a7e14dcfSSatish Balay 33*a7e14dcfSSatish Balay static const char *NTR_KSP[64] = { 34*a7e14dcfSSatish Balay "nash", "stcg", "gltr" 35*a7e14dcfSSatish Balay }; 36*a7e14dcfSSatish Balay 37*a7e14dcfSSatish Balay static const char *NTR_PC[64] = { 38*a7e14dcfSSatish Balay "none", "ahess", "bfgs", "petsc" 39*a7e14dcfSSatish Balay }; 40*a7e14dcfSSatish Balay 41*a7e14dcfSSatish Balay static const char *BFGS_SCALE[64] = { 42*a7e14dcfSSatish Balay "ahess", "bfgs" 43*a7e14dcfSSatish Balay }; 44*a7e14dcfSSatish Balay 45*a7e14dcfSSatish Balay static const char *NTR_INIT[64] = { 46*a7e14dcfSSatish Balay "constant", "direction", "interpolation" 47*a7e14dcfSSatish Balay }; 48*a7e14dcfSSatish Balay 49*a7e14dcfSSatish Balay static const char *NTR_UPDATE[64] = { 50*a7e14dcfSSatish Balay "reduction", "interpolation" 51*a7e14dcfSSatish Balay }; 52*a7e14dcfSSatish Balay 53*a7e14dcfSSatish Balay /* Routine for BFGS preconditioner */ 54*a7e14dcfSSatish Balay static PetscErrorCode MatLMVMSolveShell(PC pc, Vec xin, Vec xout); 55*a7e14dcfSSatish Balay 56*a7e14dcfSSatish Balay /* 57*a7e14dcfSSatish Balay TaoSolve_NTR - Implements Newton's Method with a trust region approach 58*a7e14dcfSSatish Balay for solving unconstrained minimization problems. 59*a7e14dcfSSatish Balay 60*a7e14dcfSSatish Balay The basic algorithm is taken from MINPACK-2 (dstrn). 61*a7e14dcfSSatish Balay 62*a7e14dcfSSatish Balay TaoSolve_NTR computes a local minimizer of a twice differentiable function 63*a7e14dcfSSatish Balay f by applying a trust region variant of Newton's method. At each stage 64*a7e14dcfSSatish Balay of the algorithm, we use the prconditioned conjugate gradient method to 65*a7e14dcfSSatish Balay determine an approximate minimizer of the quadratic equation 66*a7e14dcfSSatish Balay 67*a7e14dcfSSatish Balay q(s) = <s, Hs + g> 68*a7e14dcfSSatish Balay 69*a7e14dcfSSatish Balay subject to the trust region constraint 70*a7e14dcfSSatish Balay 71*a7e14dcfSSatish Balay || s ||_M <= radius, 72*a7e14dcfSSatish Balay 73*a7e14dcfSSatish Balay where radius is the trust region radius and M is a symmetric positive 74*a7e14dcfSSatish Balay definite matrix (the preconditioner). Here g is the gradient and H 75*a7e14dcfSSatish Balay is the Hessian matrix. 76*a7e14dcfSSatish Balay 77*a7e14dcfSSatish Balay Note: TaoSolve_NTR MUST use the iterative solver KSPNASH, KSPSTCG, 78*a7e14dcfSSatish Balay or KSPGLTR. Thus, we set KSPNASH, KSPSTCG, or KSPGLTR in this 79*a7e14dcfSSatish Balay routine regardless of what the user may have previously specified. 80*a7e14dcfSSatish Balay */ 81*a7e14dcfSSatish Balay #undef __FUNCT__ 82*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSolve_NTR" 83*a7e14dcfSSatish Balay static PetscErrorCode TaoSolve_NTR(TaoSolver tao) 84*a7e14dcfSSatish Balay { 85*a7e14dcfSSatish Balay TAO_NTR *tr = (TAO_NTR *)tao->data; 86*a7e14dcfSSatish Balay 87*a7e14dcfSSatish Balay PC pc; 88*a7e14dcfSSatish Balay 89*a7e14dcfSSatish Balay KSPConvergedReason ksp_reason; 90*a7e14dcfSSatish Balay TaoSolverTerminationReason reason; 91*a7e14dcfSSatish Balay 92*a7e14dcfSSatish Balay MatStructure matflag; 93*a7e14dcfSSatish Balay 94*a7e14dcfSSatish Balay PetscReal fmin, ftrial, prered, actred, kappa, sigma, beta; 95*a7e14dcfSSatish Balay PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius; 96*a7e14dcfSSatish Balay PetscReal f, gnorm; 97*a7e14dcfSSatish Balay 98*a7e14dcfSSatish Balay PetscReal delta; 99*a7e14dcfSSatish Balay PetscReal norm_d; 100*a7e14dcfSSatish Balay PetscErrorCode ierr; 101*a7e14dcfSSatish Balay 102*a7e14dcfSSatish Balay PetscInt iter = 0; 103*a7e14dcfSSatish Balay PetscInt bfgsUpdates = 0; 104*a7e14dcfSSatish Balay PetscInt needH; 105*a7e14dcfSSatish Balay 106*a7e14dcfSSatish Balay PetscInt i_max = 5; 107*a7e14dcfSSatish Balay PetscInt j_max = 1; 108*a7e14dcfSSatish Balay PetscInt i, j, N, n, its; 109*a7e14dcfSSatish Balay 110*a7e14dcfSSatish Balay PetscFunctionBegin; 111*a7e14dcfSSatish Balay 112*a7e14dcfSSatish Balay if (tao->XL || tao->XU || tao->ops->computebounds) { 113*a7e14dcfSSatish Balay ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by ntr algorithm\n"); CHKERRQ(ierr); 114*a7e14dcfSSatish Balay } 115*a7e14dcfSSatish Balay 116*a7e14dcfSSatish Balay tao->trust = tao->trust0; 117*a7e14dcfSSatish Balay 118*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 119*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tr->min_radius); 120*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, tr->max_radius); 121*a7e14dcfSSatish Balay 122*a7e14dcfSSatish Balay 123*a7e14dcfSSatish Balay if (NTR_PC_BFGS == tr->pc_type && !tr->M) { 124*a7e14dcfSSatish Balay ierr = VecGetLocalSize(tao->solution,&n); CHKERRQ(ierr); 125*a7e14dcfSSatish Balay ierr = VecGetSize(tao->solution,&N); CHKERRQ(ierr); 126*a7e14dcfSSatish Balay ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&tr->M); CHKERRQ(ierr); 127*a7e14dcfSSatish Balay ierr = MatLMVMAllocateVectors(tr->M,tao->solution); CHKERRQ(ierr); 128*a7e14dcfSSatish Balay } 129*a7e14dcfSSatish Balay 130*a7e14dcfSSatish Balay /* Check convergence criteria */ 131*a7e14dcfSSatish Balay ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient); CHKERRQ(ierr); 132*a7e14dcfSSatish Balay ierr = VecNorm(tao->gradient,NORM_2,&gnorm); CHKERRQ(ierr); 133*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) { 134*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 135*a7e14dcfSSatish Balay } 136*a7e14dcfSSatish Balay needH = 1; 137*a7e14dcfSSatish Balay 138*a7e14dcfSSatish Balay ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason); CHKERRQ(ierr); 139*a7e14dcfSSatish Balay if (reason != TAO_CONTINUE_ITERATING) { 140*a7e14dcfSSatish Balay PetscFunctionReturn(0); 141*a7e14dcfSSatish Balay } 142*a7e14dcfSSatish Balay 143*a7e14dcfSSatish Balay /* Create vectors for the limited memory preconditioner */ 144*a7e14dcfSSatish Balay if ((NTR_PC_BFGS == tr->pc_type) && 145*a7e14dcfSSatish Balay (BFGS_SCALE_BFGS != tr->bfgs_scale_type)) { 146*a7e14dcfSSatish Balay if (!tr->Diag) { 147*a7e14dcfSSatish Balay ierr = VecDuplicate(tao->solution, &tr->Diag); CHKERRQ(ierr); 148*a7e14dcfSSatish Balay } 149*a7e14dcfSSatish Balay } 150*a7e14dcfSSatish Balay 151*a7e14dcfSSatish Balay switch(tr->ksp_type) { 152*a7e14dcfSSatish Balay case NTR_KSP_NASH: 153*a7e14dcfSSatish Balay ierr = KSPSetType(tao->ksp, KSPNASH); CHKERRQ(ierr); 154*a7e14dcfSSatish Balay if (tao->ksp->ops->setfromoptions) { 155*a7e14dcfSSatish Balay (*tao->ksp->ops->setfromoptions)(tao->ksp); 156*a7e14dcfSSatish Balay } 157*a7e14dcfSSatish Balay break; 158*a7e14dcfSSatish Balay 159*a7e14dcfSSatish Balay case NTR_KSP_STCG: 160*a7e14dcfSSatish Balay ierr = KSPSetType(tao->ksp, KSPSTCG); CHKERRQ(ierr); 161*a7e14dcfSSatish Balay if (tao->ksp->ops->setfromoptions) { 162*a7e14dcfSSatish Balay (*tao->ksp->ops->setfromoptions)(tao->ksp); 163*a7e14dcfSSatish Balay } 164*a7e14dcfSSatish Balay break; 165*a7e14dcfSSatish Balay 166*a7e14dcfSSatish Balay default: 167*a7e14dcfSSatish Balay ierr = KSPSetType(tao->ksp, KSPGLTR); CHKERRQ(ierr); 168*a7e14dcfSSatish Balay if (tao->ksp->ops->setfromoptions) { 169*a7e14dcfSSatish Balay (*tao->ksp->ops->setfromoptions)(tao->ksp); 170*a7e14dcfSSatish Balay } 171*a7e14dcfSSatish Balay break; 172*a7e14dcfSSatish Balay } 173*a7e14dcfSSatish Balay 174*a7e14dcfSSatish Balay /* Modify the preconditioner to use the bfgs approximation */ 175*a7e14dcfSSatish Balay ierr = KSPGetPC(tao->ksp, &pc); CHKERRQ(ierr); 176*a7e14dcfSSatish Balay switch(tr->pc_type) { 177*a7e14dcfSSatish Balay case NTR_PC_NONE: 178*a7e14dcfSSatish Balay ierr = PCSetType(pc, PCNONE); CHKERRQ(ierr); 179*a7e14dcfSSatish Balay if (pc->ops->setfromoptions) { 180*a7e14dcfSSatish Balay (*pc->ops->setfromoptions)(pc); 181*a7e14dcfSSatish Balay } 182*a7e14dcfSSatish Balay break; 183*a7e14dcfSSatish Balay 184*a7e14dcfSSatish Balay case NTR_PC_AHESS: 185*a7e14dcfSSatish Balay ierr = PCSetType(pc, PCJACOBI); CHKERRQ(ierr); 186*a7e14dcfSSatish Balay if (pc->ops->setfromoptions) { 187*a7e14dcfSSatish Balay (*pc->ops->setfromoptions)(pc); 188*a7e14dcfSSatish Balay } 189*a7e14dcfSSatish Balay ierr = PCJacobiSetUseAbs(pc); CHKERRQ(ierr); 190*a7e14dcfSSatish Balay break; 191*a7e14dcfSSatish Balay 192*a7e14dcfSSatish Balay case NTR_PC_BFGS: 193*a7e14dcfSSatish Balay ierr = PCSetType(pc, PCSHELL); CHKERRQ(ierr); 194*a7e14dcfSSatish Balay if (pc->ops->setfromoptions) { 195*a7e14dcfSSatish Balay (*pc->ops->setfromoptions)(pc); 196*a7e14dcfSSatish Balay } 197*a7e14dcfSSatish Balay ierr = PCShellSetName(pc, "bfgs"); CHKERRQ(ierr); 198*a7e14dcfSSatish Balay ierr = PCShellSetContext(pc, tr->M); CHKERRQ(ierr); 199*a7e14dcfSSatish Balay ierr = PCShellSetApply(pc, MatLMVMSolveShell); CHKERRQ(ierr); 200*a7e14dcfSSatish Balay break; 201*a7e14dcfSSatish Balay 202*a7e14dcfSSatish Balay default: 203*a7e14dcfSSatish Balay /* Use the pc method set by pc_type */ 204*a7e14dcfSSatish Balay break; 205*a7e14dcfSSatish Balay } 206*a7e14dcfSSatish Balay 207*a7e14dcfSSatish Balay /* Initialize trust-region radius */ 208*a7e14dcfSSatish Balay switch(tr->init_type) { 209*a7e14dcfSSatish Balay case NTR_INIT_CONSTANT: 210*a7e14dcfSSatish Balay /* Use the initial radius specified */ 211*a7e14dcfSSatish Balay break; 212*a7e14dcfSSatish Balay 213*a7e14dcfSSatish Balay case NTR_INIT_INTERPOLATION: 214*a7e14dcfSSatish Balay /* Use the initial radius specified */ 215*a7e14dcfSSatish Balay max_radius = 0.0; 216*a7e14dcfSSatish Balay 217*a7e14dcfSSatish Balay for (j = 0; j < j_max; ++j) { 218*a7e14dcfSSatish Balay fmin = f; 219*a7e14dcfSSatish Balay sigma = 0.0; 220*a7e14dcfSSatish Balay 221*a7e14dcfSSatish Balay if (needH) { 222*a7e14dcfSSatish Balay ierr = TaoComputeHessian(tao, tao->solution, &tao->hessian, &tao->hessian_pre, &matflag); CHKERRQ(ierr); 223*a7e14dcfSSatish Balay needH = 0; 224*a7e14dcfSSatish Balay } 225*a7e14dcfSSatish Balay 226*a7e14dcfSSatish Balay for (i = 0; i < i_max; ++i) { 227*a7e14dcfSSatish Balay 228*a7e14dcfSSatish Balay ierr = VecCopy(tao->solution, tr->W); CHKERRQ(ierr); 229*a7e14dcfSSatish Balay ierr = VecAXPY(tr->W, -tao->trust/gnorm, tao->gradient); CHKERRQ(ierr); 230*a7e14dcfSSatish Balay ierr = TaoComputeObjective(tao, tr->W, &ftrial); CHKERRQ(ierr); 231*a7e14dcfSSatish Balay 232*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(ftrial)) { 233*a7e14dcfSSatish Balay tau = tr->gamma1_i; 234*a7e14dcfSSatish Balay } 235*a7e14dcfSSatish Balay else { 236*a7e14dcfSSatish Balay if (ftrial < fmin) { 237*a7e14dcfSSatish Balay fmin = ftrial; 238*a7e14dcfSSatish Balay sigma = -tao->trust / gnorm; 239*a7e14dcfSSatish Balay } 240*a7e14dcfSSatish Balay 241*a7e14dcfSSatish Balay ierr = MatMult(tao->hessian, tao->gradient, tao->stepdirection); CHKERRQ(ierr); 242*a7e14dcfSSatish Balay ierr = VecDot(tao->gradient, tao->stepdirection, &prered); CHKERRQ(ierr); 243*a7e14dcfSSatish Balay 244*a7e14dcfSSatish Balay prered = tao->trust * (gnorm - 0.5 * tao->trust * prered / (gnorm * gnorm)); 245*a7e14dcfSSatish Balay actred = f - ftrial; 246*a7e14dcfSSatish Balay if ((PetscAbsScalar(actred) <= tr->epsilon) && 247*a7e14dcfSSatish Balay (PetscAbsScalar(prered) <= tr->epsilon)) { 248*a7e14dcfSSatish Balay kappa = 1.0; 249*a7e14dcfSSatish Balay } 250*a7e14dcfSSatish Balay else { 251*a7e14dcfSSatish Balay kappa = actred / prered; 252*a7e14dcfSSatish Balay } 253*a7e14dcfSSatish Balay 254*a7e14dcfSSatish Balay tau_1 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust + (1.0 - tr->theta_i) * prered - actred); 255*a7e14dcfSSatish Balay tau_2 = tr->theta_i * gnorm * tao->trust / (tr->theta_i * gnorm * tao->trust - (1.0 + tr->theta_i) * prered + actred); 256*a7e14dcfSSatish Balay tau_min = PetscMin(tau_1, tau_2); 257*a7e14dcfSSatish Balay tau_max = PetscMax(tau_1, tau_2); 258*a7e14dcfSSatish Balay 259*a7e14dcfSSatish Balay if (PetscAbsScalar(kappa - 1.0) <= tr->mu1_i) { 260*a7e14dcfSSatish Balay /* Great agreement */ 261*a7e14dcfSSatish Balay max_radius = PetscMax(max_radius, tao->trust); 262*a7e14dcfSSatish Balay 263*a7e14dcfSSatish Balay if (tau_max < 1.0) { 264*a7e14dcfSSatish Balay tau = tr->gamma3_i; 265*a7e14dcfSSatish Balay } 266*a7e14dcfSSatish Balay else if (tau_max > tr->gamma4_i) { 267*a7e14dcfSSatish Balay tau = tr->gamma4_i; 268*a7e14dcfSSatish Balay } 269*a7e14dcfSSatish Balay else { 270*a7e14dcfSSatish Balay tau = tau_max; 271*a7e14dcfSSatish Balay } 272*a7e14dcfSSatish Balay } 273*a7e14dcfSSatish Balay else if (PetscAbsScalar(kappa - 1.0) <= tr->mu2_i) { 274*a7e14dcfSSatish Balay /* Good agreement */ 275*a7e14dcfSSatish Balay max_radius = PetscMax(max_radius, tao->trust); 276*a7e14dcfSSatish Balay 277*a7e14dcfSSatish Balay if (tau_max < tr->gamma2_i) { 278*a7e14dcfSSatish Balay tau = tr->gamma2_i; 279*a7e14dcfSSatish Balay } 280*a7e14dcfSSatish Balay else if (tau_max > tr->gamma3_i) { 281*a7e14dcfSSatish Balay tau = tr->gamma3_i; 282*a7e14dcfSSatish Balay } 283*a7e14dcfSSatish Balay else { 284*a7e14dcfSSatish Balay tau = tau_max; 285*a7e14dcfSSatish Balay } 286*a7e14dcfSSatish Balay } 287*a7e14dcfSSatish Balay else { 288*a7e14dcfSSatish Balay /* Not good agreement */ 289*a7e14dcfSSatish Balay if (tau_min > 1.0) { 290*a7e14dcfSSatish Balay tau = tr->gamma2_i; 291*a7e14dcfSSatish Balay } 292*a7e14dcfSSatish Balay else if (tau_max < tr->gamma1_i) { 293*a7e14dcfSSatish Balay tau = tr->gamma1_i; 294*a7e14dcfSSatish Balay } 295*a7e14dcfSSatish Balay else if ((tau_min < tr->gamma1_i) && (tau_max >= 1.0)) { 296*a7e14dcfSSatish Balay tau = tr->gamma1_i; 297*a7e14dcfSSatish Balay } 298*a7e14dcfSSatish Balay else if ((tau_1 >= tr->gamma1_i) && (tau_1 < 1.0) && 299*a7e14dcfSSatish Balay ((tau_2 < tr->gamma1_i) || (tau_2 >= 1.0))) { 300*a7e14dcfSSatish Balay tau = tau_1; 301*a7e14dcfSSatish Balay } 302*a7e14dcfSSatish Balay else if ((tau_2 >= tr->gamma1_i) && (tau_2 < 1.0) && 303*a7e14dcfSSatish Balay ((tau_1 < tr->gamma1_i) || (tau_2 >= 1.0))) { 304*a7e14dcfSSatish Balay tau = tau_2; 305*a7e14dcfSSatish Balay } 306*a7e14dcfSSatish Balay else { 307*a7e14dcfSSatish Balay tau = tau_max; 308*a7e14dcfSSatish Balay } 309*a7e14dcfSSatish Balay } 310*a7e14dcfSSatish Balay } 311*a7e14dcfSSatish Balay tao->trust = tau * tao->trust; 312*a7e14dcfSSatish Balay } 313*a7e14dcfSSatish Balay 314*a7e14dcfSSatish Balay if (fmin < f) { 315*a7e14dcfSSatish Balay f = fmin; 316*a7e14dcfSSatish Balay ierr = VecAXPY(tao->solution, sigma, tao->gradient); CHKERRQ(ierr); 317*a7e14dcfSSatish Balay ierr = TaoComputeGradient(tao,tao->solution, tao->gradient); CHKERRQ(ierr); 318*a7e14dcfSSatish Balay 319*a7e14dcfSSatish Balay ierr = VecNorm(tao->gradient, NORM_2, &gnorm); CHKERRQ(ierr); 320*a7e14dcfSSatish Balay 321*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) { 322*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 323*a7e14dcfSSatish Balay } 324*a7e14dcfSSatish Balay needH = 1; 325*a7e14dcfSSatish Balay 326*a7e14dcfSSatish Balay ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason); CHKERRQ(ierr); 327*a7e14dcfSSatish Balay if (reason != TAO_CONTINUE_ITERATING) { 328*a7e14dcfSSatish Balay PetscFunctionReturn(0); 329*a7e14dcfSSatish Balay } 330*a7e14dcfSSatish Balay } 331*a7e14dcfSSatish Balay } 332*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, max_radius); 333*a7e14dcfSSatish Balay 334*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 335*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tr->min_radius); 336*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, tr->max_radius); 337*a7e14dcfSSatish Balay break; 338*a7e14dcfSSatish Balay 339*a7e14dcfSSatish Balay default: 340*a7e14dcfSSatish Balay /* Norm of the first direction will initialize radius */ 341*a7e14dcfSSatish Balay tao->trust = 0.0; 342*a7e14dcfSSatish Balay break; 343*a7e14dcfSSatish Balay } 344*a7e14dcfSSatish Balay 345*a7e14dcfSSatish Balay /* Set initial scaling for the BFGS preconditioner 346*a7e14dcfSSatish Balay This step is done after computing the initial trust-region radius 347*a7e14dcfSSatish Balay since the function value may have decreased */ 348*a7e14dcfSSatish Balay if (NTR_PC_BFGS == tr->pc_type) { 349*a7e14dcfSSatish Balay if (f != 0.0) { 350*a7e14dcfSSatish Balay delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 351*a7e14dcfSSatish Balay } 352*a7e14dcfSSatish Balay else { 353*a7e14dcfSSatish Balay delta = 2.0 / (gnorm*gnorm); 354*a7e14dcfSSatish Balay } 355*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(tr->M,delta); CHKERRQ(ierr); 356*a7e14dcfSSatish Balay } 357*a7e14dcfSSatish Balay 358*a7e14dcfSSatish Balay /* Have not converged; continue with Newton method */ 359*a7e14dcfSSatish Balay while (reason == TAO_CONTINUE_ITERATING) { 360*a7e14dcfSSatish Balay ++iter; 361*a7e14dcfSSatish Balay 362*a7e14dcfSSatish Balay /* Compute the Hessian */ 363*a7e14dcfSSatish Balay if (needH) { 364*a7e14dcfSSatish Balay ierr = TaoComputeHessian(tao, tao->solution, &tao->hessian, &tao->hessian_pre, &matflag); CHKERRQ(ierr); 365*a7e14dcfSSatish Balay needH = 0; 366*a7e14dcfSSatish Balay } 367*a7e14dcfSSatish Balay 368*a7e14dcfSSatish Balay if (NTR_PC_BFGS == tr->pc_type) { 369*a7e14dcfSSatish Balay if (BFGS_SCALE_AHESS == tr->bfgs_scale_type) { 370*a7e14dcfSSatish Balay /* Obtain diagonal for the bfgs preconditioner */ 371*a7e14dcfSSatish Balay ierr = MatGetDiagonal(tao->hessian, tr->Diag); CHKERRQ(ierr); 372*a7e14dcfSSatish Balay ierr = VecAbs(tr->Diag); CHKERRQ(ierr); 373*a7e14dcfSSatish Balay ierr = VecReciprocal(tr->Diag); CHKERRQ(ierr); 374*a7e14dcfSSatish Balay ierr = MatLMVMSetScale(tr->M,tr->Diag); CHKERRQ(ierr); 375*a7e14dcfSSatish Balay } 376*a7e14dcfSSatish Balay 377*a7e14dcfSSatish Balay /* Update the limited memory preconditioner */ 378*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient); CHKERRQ(ierr); 379*a7e14dcfSSatish Balay ++bfgsUpdates; 380*a7e14dcfSSatish Balay } 381*a7e14dcfSSatish Balay 382*a7e14dcfSSatish Balay while (reason == TAO_CONTINUE_ITERATING) { 383*a7e14dcfSSatish Balay ierr = KSPSetOperators(tao->ksp, tao->hessian, tao->hessian_pre, matflag); CHKERRQ(ierr); 384*a7e14dcfSSatish Balay 385*a7e14dcfSSatish Balay /* Solve the trust region subproblem */ 386*a7e14dcfSSatish Balay if (NTR_KSP_NASH == tr->ksp_type) { 387*a7e14dcfSSatish Balay ierr = KSPNASHSetRadius(tao->ksp,tao->trust); CHKERRQ(ierr); 388*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection); CHKERRQ(ierr); 389*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&its); CHKERRQ(ierr); 390*a7e14dcfSSatish Balay tao->ksp_its+=its; 391*a7e14dcfSSatish Balay ierr = KSPNASHGetNormD(tao->ksp, &norm_d); CHKERRQ(ierr); 392*a7e14dcfSSatish Balay } else if (NTR_KSP_STCG == tr->ksp_type) { 393*a7e14dcfSSatish Balay ierr = KSPSTCGSetRadius(tao->ksp,tao->trust); CHKERRQ(ierr); 394*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection); CHKERRQ(ierr); 395*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&its); CHKERRQ(ierr); 396*a7e14dcfSSatish Balay tao->ksp_its+=its; 397*a7e14dcfSSatish Balay ierr = KSPSTCGGetNormD(tao->ksp, &norm_d); CHKERRQ(ierr); 398*a7e14dcfSSatish Balay } else { /* NTR_KSP_GLTR */ 399*a7e14dcfSSatish Balay ierr = KSPGLTRSetRadius(tao->ksp,tao->trust); CHKERRQ(ierr); 400*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection); CHKERRQ(ierr); 401*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&its); CHKERRQ(ierr); 402*a7e14dcfSSatish Balay tao->ksp_its+=its; 403*a7e14dcfSSatish Balay ierr = KSPGLTRGetNormD(tao->ksp, &norm_d); CHKERRQ(ierr); 404*a7e14dcfSSatish Balay } 405*a7e14dcfSSatish Balay 406*a7e14dcfSSatish Balay if (0.0 == tao->trust) { 407*a7e14dcfSSatish Balay /* Radius was uninitialized; use the norm of the direction */ 408*a7e14dcfSSatish Balay if (norm_d > 0.0) { 409*a7e14dcfSSatish Balay tao->trust = norm_d; 410*a7e14dcfSSatish Balay 411*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 412*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tr->min_radius); 413*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, tr->max_radius); 414*a7e14dcfSSatish Balay } 415*a7e14dcfSSatish Balay else { 416*a7e14dcfSSatish Balay /* The direction was bad; set radius to default value and re-solve 417*a7e14dcfSSatish Balay the trust-region subproblem to get a direction */ 418*a7e14dcfSSatish Balay tao->trust = tao->trust0; 419*a7e14dcfSSatish Balay 420*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 421*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tr->min_radius); 422*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, tr->max_radius); 423*a7e14dcfSSatish Balay 424*a7e14dcfSSatish Balay if (NTR_KSP_NASH == tr->ksp_type) { 425*a7e14dcfSSatish Balay ierr = KSPNASHSetRadius(tao->ksp,tao->trust); CHKERRQ(ierr); 426*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection); CHKERRQ(ierr); 427*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&its); CHKERRQ(ierr); 428*a7e14dcfSSatish Balay tao->ksp_its+=its; 429*a7e14dcfSSatish Balay ierr = KSPNASHGetNormD(tao->ksp, &norm_d); CHKERRQ(ierr); 430*a7e14dcfSSatish Balay } else if (NTR_KSP_STCG == tr->ksp_type) { 431*a7e14dcfSSatish Balay ierr = KSPSTCGSetRadius(tao->ksp,tao->trust); CHKERRQ(ierr); 432*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection); CHKERRQ(ierr); 433*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&its); CHKERRQ(ierr); 434*a7e14dcfSSatish Balay tao->ksp_its+=its; 435*a7e14dcfSSatish Balay ierr = KSPSTCGGetNormD(tao->ksp, &norm_d); CHKERRQ(ierr); 436*a7e14dcfSSatish Balay } else { /* NTR_KSP_GLTR */ 437*a7e14dcfSSatish Balay ierr = KSPGLTRSetRadius(tao->ksp,tao->trust); CHKERRQ(ierr); 438*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, tao->stepdirection); CHKERRQ(ierr); 439*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&its); CHKERRQ(ierr); 440*a7e14dcfSSatish Balay tao->ksp_its+=its; 441*a7e14dcfSSatish Balay ierr = KSPGLTRGetNormD(tao->ksp, &norm_d); CHKERRQ(ierr); 442*a7e14dcfSSatish Balay } 443*a7e14dcfSSatish Balay 444*a7e14dcfSSatish Balay if (norm_d == 0.0) { 445*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero"); 446*a7e14dcfSSatish Balay } 447*a7e14dcfSSatish Balay } 448*a7e14dcfSSatish Balay } 449*a7e14dcfSSatish Balay ierr = VecScale(tao->stepdirection, -1.0); CHKERRQ(ierr); 450*a7e14dcfSSatish Balay ierr = KSPGetConvergedReason(tao->ksp, &ksp_reason); CHKERRQ(ierr); 451*a7e14dcfSSatish Balay if ((KSP_DIVERGED_INDEFINITE_PC == ksp_reason) && 452*a7e14dcfSSatish Balay (NTR_PC_BFGS == tr->pc_type) && (bfgsUpdates > 1)) { 453*a7e14dcfSSatish Balay /* Preconditioner is numerically indefinite; reset the 454*a7e14dcfSSatish Balay approximate if using BFGS preconditioning. */ 455*a7e14dcfSSatish Balay 456*a7e14dcfSSatish Balay if (f != 0.0) { 457*a7e14dcfSSatish Balay delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 458*a7e14dcfSSatish Balay } 459*a7e14dcfSSatish Balay else { 460*a7e14dcfSSatish Balay delta = 2.0 / (gnorm*gnorm); 461*a7e14dcfSSatish Balay } 462*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(tr->M, delta); CHKERRQ(ierr); 463*a7e14dcfSSatish Balay ierr = MatLMVMReset(tr->M); CHKERRQ(ierr); 464*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(tr->M, tao->solution, tao->gradient); CHKERRQ(ierr); 465*a7e14dcfSSatish Balay bfgsUpdates = 1; 466*a7e14dcfSSatish Balay } 467*a7e14dcfSSatish Balay 468*a7e14dcfSSatish Balay if (NTR_UPDATE_REDUCTION == tr->update_type) { 469*a7e14dcfSSatish Balay /* Get predicted reduction */ 470*a7e14dcfSSatish Balay if (NTR_KSP_NASH == tr->ksp_type) { 471*a7e14dcfSSatish Balay ierr = KSPNASHGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 472*a7e14dcfSSatish Balay } else if (NTR_KSP_STCG == tr->ksp_type) { 473*a7e14dcfSSatish Balay ierr = KSPSTCGGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 474*a7e14dcfSSatish Balay } else { /* gltr */ 475*a7e14dcfSSatish Balay ierr = KSPGLTRGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 476*a7e14dcfSSatish Balay } 477*a7e14dcfSSatish Balay 478*a7e14dcfSSatish Balay if (prered >= 0.0) { 479*a7e14dcfSSatish Balay /* The predicted reduction has the wrong sign. This cannot 480*a7e14dcfSSatish Balay happen in infinite precision arithmetic. Step should 481*a7e14dcfSSatish Balay be rejected! */ 482*a7e14dcfSSatish Balay tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); 483*a7e14dcfSSatish Balay } 484*a7e14dcfSSatish Balay else { 485*a7e14dcfSSatish Balay /* Compute trial step and function value */ 486*a7e14dcfSSatish Balay ierr = VecCopy(tao->solution,tr->W); CHKERRQ(ierr); 487*a7e14dcfSSatish Balay ierr = VecAXPY(tr->W, 1.0, tao->stepdirection); CHKERRQ(ierr); 488*a7e14dcfSSatish Balay ierr = TaoComputeObjective(tao, tr->W, &ftrial); CHKERRQ(ierr); 489*a7e14dcfSSatish Balay 490*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(ftrial)) { 491*a7e14dcfSSatish Balay tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); 492*a7e14dcfSSatish Balay } else { 493*a7e14dcfSSatish Balay /* Compute and actual reduction */ 494*a7e14dcfSSatish Balay actred = f - ftrial; 495*a7e14dcfSSatish Balay prered = -prered; 496*a7e14dcfSSatish Balay if ((PetscAbsScalar(actred) <= tr->epsilon) && 497*a7e14dcfSSatish Balay (PetscAbsScalar(prered) <= tr->epsilon)) { 498*a7e14dcfSSatish Balay kappa = 1.0; 499*a7e14dcfSSatish Balay } 500*a7e14dcfSSatish Balay else { 501*a7e14dcfSSatish Balay kappa = actred / prered; 502*a7e14dcfSSatish Balay } 503*a7e14dcfSSatish Balay 504*a7e14dcfSSatish Balay /* Accept or reject the step and update radius */ 505*a7e14dcfSSatish Balay if (kappa < tr->eta1) { 506*a7e14dcfSSatish Balay /* Reject the step */ 507*a7e14dcfSSatish Balay tao->trust = tr->alpha1 * PetscMin(tao->trust, norm_d); 508*a7e14dcfSSatish Balay } 509*a7e14dcfSSatish Balay else { 510*a7e14dcfSSatish Balay /* Accept the step */ 511*a7e14dcfSSatish Balay if (kappa < tr->eta2) { 512*a7e14dcfSSatish Balay /* Marginal bad step */ 513*a7e14dcfSSatish Balay tao->trust = tr->alpha2 * PetscMin(tao->trust, norm_d); 514*a7e14dcfSSatish Balay } 515*a7e14dcfSSatish Balay else if (kappa < tr->eta3) { 516*a7e14dcfSSatish Balay /* Reasonable step */ 517*a7e14dcfSSatish Balay tao->trust = tr->alpha3 * tao->trust; 518*a7e14dcfSSatish Balay } 519*a7e14dcfSSatish Balay else if (kappa < tr->eta4) { 520*a7e14dcfSSatish Balay /* Good step */ 521*a7e14dcfSSatish Balay tao->trust = PetscMax(tr->alpha4 * norm_d, tao->trust); 522*a7e14dcfSSatish Balay } 523*a7e14dcfSSatish Balay else { 524*a7e14dcfSSatish Balay /* Very good step */ 525*a7e14dcfSSatish Balay tao->trust = PetscMax(tr->alpha5 * norm_d, tao->trust); 526*a7e14dcfSSatish Balay } 527*a7e14dcfSSatish Balay break; 528*a7e14dcfSSatish Balay } 529*a7e14dcfSSatish Balay } 530*a7e14dcfSSatish Balay } 531*a7e14dcfSSatish Balay } 532*a7e14dcfSSatish Balay else { 533*a7e14dcfSSatish Balay /* Get predicted reduction */ 534*a7e14dcfSSatish Balay if (NTR_KSP_NASH == tr->ksp_type) { 535*a7e14dcfSSatish Balay ierr = KSPNASHGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 536*a7e14dcfSSatish Balay } else if (NTR_KSP_STCG == tr->ksp_type) { 537*a7e14dcfSSatish Balay ierr = KSPSTCGGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 538*a7e14dcfSSatish Balay } else { /* gltr */ 539*a7e14dcfSSatish Balay ierr = KSPGLTRGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 540*a7e14dcfSSatish Balay } 541*a7e14dcfSSatish Balay 542*a7e14dcfSSatish Balay if (prered >= 0.0) { 543*a7e14dcfSSatish Balay /* The predicted reduction has the wrong sign. This cannot 544*a7e14dcfSSatish Balay happen in infinite precision arithmetic. Step should 545*a7e14dcfSSatish Balay be rejected! */ 546*a7e14dcfSSatish Balay tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 547*a7e14dcfSSatish Balay } 548*a7e14dcfSSatish Balay else { 549*a7e14dcfSSatish Balay ierr = VecCopy(tao->solution, tr->W); CHKERRQ(ierr); 550*a7e14dcfSSatish Balay ierr = VecAXPY(tr->W, 1.0, tao->stepdirection); CHKERRQ(ierr); 551*a7e14dcfSSatish Balay ierr = TaoComputeObjective(tao, tr->W, &ftrial); CHKERRQ(ierr); 552*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(ftrial)) { 553*a7e14dcfSSatish Balay tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 554*a7e14dcfSSatish Balay } 555*a7e14dcfSSatish Balay else { 556*a7e14dcfSSatish Balay ierr = VecDot(tao->gradient, tao->stepdirection, &beta); CHKERRQ(ierr); 557*a7e14dcfSSatish Balay actred = f - ftrial; 558*a7e14dcfSSatish Balay prered = -prered; 559*a7e14dcfSSatish Balay if ((PetscAbsScalar(actred) <= tr->epsilon) && 560*a7e14dcfSSatish Balay (PetscAbsScalar(prered) <= tr->epsilon)) { 561*a7e14dcfSSatish Balay kappa = 1.0; 562*a7e14dcfSSatish Balay } 563*a7e14dcfSSatish Balay else { 564*a7e14dcfSSatish Balay kappa = actred / prered; 565*a7e14dcfSSatish Balay } 566*a7e14dcfSSatish Balay 567*a7e14dcfSSatish Balay tau_1 = tr->theta * beta / (tr->theta * beta - (1.0 - tr->theta) * prered + actred); 568*a7e14dcfSSatish Balay tau_2 = tr->theta * beta / (tr->theta * beta + (1.0 + tr->theta) * prered - actred); 569*a7e14dcfSSatish Balay tau_min = PetscMin(tau_1, tau_2); 570*a7e14dcfSSatish Balay tau_max = PetscMax(tau_1, tau_2); 571*a7e14dcfSSatish Balay 572*a7e14dcfSSatish Balay if (kappa >= 1.0 - tr->mu1) { 573*a7e14dcfSSatish Balay /* Great agreement; accept step and update radius */ 574*a7e14dcfSSatish Balay if (tau_max < 1.0) { 575*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); 576*a7e14dcfSSatish Balay } 577*a7e14dcfSSatish Balay else if (tau_max > tr->gamma4) { 578*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tr->gamma4 * norm_d); 579*a7e14dcfSSatish Balay } 580*a7e14dcfSSatish Balay else { 581*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tau_max * norm_d); 582*a7e14dcfSSatish Balay } 583*a7e14dcfSSatish Balay break; 584*a7e14dcfSSatish Balay } 585*a7e14dcfSSatish Balay else if (kappa >= 1.0 - tr->mu2) { 586*a7e14dcfSSatish Balay /* Good agreement */ 587*a7e14dcfSSatish Balay 588*a7e14dcfSSatish Balay if (tau_max < tr->gamma2) { 589*a7e14dcfSSatish Balay tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); 590*a7e14dcfSSatish Balay } 591*a7e14dcfSSatish Balay else if (tau_max > tr->gamma3) { 592*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tr->gamma3 * norm_d); 593*a7e14dcfSSatish Balay } 594*a7e14dcfSSatish Balay else if (tau_max < 1.0) { 595*a7e14dcfSSatish Balay tao->trust = tau_max * PetscMin(tao->trust, norm_d); 596*a7e14dcfSSatish Balay } 597*a7e14dcfSSatish Balay else { 598*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tau_max * norm_d); 599*a7e14dcfSSatish Balay } 600*a7e14dcfSSatish Balay break; 601*a7e14dcfSSatish Balay } 602*a7e14dcfSSatish Balay else { 603*a7e14dcfSSatish Balay /* Not good agreement */ 604*a7e14dcfSSatish Balay if (tau_min > 1.0) { 605*a7e14dcfSSatish Balay tao->trust = tr->gamma2 * PetscMin(tao->trust, norm_d); 606*a7e14dcfSSatish Balay } 607*a7e14dcfSSatish Balay else if (tau_max < tr->gamma1) { 608*a7e14dcfSSatish Balay tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 609*a7e14dcfSSatish Balay } 610*a7e14dcfSSatish Balay else if ((tau_min < tr->gamma1) && (tau_max >= 1.0)) { 611*a7e14dcfSSatish Balay tao->trust = tr->gamma1 * PetscMin(tao->trust, norm_d); 612*a7e14dcfSSatish Balay } 613*a7e14dcfSSatish Balay else if ((tau_1 >= tr->gamma1) && (tau_1 < 1.0) && 614*a7e14dcfSSatish Balay ((tau_2 < tr->gamma1) || (tau_2 >= 1.0))) { 615*a7e14dcfSSatish Balay tao->trust = tau_1 * PetscMin(tao->trust, norm_d); 616*a7e14dcfSSatish Balay } 617*a7e14dcfSSatish Balay else if ((tau_2 >= tr->gamma1) && (tau_2 < 1.0) && 618*a7e14dcfSSatish Balay ((tau_1 < tr->gamma1) || (tau_2 >= 1.0))) { 619*a7e14dcfSSatish Balay tao->trust = tau_2 * PetscMin(tao->trust, norm_d); 620*a7e14dcfSSatish Balay } 621*a7e14dcfSSatish Balay else { 622*a7e14dcfSSatish Balay tao->trust = tau_max * PetscMin(tao->trust, norm_d); 623*a7e14dcfSSatish Balay } 624*a7e14dcfSSatish Balay } 625*a7e14dcfSSatish Balay } 626*a7e14dcfSSatish Balay } 627*a7e14dcfSSatish Balay } 628*a7e14dcfSSatish Balay 629*a7e14dcfSSatish Balay /* The step computed was not good and the radius was decreased. 630*a7e14dcfSSatish Balay Monitor the radius to terminate. */ 631*a7e14dcfSSatish Balay ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, tao->trust, &reason); CHKERRQ(ierr); 632*a7e14dcfSSatish Balay } 633*a7e14dcfSSatish Balay 634*a7e14dcfSSatish Balay /* The radius may have been increased; modify if it is too large */ 635*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, tr->max_radius); 636*a7e14dcfSSatish Balay 637*a7e14dcfSSatish Balay if (reason == TAO_CONTINUE_ITERATING) { 638*a7e14dcfSSatish Balay ierr = VecCopy(tr->W, tao->solution); CHKERRQ(ierr); 639*a7e14dcfSSatish Balay f = ftrial; 640*a7e14dcfSSatish Balay ierr = TaoComputeGradient(tao, tao->solution, tao->gradient); 641*a7e14dcfSSatish Balay ierr = VecNorm(tao->gradient, NORM_2, &gnorm); CHKERRQ(ierr); 642*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) { 643*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 644*a7e14dcfSSatish Balay } 645*a7e14dcfSSatish Balay needH = 1; 646*a7e14dcfSSatish Balay ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, tao->trust, &reason); CHKERRQ(ierr); 647*a7e14dcfSSatish Balay } 648*a7e14dcfSSatish Balay } 649*a7e14dcfSSatish Balay PetscFunctionReturn(0); 650*a7e14dcfSSatish Balay } 651*a7e14dcfSSatish Balay 652*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 653*a7e14dcfSSatish Balay #undef __FUNCT__ 654*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetUp_NTR" 655*a7e14dcfSSatish Balay static PetscErrorCode TaoSetUp_NTR(TaoSolver tao) 656*a7e14dcfSSatish Balay { 657*a7e14dcfSSatish Balay TAO_NTR *tr = (TAO_NTR *)tao->data; 658*a7e14dcfSSatish Balay PetscErrorCode ierr; 659*a7e14dcfSSatish Balay 660*a7e14dcfSSatish Balay PetscFunctionBegin; 661*a7e14dcfSSatish Balay 662*a7e14dcfSSatish Balay if (!tao->gradient) {ierr = VecDuplicate(tao->solution, &tao->gradient); CHKERRQ(ierr);} 663*a7e14dcfSSatish Balay if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution, &tao->stepdirection); CHKERRQ(ierr);} 664*a7e14dcfSSatish Balay if (!tr->W) {ierr = VecDuplicate(tao->solution, &tr->W); CHKERRQ(ierr);} 665*a7e14dcfSSatish Balay 666*a7e14dcfSSatish Balay tr->Diag = 0; 667*a7e14dcfSSatish Balay tr->M = 0; 668*a7e14dcfSSatish Balay 669*a7e14dcfSSatish Balay 670*a7e14dcfSSatish Balay PetscFunctionReturn(0); 671*a7e14dcfSSatish Balay } 672*a7e14dcfSSatish Balay 673*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 674*a7e14dcfSSatish Balay #undef __FUNCT__ 675*a7e14dcfSSatish Balay #define __FUNCT__ "TaoDestroy_NTR" 676*a7e14dcfSSatish Balay static PetscErrorCode TaoDestroy_NTR(TaoSolver tao) 677*a7e14dcfSSatish Balay { 678*a7e14dcfSSatish Balay TAO_NTR *tr = (TAO_NTR *)tao->data; 679*a7e14dcfSSatish Balay PetscErrorCode ierr; 680*a7e14dcfSSatish Balay 681*a7e14dcfSSatish Balay PetscFunctionBegin; 682*a7e14dcfSSatish Balay if (tao->setupcalled) { 683*a7e14dcfSSatish Balay ierr = VecDestroy(&tr->W); CHKERRQ(ierr); 684*a7e14dcfSSatish Balay } 685*a7e14dcfSSatish Balay if (tr->M) { 686*a7e14dcfSSatish Balay ierr = MatDestroy(&tr->M); CHKERRQ(ierr); 687*a7e14dcfSSatish Balay tr->M = PETSC_NULL; 688*a7e14dcfSSatish Balay } 689*a7e14dcfSSatish Balay if (tr->Diag) { 690*a7e14dcfSSatish Balay ierr = VecDestroy(&tr->Diag); CHKERRQ(ierr); 691*a7e14dcfSSatish Balay tr->Diag = PETSC_NULL; 692*a7e14dcfSSatish Balay } 693*a7e14dcfSSatish Balay ierr = PetscFree(tao->data); CHKERRQ(ierr); 694*a7e14dcfSSatish Balay tao->data = PETSC_NULL; 695*a7e14dcfSSatish Balay 696*a7e14dcfSSatish Balay PetscFunctionReturn(0); 697*a7e14dcfSSatish Balay } 698*a7e14dcfSSatish Balay 699*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 700*a7e14dcfSSatish Balay #undef __FUNCT__ 701*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetFromOptions_NTR" 702*a7e14dcfSSatish Balay static PetscErrorCode TaoSetFromOptions_NTR(TaoSolver tao) 703*a7e14dcfSSatish Balay { 704*a7e14dcfSSatish Balay TAO_NTR *tr = (TAO_NTR *)tao->data; 705*a7e14dcfSSatish Balay PetscErrorCode ierr; 706*a7e14dcfSSatish Balay 707*a7e14dcfSSatish Balay PetscFunctionBegin; 708*a7e14dcfSSatish Balay ierr = PetscOptionsHead("Newton trust region method for unconstrained optimization"); CHKERRQ(ierr); 709*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_ntr_ksp_type", "ksp type", "", NTR_KSP, NTR_KSP_TYPES, NTR_KSP[tr->ksp_type], &tr->ksp_type, 0); CHKERRQ(ierr); 710*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_ntr_pc_type", "pc type", "", NTR_PC, NTR_PC_TYPES, NTR_PC[tr->pc_type], &tr->pc_type, 0); CHKERRQ(ierr); 711*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_ntr_bfgs_scale_type", "bfgs scale type", "", BFGS_SCALE, BFGS_SCALE_TYPES, BFGS_SCALE[tr->bfgs_scale_type], &tr->bfgs_scale_type, 0); CHKERRQ(ierr); 712*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_ntr_init_type", "tao->trust initialization type", "", NTR_INIT, NTR_INIT_TYPES, NTR_INIT[tr->init_type], &tr->init_type, 0); CHKERRQ(ierr); 713*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_ntr_update_type", "radius update type", "", NTR_UPDATE, NTR_UPDATE_TYPES, NTR_UPDATE[tr->update_type], &tr->update_type, 0); CHKERRQ(ierr); 714*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_eta1", "step is unsuccessful if actual reduction < eta1 * predicted reduction", "", tr->eta1, &tr->eta1, 0); CHKERRQ(ierr); 715*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_eta2", "", "", tr->eta2, &tr->eta2, 0); CHKERRQ(ierr); 716*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_eta3", "", "", tr->eta3, &tr->eta3, 0); CHKERRQ(ierr); 717*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_eta4", "", "", tr->eta4, &tr->eta4, 0); CHKERRQ(ierr); 718*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_alpha1", "", "", tr->alpha1, &tr->alpha1, 0); CHKERRQ(ierr); 719*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_alpha2", "", "", tr->alpha2, &tr->alpha2, 0); CHKERRQ(ierr); 720*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_alpha3", "", "", tr->alpha3, &tr->alpha3, 0); CHKERRQ(ierr); 721*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_alpha4", "", "", tr->alpha4, &tr->alpha4, 0); CHKERRQ(ierr); 722*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_alpha5", "", "", tr->alpha5, &tr->alpha5, 0); CHKERRQ(ierr); 723*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_mu1", "", "", tr->mu1, &tr->mu1, 0); CHKERRQ(ierr); 724*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_mu2", "", "", tr->mu2, &tr->mu2, 0); CHKERRQ(ierr); 725*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma1", "", "", tr->gamma1, &tr->gamma1, 0); CHKERRQ(ierr); 726*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma2", "", "", tr->gamma2, &tr->gamma2, 0); CHKERRQ(ierr); 727*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma3", "", "", tr->gamma3, &tr->gamma3, 0); CHKERRQ(ierr); 728*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma4", "", "", tr->gamma4, &tr->gamma4, 0); CHKERRQ(ierr); 729*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_theta", "", "", tr->theta, &tr->theta, 0); CHKERRQ(ierr); 730*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_mu1_i", "", "", tr->mu1_i, &tr->mu1_i, 0); CHKERRQ(ierr); 731*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_mu2_i", "", "", tr->mu2_i, &tr->mu2_i, 0); CHKERRQ(ierr); 732*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma1_i", "", "", tr->gamma1_i, &tr->gamma1_i, 0); CHKERRQ(ierr); 733*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma2_i", "", "", tr->gamma2_i, &tr->gamma2_i, 0); CHKERRQ(ierr); 734*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma3_i", "", "", tr->gamma3_i, &tr->gamma3_i, 0); CHKERRQ(ierr); 735*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_gamma4_i", "", "", tr->gamma4_i, &tr->gamma4_i, 0); CHKERRQ(ierr); 736*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_theta_i", "", "", tr->theta_i, &tr->theta_i, 0); CHKERRQ(ierr); 737*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_min_radius", "lower bound on initial trust-region radius", "", tr->min_radius, &tr->min_radius, 0); CHKERRQ(ierr); 738*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_max_radius", "upper bound on trust-region radius", "", tr->max_radius, &tr->max_radius, 0); CHKERRQ(ierr); 739*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_ntr_epsilon", "tolerance used when computing actual and predicted reduction", "", tr->epsilon, &tr->epsilon, 0); CHKERRQ(ierr); 740*a7e14dcfSSatish Balay ierr = PetscOptionsTail(); CHKERRQ(ierr); 741*a7e14dcfSSatish Balay ierr = KSPSetFromOptions(tao->ksp); CHKERRQ(ierr); 742*a7e14dcfSSatish Balay PetscFunctionReturn(0); 743*a7e14dcfSSatish Balay } 744*a7e14dcfSSatish Balay 745*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 746*a7e14dcfSSatish Balay #undef __FUNCT__ 747*a7e14dcfSSatish Balay #define __FUNCT__ "TaoView_NTR" 748*a7e14dcfSSatish Balay static PetscErrorCode TaoView_NTR(TaoSolver tao, PetscViewer viewer) 749*a7e14dcfSSatish Balay { 750*a7e14dcfSSatish Balay TAO_NTR *tr = (TAO_NTR *)tao->data; 751*a7e14dcfSSatish Balay PetscErrorCode ierr; 752*a7e14dcfSSatish Balay PetscInt nrejects; 753*a7e14dcfSSatish Balay PetscBool isascii; 754*a7e14dcfSSatish Balay PetscFunctionBegin; 755*a7e14dcfSSatish Balay ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 756*a7e14dcfSSatish Balay if (isascii) { 757*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPushTab(viewer); CHKERRQ(ierr); 758*a7e14dcfSSatish Balay if (NTR_PC_BFGS == tr->pc_type && tr->M) { 759*a7e14dcfSSatish Balay ierr = MatLMVMGetRejects(tr->M, &nrejects); CHKERRQ(ierr); 760*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n", nrejects); CHKERRQ(ierr); 761*a7e14dcfSSatish Balay } 762*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPopTab(viewer); CHKERRQ(ierr); 763*a7e14dcfSSatish Balay 764*a7e14dcfSSatish Balay } else { 765*a7e14dcfSSatish Balay SETERRQ1(((PetscObject)tao)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for TAO NTR",((PetscObject)viewer)->type_name); 766*a7e14dcfSSatish Balay } 767*a7e14dcfSSatish Balay PetscFunctionReturn(0); 768*a7e14dcfSSatish Balay } 769*a7e14dcfSSatish Balay 770*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 771*a7e14dcfSSatish Balay EXTERN_C_BEGIN 772*a7e14dcfSSatish Balay #undef __FUNCT__ 773*a7e14dcfSSatish Balay #define __FUNCT__ "TaoCreate_NTR" 774*a7e14dcfSSatish Balay PetscErrorCode TaoCreate_NTR(TaoSolver tao) 775*a7e14dcfSSatish Balay { 776*a7e14dcfSSatish Balay TAO_NTR *tr; 777*a7e14dcfSSatish Balay PetscErrorCode ierr; 778*a7e14dcfSSatish Balay 779*a7e14dcfSSatish Balay PetscFunctionBegin; 780*a7e14dcfSSatish Balay 781*a7e14dcfSSatish Balay ierr = PetscNewLog(tao, TAO_NTR, &tr); CHKERRQ(ierr); 782*a7e14dcfSSatish Balay 783*a7e14dcfSSatish Balay tao->ops->setup = TaoSetUp_NTR; 784*a7e14dcfSSatish Balay tao->ops->solve = TaoSolve_NTR; 785*a7e14dcfSSatish Balay tao->ops->view = TaoView_NTR; 786*a7e14dcfSSatish Balay tao->ops->setfromoptions = TaoSetFromOptions_NTR; 787*a7e14dcfSSatish Balay tao->ops->destroy = TaoDestroy_NTR; 788*a7e14dcfSSatish Balay 789*a7e14dcfSSatish Balay tao->max_it = 50; 790*a7e14dcfSSatish Balay tao->fatol = 1e-10; 791*a7e14dcfSSatish Balay tao->frtol = 1e-10; 792*a7e14dcfSSatish Balay tao->data = (void*)tr; 793*a7e14dcfSSatish Balay 794*a7e14dcfSSatish Balay tao->trust0 = 100.0; 795*a7e14dcfSSatish Balay 796*a7e14dcfSSatish Balay /* Standard trust region update parameters */ 797*a7e14dcfSSatish Balay tr->eta1 = 1.0e-4; 798*a7e14dcfSSatish Balay tr->eta2 = 0.25; 799*a7e14dcfSSatish Balay tr->eta3 = 0.50; 800*a7e14dcfSSatish Balay tr->eta4 = 0.90; 801*a7e14dcfSSatish Balay 802*a7e14dcfSSatish Balay tr->alpha1 = 0.25; 803*a7e14dcfSSatish Balay tr->alpha2 = 0.50; 804*a7e14dcfSSatish Balay tr->alpha3 = 1.00; 805*a7e14dcfSSatish Balay tr->alpha4 = 2.00; 806*a7e14dcfSSatish Balay tr->alpha5 = 4.00; 807*a7e14dcfSSatish Balay 808*a7e14dcfSSatish Balay /* Interpolation parameters */ 809*a7e14dcfSSatish Balay tr->mu1_i = 0.35; 810*a7e14dcfSSatish Balay tr->mu2_i = 0.50; 811*a7e14dcfSSatish Balay 812*a7e14dcfSSatish Balay tr->gamma1_i = 0.0625; 813*a7e14dcfSSatish Balay tr->gamma2_i = 0.50; 814*a7e14dcfSSatish Balay tr->gamma3_i = 2.00; 815*a7e14dcfSSatish Balay tr->gamma4_i = 5.00; 816*a7e14dcfSSatish Balay 817*a7e14dcfSSatish Balay tr->theta_i = 0.25; 818*a7e14dcfSSatish Balay 819*a7e14dcfSSatish Balay /* Interpolation trust region update parameters */ 820*a7e14dcfSSatish Balay tr->mu1 = 0.10; 821*a7e14dcfSSatish Balay tr->mu2 = 0.50; 822*a7e14dcfSSatish Balay 823*a7e14dcfSSatish Balay tr->gamma1 = 0.25; 824*a7e14dcfSSatish Balay tr->gamma2 = 0.50; 825*a7e14dcfSSatish Balay tr->gamma3 = 2.00; 826*a7e14dcfSSatish Balay tr->gamma4 = 4.00; 827*a7e14dcfSSatish Balay 828*a7e14dcfSSatish Balay tr->theta = 0.05; 829*a7e14dcfSSatish Balay 830*a7e14dcfSSatish Balay tr->min_radius = 1.0e-10; 831*a7e14dcfSSatish Balay tr->max_radius = 1.0e10; 832*a7e14dcfSSatish Balay tr->epsilon = 1.0e-6; 833*a7e14dcfSSatish Balay 834*a7e14dcfSSatish Balay tr->ksp_type = NTR_KSP_STCG; 835*a7e14dcfSSatish Balay tr->pc_type = NTR_PC_BFGS; 836*a7e14dcfSSatish Balay tr->bfgs_scale_type = BFGS_SCALE_AHESS; 837*a7e14dcfSSatish Balay tr->init_type = NTR_INIT_INTERPOLATION; 838*a7e14dcfSSatish Balay tr->update_type = NTR_UPDATE_REDUCTION; 839*a7e14dcfSSatish Balay 840*a7e14dcfSSatish Balay 841*a7e14dcfSSatish Balay /* Set linear solver to default for trust region */ 842*a7e14dcfSSatish Balay ierr = KSPCreate(((PetscObject)tao)->comm, &tao->ksp); CHKERRQ(ierr); 843*a7e14dcfSSatish Balay 844*a7e14dcfSSatish Balay PetscFunctionReturn(0); 845*a7e14dcfSSatish Balay 846*a7e14dcfSSatish Balay 847*a7e14dcfSSatish Balay } 848*a7e14dcfSSatish Balay EXTERN_C_END 849*a7e14dcfSSatish Balay 850*a7e14dcfSSatish Balay 851*a7e14dcfSSatish Balay #undef __FUNCT__ 852*a7e14dcfSSatish Balay #define __FUNCT__ "MatLMVMSolveShell" 853*a7e14dcfSSatish Balay static PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x) 854*a7e14dcfSSatish Balay { 855*a7e14dcfSSatish Balay PetscErrorCode ierr; 856*a7e14dcfSSatish Balay Mat M; 857*a7e14dcfSSatish Balay PetscFunctionBegin; 858*a7e14dcfSSatish Balay PetscValidHeaderSpecific(pc,PC_CLASSID,1); 859*a7e14dcfSSatish Balay PetscValidHeaderSpecific(b,VEC_CLASSID,2); 860*a7e14dcfSSatish Balay PetscValidHeaderSpecific(x,VEC_CLASSID,3); 861*a7e14dcfSSatish Balay ierr = PCShellGetContext(pc,(void**)&M); CHKERRQ(ierr); 862*a7e14dcfSSatish Balay ierr = MatLMVMSolve(M, b, x); CHKERRQ(ierr); 863*a7e14dcfSSatish Balay PetscFunctionReturn(0); 864*a7e14dcfSSatish Balay } 865