1*a7e14dcfSSatish Balay #include "taolinesearch.h" 2*a7e14dcfSSatish Balay #include "src/matrix/lmvmmat.h" 3*a7e14dcfSSatish Balay #include "nls.h" 4*a7e14dcfSSatish Balay 5*a7e14dcfSSatish Balay #include "petscksp.h" 6*a7e14dcfSSatish Balay #include "petscpc.h" 7*a7e14dcfSSatish Balay #include "petsc-private/kspimpl.h" 8*a7e14dcfSSatish Balay #include "petsc-private/pcimpl.h" 9*a7e14dcfSSatish Balay 10*a7e14dcfSSatish Balay #define NLS_KSP_CG 0 11*a7e14dcfSSatish Balay #define NLS_KSP_NASH 1 12*a7e14dcfSSatish Balay #define NLS_KSP_STCG 2 13*a7e14dcfSSatish Balay #define NLS_KSP_GLTR 3 14*a7e14dcfSSatish Balay #define NLS_KSP_PETSC 4 15*a7e14dcfSSatish Balay #define NLS_KSP_TYPES 5 16*a7e14dcfSSatish Balay 17*a7e14dcfSSatish Balay #define NLS_PC_NONE 0 18*a7e14dcfSSatish Balay #define NLS_PC_AHESS 1 19*a7e14dcfSSatish Balay #define NLS_PC_BFGS 2 20*a7e14dcfSSatish Balay #define NLS_PC_PETSC 3 21*a7e14dcfSSatish Balay #define NLS_PC_TYPES 4 22*a7e14dcfSSatish Balay 23*a7e14dcfSSatish Balay #define BFGS_SCALE_AHESS 0 24*a7e14dcfSSatish Balay #define BFGS_SCALE_PHESS 1 25*a7e14dcfSSatish Balay #define BFGS_SCALE_BFGS 2 26*a7e14dcfSSatish Balay #define BFGS_SCALE_TYPES 3 27*a7e14dcfSSatish Balay 28*a7e14dcfSSatish Balay #define NLS_INIT_CONSTANT 0 29*a7e14dcfSSatish Balay #define NLS_INIT_DIRECTION 1 30*a7e14dcfSSatish Balay #define NLS_INIT_INTERPOLATION 2 31*a7e14dcfSSatish Balay #define NLS_INIT_TYPES 3 32*a7e14dcfSSatish Balay 33*a7e14dcfSSatish Balay #define NLS_UPDATE_STEP 0 34*a7e14dcfSSatish Balay #define NLS_UPDATE_REDUCTION 1 35*a7e14dcfSSatish Balay #define NLS_UPDATE_INTERPOLATION 2 36*a7e14dcfSSatish Balay #define NLS_UPDATE_TYPES 3 37*a7e14dcfSSatish Balay 38*a7e14dcfSSatish Balay static const char *NLS_KSP[64] = { 39*a7e14dcfSSatish Balay "cg", "nash", "stcg", "gltr", "petsc" 40*a7e14dcfSSatish Balay }; 41*a7e14dcfSSatish Balay 42*a7e14dcfSSatish Balay static const char *NLS_PC[64] = { 43*a7e14dcfSSatish Balay "none", "ahess", "bfgs", "petsc" 44*a7e14dcfSSatish Balay }; 45*a7e14dcfSSatish Balay 46*a7e14dcfSSatish Balay static const char *BFGS_SCALE[64] = { 47*a7e14dcfSSatish Balay "ahess", "phess", "bfgs" 48*a7e14dcfSSatish Balay }; 49*a7e14dcfSSatish Balay 50*a7e14dcfSSatish Balay static const char *NLS_INIT[64] = { 51*a7e14dcfSSatish Balay "constant", "direction", "interpolation" 52*a7e14dcfSSatish Balay }; 53*a7e14dcfSSatish Balay 54*a7e14dcfSSatish Balay static const char *NLS_UPDATE[64] = { 55*a7e14dcfSSatish Balay "step", "reduction", "interpolation" 56*a7e14dcfSSatish Balay }; 57*a7e14dcfSSatish Balay 58*a7e14dcfSSatish Balay static PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x) ; 59*a7e14dcfSSatish Balay /* Routine for BFGS preconditioner 60*a7e14dcfSSatish Balay 61*a7e14dcfSSatish Balay 62*a7e14dcfSSatish Balay Implements Newton's Method with a line search approach for solving 63*a7e14dcfSSatish Balay unconstrained minimization problems. A More'-Thuente line search 64*a7e14dcfSSatish Balay is used to guarantee that the bfgs preconditioner remains positive 65*a7e14dcfSSatish Balay definite. 66*a7e14dcfSSatish Balay 67*a7e14dcfSSatish Balay The method can shift the Hessian matrix. The shifting procedure is 68*a7e14dcfSSatish Balay adapted from the PATH algorithm for solving complementarity 69*a7e14dcfSSatish Balay problems. 70*a7e14dcfSSatish Balay 71*a7e14dcfSSatish Balay The linear system solve should be done with a conjugate gradient 72*a7e14dcfSSatish Balay method, although any method can be used. */ 73*a7e14dcfSSatish Balay 74*a7e14dcfSSatish Balay #define NLS_NEWTON 0 75*a7e14dcfSSatish Balay #define NLS_BFGS 1 76*a7e14dcfSSatish Balay #define NLS_SCALED_GRADIENT 2 77*a7e14dcfSSatish Balay #define NLS_GRADIENT 3 78*a7e14dcfSSatish Balay 79*a7e14dcfSSatish Balay #undef __FUNCT__ 80*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSolve_NLS" 81*a7e14dcfSSatish Balay static PetscErrorCode TaoSolve_NLS(TaoSolver tao) 82*a7e14dcfSSatish Balay { 83*a7e14dcfSSatish Balay PetscErrorCode ierr; 84*a7e14dcfSSatish Balay TAO_NLS *nlsP = (TAO_NLS *)tao->data; 85*a7e14dcfSSatish Balay 86*a7e14dcfSSatish Balay PC pc; 87*a7e14dcfSSatish Balay 88*a7e14dcfSSatish Balay KSPConvergedReason ksp_reason; 89*a7e14dcfSSatish Balay TaoLineSearchTerminationReason ls_reason; 90*a7e14dcfSSatish Balay TaoSolverTerminationReason reason; 91*a7e14dcfSSatish Balay 92*a7e14dcfSSatish Balay PetscReal fmin, ftrial, f_full, prered, actred, kappa, sigma; 93*a7e14dcfSSatish Balay PetscReal tau, tau_1, tau_2, tau_max, tau_min, max_radius; 94*a7e14dcfSSatish Balay PetscReal f, fold, gdx, gnorm, pert; 95*a7e14dcfSSatish Balay PetscReal step = 1.0; 96*a7e14dcfSSatish Balay 97*a7e14dcfSSatish Balay PetscReal delta; 98*a7e14dcfSSatish Balay PetscReal norm_d = 0.0, e_min; 99*a7e14dcfSSatish Balay 100*a7e14dcfSSatish Balay MatStructure matflag; 101*a7e14dcfSSatish Balay 102*a7e14dcfSSatish Balay PetscInt stepType; 103*a7e14dcfSSatish Balay PetscInt iter = 0; 104*a7e14dcfSSatish Balay PetscInt bfgsUpdates = 0; 105*a7e14dcfSSatish Balay PetscInt n,N,kspits; 106*a7e14dcfSSatish Balay PetscInt needH; 107*a7e14dcfSSatish Balay 108*a7e14dcfSSatish Balay PetscInt i_max = 5; 109*a7e14dcfSSatish Balay PetscInt j_max = 1; 110*a7e14dcfSSatish Balay PetscInt i, j; 111*a7e14dcfSSatish Balay 112*a7e14dcfSSatish Balay PetscFunctionBegin; 113*a7e14dcfSSatish Balay 114*a7e14dcfSSatish Balay if (tao->XL || tao->XU || tao->ops->computebounds) { 115*a7e14dcfSSatish Balay ierr = PetscPrintf(((PetscObject)tao)->comm,"WARNING: Variable bounds have been set but will be ignored by nls algorithm\n"); CHKERRQ(ierr); 116*a7e14dcfSSatish Balay } 117*a7e14dcfSSatish Balay 118*a7e14dcfSSatish Balay /* Initialized variables */ 119*a7e14dcfSSatish Balay pert = nlsP->sval; 120*a7e14dcfSSatish Balay 121*a7e14dcfSSatish Balay nlsP->ksp_atol = 0; 122*a7e14dcfSSatish Balay nlsP->ksp_rtol = 0; 123*a7e14dcfSSatish Balay nlsP->ksp_dtol = 0; 124*a7e14dcfSSatish Balay nlsP->ksp_ctol = 0; 125*a7e14dcfSSatish Balay nlsP->ksp_negc = 0; 126*a7e14dcfSSatish Balay nlsP->ksp_iter = 0; 127*a7e14dcfSSatish Balay nlsP->ksp_othr = 0; 128*a7e14dcfSSatish Balay 129*a7e14dcfSSatish Balay 130*a7e14dcfSSatish Balay 131*a7e14dcfSSatish Balay /* Modify the linear solver to a trust region method if desired */ 132*a7e14dcfSSatish Balay 133*a7e14dcfSSatish Balay switch(nlsP->ksp_type) { 134*a7e14dcfSSatish Balay case NLS_KSP_CG: 135*a7e14dcfSSatish Balay ierr = KSPSetType(tao->ksp, KSPCG); CHKERRQ(ierr); 136*a7e14dcfSSatish Balay if (tao->ksp->ops->setfromoptions) { 137*a7e14dcfSSatish Balay (*tao->ksp->ops->setfromoptions)(tao->ksp); 138*a7e14dcfSSatish Balay } 139*a7e14dcfSSatish Balay break; 140*a7e14dcfSSatish Balay 141*a7e14dcfSSatish Balay case NLS_KSP_NASH: 142*a7e14dcfSSatish Balay ierr = KSPSetType(tao->ksp, KSPNASH); CHKERRQ(ierr); 143*a7e14dcfSSatish Balay if (tao->ksp->ops->setfromoptions) { 144*a7e14dcfSSatish Balay (*tao->ksp->ops->setfromoptions)(tao->ksp); 145*a7e14dcfSSatish Balay } 146*a7e14dcfSSatish Balay break; 147*a7e14dcfSSatish Balay 148*a7e14dcfSSatish Balay case NLS_KSP_STCG: 149*a7e14dcfSSatish Balay ierr = KSPSetType(tao->ksp, KSPSTCG); CHKERRQ(ierr); 150*a7e14dcfSSatish Balay if (tao->ksp->ops->setfromoptions) { 151*a7e14dcfSSatish Balay (*tao->ksp->ops->setfromoptions)(tao->ksp); 152*a7e14dcfSSatish Balay } 153*a7e14dcfSSatish Balay break; 154*a7e14dcfSSatish Balay 155*a7e14dcfSSatish Balay case NLS_KSP_GLTR: 156*a7e14dcfSSatish Balay ierr = KSPSetType(tao->ksp, KSPGLTR); CHKERRQ(ierr); 157*a7e14dcfSSatish Balay if (tao->ksp->ops->setfromoptions) { 158*a7e14dcfSSatish Balay (*tao->ksp->ops->setfromoptions)(tao->ksp); 159*a7e14dcfSSatish Balay } 160*a7e14dcfSSatish Balay break; 161*a7e14dcfSSatish Balay 162*a7e14dcfSSatish Balay default: 163*a7e14dcfSSatish Balay /* Use the method set by the ksp_type */ 164*a7e14dcfSSatish Balay break; 165*a7e14dcfSSatish Balay } 166*a7e14dcfSSatish Balay 167*a7e14dcfSSatish Balay /* Initialize trust-region radius when using nash, stcg, or gltr 168*a7e14dcfSSatish Balay Will be reset during the first iteration */ 169*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type) { 170*a7e14dcfSSatish Balay ierr = KSPNASHSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 171*a7e14dcfSSatish Balay } else if (NLS_KSP_STCG == nlsP->ksp_type) { 172*a7e14dcfSSatish Balay ierr = KSPSTCGSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 173*a7e14dcfSSatish Balay } else if (NLS_KSP_GLTR == nlsP->ksp_type) { 174*a7e14dcfSSatish Balay ierr = KSPGLTRSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 175*a7e14dcfSSatish Balay } 176*a7e14dcfSSatish Balay 177*a7e14dcfSSatish Balay 178*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type || 179*a7e14dcfSSatish Balay NLS_KSP_STCG == nlsP->ksp_type || 180*a7e14dcfSSatish Balay NLS_KSP_GLTR == nlsP->ksp_type) { 181*a7e14dcfSSatish Balay tao->trust = tao->trust0; 182*a7e14dcfSSatish Balay 183*a7e14dcfSSatish Balay if (tao->trust < 0.0) { 184*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "Initial radius negative"); 185*a7e14dcfSSatish Balay } 186*a7e14dcfSSatish Balay 187*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 188*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, nlsP->min_radius); 189*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, nlsP->max_radius); 190*a7e14dcfSSatish Balay } 191*a7e14dcfSSatish Balay 192*a7e14dcfSSatish Balay /* Get vectors we will need */ 193*a7e14dcfSSatish Balay 194*a7e14dcfSSatish Balay if (NLS_PC_BFGS == nlsP->pc_type && !nlsP->M) { 195*a7e14dcfSSatish Balay ierr = VecGetLocalSize(tao->solution,&n); CHKERRQ(ierr); 196*a7e14dcfSSatish Balay ierr = VecGetSize(tao->solution,&N); CHKERRQ(ierr); 197*a7e14dcfSSatish Balay ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&nlsP->M); CHKERRQ(ierr); 198*a7e14dcfSSatish Balay ierr = MatLMVMAllocateVectors(nlsP->M,tao->solution); CHKERRQ(ierr); 199*a7e14dcfSSatish Balay } 200*a7e14dcfSSatish Balay 201*a7e14dcfSSatish Balay /* Check convergence criteria */ 202*a7e14dcfSSatish Balay ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &f, tao->gradient); CHKERRQ(ierr); 203*a7e14dcfSSatish Balay ierr = VecNorm(tao->gradient,NORM_2,&gnorm); CHKERRQ(ierr); 204*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) { 205*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 206*a7e14dcfSSatish Balay } 207*a7e14dcfSSatish Balay needH = 1; 208*a7e14dcfSSatish Balay 209*a7e14dcfSSatish Balay ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason); CHKERRQ(ierr); 210*a7e14dcfSSatish Balay if (reason != TAO_CONTINUE_ITERATING) { 211*a7e14dcfSSatish Balay PetscFunctionReturn(0); 212*a7e14dcfSSatish Balay } 213*a7e14dcfSSatish Balay 214*a7e14dcfSSatish Balay /* create vectors for the limited memory preconditioner */ 215*a7e14dcfSSatish Balay if ((NLS_PC_BFGS == nlsP->pc_type) && 216*a7e14dcfSSatish Balay (BFGS_SCALE_BFGS != nlsP->bfgs_scale_type)) { 217*a7e14dcfSSatish Balay if (!nlsP->Diag) { 218*a7e14dcfSSatish Balay ierr = VecDuplicate(tao->solution,&nlsP->Diag); CHKERRQ(ierr); 219*a7e14dcfSSatish Balay } 220*a7e14dcfSSatish Balay } 221*a7e14dcfSSatish Balay 222*a7e14dcfSSatish Balay 223*a7e14dcfSSatish Balay /* Modify the preconditioner to use the bfgs approximation */ 224*a7e14dcfSSatish Balay ierr = KSPGetPC(tao->ksp, &pc); CHKERRQ(ierr); 225*a7e14dcfSSatish Balay switch(nlsP->pc_type) { 226*a7e14dcfSSatish Balay case NLS_PC_NONE: 227*a7e14dcfSSatish Balay ierr = PCSetType(pc, PCNONE); CHKERRQ(ierr); 228*a7e14dcfSSatish Balay if (pc->ops->setfromoptions) { 229*a7e14dcfSSatish Balay (*pc->ops->setfromoptions)(pc); 230*a7e14dcfSSatish Balay } 231*a7e14dcfSSatish Balay break; 232*a7e14dcfSSatish Balay 233*a7e14dcfSSatish Balay case NLS_PC_AHESS: 234*a7e14dcfSSatish Balay ierr = PCSetType(pc, PCJACOBI); CHKERRQ(ierr); 235*a7e14dcfSSatish Balay if (pc->ops->setfromoptions) { 236*a7e14dcfSSatish Balay (*pc->ops->setfromoptions)(pc); 237*a7e14dcfSSatish Balay } 238*a7e14dcfSSatish Balay ierr = PCJacobiSetUseAbs(pc); CHKERRQ(ierr); 239*a7e14dcfSSatish Balay break; 240*a7e14dcfSSatish Balay 241*a7e14dcfSSatish Balay case NLS_PC_BFGS: 242*a7e14dcfSSatish Balay ierr = PCSetType(pc, PCSHELL); CHKERRQ(ierr); 243*a7e14dcfSSatish Balay if (pc->ops->setfromoptions) { 244*a7e14dcfSSatish Balay (*pc->ops->setfromoptions)(pc); 245*a7e14dcfSSatish Balay } 246*a7e14dcfSSatish Balay ierr = PCShellSetName(pc, "bfgs"); CHKERRQ(ierr); 247*a7e14dcfSSatish Balay ierr = PCShellSetContext(pc, nlsP->M); CHKERRQ(ierr); 248*a7e14dcfSSatish Balay ierr = PCShellSetApply(pc, MatLMVMSolveShell); CHKERRQ(ierr); 249*a7e14dcfSSatish Balay break; 250*a7e14dcfSSatish Balay 251*a7e14dcfSSatish Balay default: 252*a7e14dcfSSatish Balay /* Use the pc method set by pc_type */ 253*a7e14dcfSSatish Balay break; 254*a7e14dcfSSatish Balay } 255*a7e14dcfSSatish Balay 256*a7e14dcfSSatish Balay /* Initialize trust-region radius. The initialization is only performed 257*a7e14dcfSSatish Balay when we are using Nash, Steihaug-Toint or the Generalized Lanczos method. */ 258*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type || 259*a7e14dcfSSatish Balay NLS_KSP_STCG == nlsP->ksp_type || 260*a7e14dcfSSatish Balay NLS_KSP_GLTR == nlsP->ksp_type) { 261*a7e14dcfSSatish Balay switch(nlsP->init_type) { 262*a7e14dcfSSatish Balay case NLS_INIT_CONSTANT: 263*a7e14dcfSSatish Balay /* Use the initial radius specified */ 264*a7e14dcfSSatish Balay break; 265*a7e14dcfSSatish Balay 266*a7e14dcfSSatish Balay case NLS_INIT_INTERPOLATION: 267*a7e14dcfSSatish Balay /* Use the initial radius specified */ 268*a7e14dcfSSatish Balay max_radius = 0.0; 269*a7e14dcfSSatish Balay 270*a7e14dcfSSatish Balay for (j = 0; j < j_max; ++j) { 271*a7e14dcfSSatish Balay fmin = f; 272*a7e14dcfSSatish Balay sigma = 0.0; 273*a7e14dcfSSatish Balay 274*a7e14dcfSSatish Balay if (needH) { 275*a7e14dcfSSatish Balay ierr = TaoComputeHessian(tao, tao->solution, &tao->hessian, &tao->hessian_pre, &matflag); CHKERRQ(ierr); 276*a7e14dcfSSatish Balay needH = 0; 277*a7e14dcfSSatish Balay } 278*a7e14dcfSSatish Balay 279*a7e14dcfSSatish Balay for (i = 0; i < i_max; ++i) { 280*a7e14dcfSSatish Balay ierr = VecCopy(tao->solution,nlsP->W); CHKERRQ(ierr); 281*a7e14dcfSSatish Balay ierr = VecAXPY(nlsP->W,-tao->trust/gnorm,tao->gradient); CHKERRQ(ierr); 282*a7e14dcfSSatish Balay ierr = TaoComputeObjective(tao, nlsP->W, &ftrial); CHKERRQ(ierr); 283*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(ftrial)) { 284*a7e14dcfSSatish Balay tau = nlsP->gamma1_i; 285*a7e14dcfSSatish Balay } 286*a7e14dcfSSatish Balay else { 287*a7e14dcfSSatish Balay if (ftrial < fmin) { 288*a7e14dcfSSatish Balay fmin = ftrial; 289*a7e14dcfSSatish Balay sigma = -tao->trust / gnorm; 290*a7e14dcfSSatish Balay } 291*a7e14dcfSSatish Balay 292*a7e14dcfSSatish Balay ierr = MatMult(tao->hessian, tao->gradient, nlsP->D); CHKERRQ(ierr); 293*a7e14dcfSSatish Balay ierr = VecDot(tao->gradient, nlsP->D, &prered); CHKERRQ(ierr); 294*a7e14dcfSSatish Balay 295*a7e14dcfSSatish Balay prered = tao->trust * (gnorm - 0.5 * tao->trust * prered / (gnorm * gnorm)); 296*a7e14dcfSSatish Balay actred = f - ftrial; 297*a7e14dcfSSatish Balay if ((PetscAbsScalar(actred) <= nlsP->epsilon) && 298*a7e14dcfSSatish Balay (PetscAbsScalar(prered) <= nlsP->epsilon)) { 299*a7e14dcfSSatish Balay kappa = 1.0; 300*a7e14dcfSSatish Balay } 301*a7e14dcfSSatish Balay else { 302*a7e14dcfSSatish Balay kappa = actred / prered; 303*a7e14dcfSSatish Balay } 304*a7e14dcfSSatish Balay 305*a7e14dcfSSatish Balay tau_1 = nlsP->theta_i * gnorm * tao->trust / (nlsP->theta_i * gnorm * tao->trust + (1.0 - nlsP->theta_i) * prered - actred); 306*a7e14dcfSSatish Balay tau_2 = nlsP->theta_i * gnorm * tao->trust / (nlsP->theta_i * gnorm * tao->trust - (1.0 + nlsP->theta_i) * prered + actred); 307*a7e14dcfSSatish Balay tau_min = PetscMin(tau_1, tau_2); 308*a7e14dcfSSatish Balay tau_max = PetscMax(tau_1, tau_2); 309*a7e14dcfSSatish Balay 310*a7e14dcfSSatish Balay if (PetscAbsScalar(kappa - 1.0) <= nlsP->mu1_i) { 311*a7e14dcfSSatish Balay /* Great agreement */ 312*a7e14dcfSSatish Balay max_radius = PetscMax(max_radius, tao->trust); 313*a7e14dcfSSatish Balay 314*a7e14dcfSSatish Balay if (tau_max < 1.0) { 315*a7e14dcfSSatish Balay tau = nlsP->gamma3_i; 316*a7e14dcfSSatish Balay } 317*a7e14dcfSSatish Balay else if (tau_max > nlsP->gamma4_i) { 318*a7e14dcfSSatish Balay tau = nlsP->gamma4_i; 319*a7e14dcfSSatish Balay } 320*a7e14dcfSSatish Balay else if (tau_1 >= 1.0 && tau_1 <= nlsP->gamma4_i && tau_2 < 1.0) { 321*a7e14dcfSSatish Balay tau = tau_1; 322*a7e14dcfSSatish Balay } 323*a7e14dcfSSatish Balay else if (tau_2 >= 1.0 && tau_2 <= nlsP->gamma4_i && tau_1 < 1.0) { 324*a7e14dcfSSatish Balay tau = tau_2; 325*a7e14dcfSSatish Balay } 326*a7e14dcfSSatish Balay else { 327*a7e14dcfSSatish Balay tau = tau_max; 328*a7e14dcfSSatish Balay } 329*a7e14dcfSSatish Balay } 330*a7e14dcfSSatish Balay else if (PetscAbsScalar(kappa - 1.0) <= nlsP->mu2_i) { 331*a7e14dcfSSatish Balay /* Good agreement */ 332*a7e14dcfSSatish Balay max_radius = PetscMax(max_radius, tao->trust); 333*a7e14dcfSSatish Balay 334*a7e14dcfSSatish Balay if (tau_max < nlsP->gamma2_i) { 335*a7e14dcfSSatish Balay tau = nlsP->gamma2_i; 336*a7e14dcfSSatish Balay } 337*a7e14dcfSSatish Balay else if (tau_max > nlsP->gamma3_i) { 338*a7e14dcfSSatish Balay tau = nlsP->gamma3_i; 339*a7e14dcfSSatish Balay } 340*a7e14dcfSSatish Balay else { 341*a7e14dcfSSatish Balay tau = tau_max; 342*a7e14dcfSSatish Balay } 343*a7e14dcfSSatish Balay } 344*a7e14dcfSSatish Balay else { 345*a7e14dcfSSatish Balay /* Not good agreement */ 346*a7e14dcfSSatish Balay if (tau_min > 1.0) { 347*a7e14dcfSSatish Balay tau = nlsP->gamma2_i; 348*a7e14dcfSSatish Balay } 349*a7e14dcfSSatish Balay else if (tau_max < nlsP->gamma1_i) { 350*a7e14dcfSSatish Balay tau = nlsP->gamma1_i; 351*a7e14dcfSSatish Balay } 352*a7e14dcfSSatish Balay else if ((tau_min < nlsP->gamma1_i) && (tau_max >= 1.0)) { 353*a7e14dcfSSatish Balay tau = nlsP->gamma1_i; 354*a7e14dcfSSatish Balay } 355*a7e14dcfSSatish Balay else if ((tau_1 >= nlsP->gamma1_i) && (tau_1 < 1.0) && 356*a7e14dcfSSatish Balay ((tau_2 < nlsP->gamma1_i) || (tau_2 >= 1.0))) { 357*a7e14dcfSSatish Balay tau = tau_1; 358*a7e14dcfSSatish Balay } 359*a7e14dcfSSatish Balay else if ((tau_2 >= nlsP->gamma1_i) && (tau_2 < 1.0) && 360*a7e14dcfSSatish Balay ((tau_1 < nlsP->gamma1_i) || (tau_2 >= 1.0))) { 361*a7e14dcfSSatish Balay tau = tau_2; 362*a7e14dcfSSatish Balay } 363*a7e14dcfSSatish Balay else { 364*a7e14dcfSSatish Balay tau = tau_max; 365*a7e14dcfSSatish Balay } 366*a7e14dcfSSatish Balay } 367*a7e14dcfSSatish Balay } 368*a7e14dcfSSatish Balay tao->trust = tau * tao->trust; 369*a7e14dcfSSatish Balay } 370*a7e14dcfSSatish Balay 371*a7e14dcfSSatish Balay if (fmin < f) { 372*a7e14dcfSSatish Balay f = fmin; 373*a7e14dcfSSatish Balay ierr = VecAXPY(tao->solution,sigma,tao->gradient); CHKERRQ(ierr); 374*a7e14dcfSSatish Balay ierr = TaoComputeGradient(tao,tao->solution,tao->gradient); CHKERRQ(ierr); 375*a7e14dcfSSatish Balay 376*a7e14dcfSSatish Balay ierr = VecNorm(tao->gradient,NORM_2,&gnorm); CHKERRQ(ierr); 377*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(gnorm)) { 378*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "User provided compute gradient generated Inf or NaN"); 379*a7e14dcfSSatish Balay } 380*a7e14dcfSSatish Balay needH = 1; 381*a7e14dcfSSatish Balay 382*a7e14dcfSSatish Balay ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, 1.0, &reason); CHKERRQ(ierr); 383*a7e14dcfSSatish Balay if (reason != TAO_CONTINUE_ITERATING) { 384*a7e14dcfSSatish Balay PetscFunctionReturn(0); 385*a7e14dcfSSatish Balay } 386*a7e14dcfSSatish Balay } 387*a7e14dcfSSatish Balay } 388*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, max_radius); 389*a7e14dcfSSatish Balay 390*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 391*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, nlsP->min_radius); 392*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, nlsP->max_radius); 393*a7e14dcfSSatish Balay break; 394*a7e14dcfSSatish Balay 395*a7e14dcfSSatish Balay default: 396*a7e14dcfSSatish Balay /* Norm of the first direction will initialize radius */ 397*a7e14dcfSSatish Balay tao->trust = 0.0; 398*a7e14dcfSSatish Balay break; 399*a7e14dcfSSatish Balay } 400*a7e14dcfSSatish Balay } 401*a7e14dcfSSatish Balay 402*a7e14dcfSSatish Balay /* Set initial scaling for the BFGS preconditioner 403*a7e14dcfSSatish Balay This step is done after computing the initial trust-region radius 404*a7e14dcfSSatish Balay since the function value may have decreased */ 405*a7e14dcfSSatish Balay if (NLS_PC_BFGS == nlsP->pc_type) { 406*a7e14dcfSSatish Balay if (f != 0.0) { 407*a7e14dcfSSatish Balay delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 408*a7e14dcfSSatish Balay } 409*a7e14dcfSSatish Balay else { 410*a7e14dcfSSatish Balay delta = 2.0 / (gnorm*gnorm); 411*a7e14dcfSSatish Balay } 412*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(nlsP->M,delta); CHKERRQ(ierr); 413*a7e14dcfSSatish Balay } 414*a7e14dcfSSatish Balay 415*a7e14dcfSSatish Balay /* Set counter for gradient/reset steps*/ 416*a7e14dcfSSatish Balay nlsP->newt = 0; 417*a7e14dcfSSatish Balay nlsP->bfgs = 0; 418*a7e14dcfSSatish Balay nlsP->sgrad = 0; 419*a7e14dcfSSatish Balay nlsP->grad = 0; 420*a7e14dcfSSatish Balay 421*a7e14dcfSSatish Balay /* Have not converged; continue with Newton method */ 422*a7e14dcfSSatish Balay while (reason == TAO_CONTINUE_ITERATING) { 423*a7e14dcfSSatish Balay ++iter; 424*a7e14dcfSSatish Balay 425*a7e14dcfSSatish Balay /* Compute the Hessian */ 426*a7e14dcfSSatish Balay if (needH) { 427*a7e14dcfSSatish Balay ierr = TaoComputeHessian(tao, tao->solution, &tao->hessian, &tao->hessian_pre, &matflag); CHKERRQ(ierr); 428*a7e14dcfSSatish Balay needH = 0; 429*a7e14dcfSSatish Balay } 430*a7e14dcfSSatish Balay 431*a7e14dcfSSatish Balay if ((NLS_PC_BFGS == nlsP->pc_type) && 432*a7e14dcfSSatish Balay (BFGS_SCALE_AHESS == nlsP->bfgs_scale_type)) { 433*a7e14dcfSSatish Balay /* Obtain diagonal for the bfgs preconditioner */ 434*a7e14dcfSSatish Balay ierr = MatGetDiagonal(tao->hessian, nlsP->Diag); CHKERRQ(ierr); 435*a7e14dcfSSatish Balay ierr = VecAbs(nlsP->Diag); CHKERRQ(ierr); 436*a7e14dcfSSatish Balay ierr = VecReciprocal(nlsP->Diag); CHKERRQ(ierr); 437*a7e14dcfSSatish Balay ierr = MatLMVMSetScale(nlsP->M,nlsP->Diag); CHKERRQ(ierr); 438*a7e14dcfSSatish Balay } 439*a7e14dcfSSatish Balay 440*a7e14dcfSSatish Balay /* Shift the Hessian matrix */ 441*a7e14dcfSSatish Balay if (pert > 0) { 442*a7e14dcfSSatish Balay ierr = MatShift(tao->hessian, pert); 443*a7e14dcfSSatish Balay if (tao->hessian != tao->hessian_pre) { 444*a7e14dcfSSatish Balay ierr = MatShift(tao->hessian_pre, pert); CHKERRQ(ierr); 445*a7e14dcfSSatish Balay } 446*a7e14dcfSSatish Balay } 447*a7e14dcfSSatish Balay 448*a7e14dcfSSatish Balay 449*a7e14dcfSSatish Balay if (NLS_PC_BFGS == nlsP->pc_type) { 450*a7e14dcfSSatish Balay if (BFGS_SCALE_PHESS == nlsP->bfgs_scale_type) { 451*a7e14dcfSSatish Balay /* Obtain diagonal for the bfgs preconditioner */ 452*a7e14dcfSSatish Balay ierr = MatGetDiagonal(tao->hessian, nlsP->Diag); CHKERRQ(ierr); 453*a7e14dcfSSatish Balay ierr = VecAbs(nlsP->Diag); CHKERRQ(ierr); 454*a7e14dcfSSatish Balay ierr = VecReciprocal(nlsP->Diag); CHKERRQ(ierr); 455*a7e14dcfSSatish Balay ierr = MatLMVMSetScale(nlsP->M,nlsP->Diag); CHKERRQ(ierr); 456*a7e14dcfSSatish Balay } 457*a7e14dcfSSatish Balay /* Update the limited memory preconditioner */ 458*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr); 459*a7e14dcfSSatish Balay ++bfgsUpdates; 460*a7e14dcfSSatish Balay } 461*a7e14dcfSSatish Balay 462*a7e14dcfSSatish Balay /* Solve the Newton system of equations */ 463*a7e14dcfSSatish Balay ierr = KSPSetOperators(tao->ksp,tao->hessian,tao->hessian_pre,matflag); CHKERRQ(ierr); 464*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type || 465*a7e14dcfSSatish Balay NLS_KSP_STCG == nlsP->ksp_type || 466*a7e14dcfSSatish Balay NLS_KSP_GLTR == nlsP->ksp_type) { 467*a7e14dcfSSatish Balay 468*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type) { 469*a7e14dcfSSatish Balay ierr = KSPNASHSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 470*a7e14dcfSSatish Balay } else if (NLS_KSP_STCG == nlsP->ksp_type) { 471*a7e14dcfSSatish Balay ierr = KSPSTCGSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 472*a7e14dcfSSatish Balay } else if (NLS_KSP_GLTR == nlsP->ksp_type) { 473*a7e14dcfSSatish Balay ierr = KSPGLTRSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 474*a7e14dcfSSatish Balay } 475*a7e14dcfSSatish Balay 476*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, nlsP->D); CHKERRQ(ierr); 477*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&kspits); CHKERRQ(ierr); 478*a7e14dcfSSatish Balay tao->ksp_its+=kspits; 479*a7e14dcfSSatish Balay 480*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type) { 481*a7e14dcfSSatish Balay ierr = KSPNASHGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr); 482*a7e14dcfSSatish Balay } else if (NLS_KSP_STCG == nlsP->ksp_type) { 483*a7e14dcfSSatish Balay ierr = KSPSTCGGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr); 484*a7e14dcfSSatish Balay } else if (NLS_KSP_GLTR == nlsP->ksp_type) { 485*a7e14dcfSSatish Balay ierr = KSPGLTRGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr); 486*a7e14dcfSSatish Balay } 487*a7e14dcfSSatish Balay 488*a7e14dcfSSatish Balay if (0.0 == tao->trust) { 489*a7e14dcfSSatish Balay /* Radius was uninitialized; use the norm of the direction */ 490*a7e14dcfSSatish Balay if (norm_d > 0.0) { 491*a7e14dcfSSatish Balay tao->trust = norm_d; 492*a7e14dcfSSatish Balay 493*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 494*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, nlsP->min_radius); 495*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, nlsP->max_radius); 496*a7e14dcfSSatish Balay } 497*a7e14dcfSSatish Balay else { 498*a7e14dcfSSatish Balay /* The direction was bad; set radius to default value and re-solve 499*a7e14dcfSSatish Balay the trust-region subproblem to get a direction */ 500*a7e14dcfSSatish Balay tao->trust = tao->trust0; 501*a7e14dcfSSatish Balay 502*a7e14dcfSSatish Balay /* Modify the radius if it is too large or small */ 503*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, nlsP->min_radius); 504*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, nlsP->max_radius); 505*a7e14dcfSSatish Balay 506*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type) { 507*a7e14dcfSSatish Balay ierr = KSPNASHSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 508*a7e14dcfSSatish Balay } else if (NLS_KSP_STCG == nlsP->ksp_type) { 509*a7e14dcfSSatish Balay ierr = KSPSTCGSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 510*a7e14dcfSSatish Balay } else if (NLS_KSP_GLTR == nlsP->ksp_type) { 511*a7e14dcfSSatish Balay ierr = KSPGLTRSetRadius(tao->ksp,nlsP->max_radius); CHKERRQ(ierr); 512*a7e14dcfSSatish Balay } 513*a7e14dcfSSatish Balay 514*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, nlsP->D); CHKERRQ(ierr); 515*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp,&kspits); CHKERRQ(ierr); 516*a7e14dcfSSatish Balay tao->ksp_its+=kspits; 517*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type) { 518*a7e14dcfSSatish Balay ierr = KSPNASHGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr); 519*a7e14dcfSSatish Balay } else if (NLS_KSP_STCG == nlsP->ksp_type) { 520*a7e14dcfSSatish Balay ierr = KSPSTCGGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr); 521*a7e14dcfSSatish Balay } else if (NLS_KSP_GLTR == nlsP->ksp_type) { 522*a7e14dcfSSatish Balay ierr = KSPGLTRGetNormD(tao->ksp,&norm_d); CHKERRQ(ierr); 523*a7e14dcfSSatish Balay } 524*a7e14dcfSSatish Balay 525*a7e14dcfSSatish Balay if (norm_d == 0.0) { 526*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1, "Initial direction zero"); 527*a7e14dcfSSatish Balay } 528*a7e14dcfSSatish Balay } 529*a7e14dcfSSatish Balay } 530*a7e14dcfSSatish Balay } 531*a7e14dcfSSatish Balay else { 532*a7e14dcfSSatish Balay ierr = KSPSolve(tao->ksp, tao->gradient, nlsP->D); CHKERRQ(ierr); 533*a7e14dcfSSatish Balay ierr = KSPGetIterationNumber(tao->ksp, &kspits); CHKERRQ(ierr); 534*a7e14dcfSSatish Balay tao->ksp_its += kspits; 535*a7e14dcfSSatish Balay } 536*a7e14dcfSSatish Balay ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr); 537*a7e14dcfSSatish Balay ierr = KSPGetConvergedReason(tao->ksp, &ksp_reason); CHKERRQ(ierr); 538*a7e14dcfSSatish Balay if ((KSP_DIVERGED_INDEFINITE_PC == ksp_reason) && 539*a7e14dcfSSatish Balay (NLS_PC_BFGS == nlsP->pc_type) && (bfgsUpdates > 1)) { 540*a7e14dcfSSatish Balay /* Preconditioner is numerically indefinite; reset the 541*a7e14dcfSSatish Balay approximate if using BFGS preconditioning. */ 542*a7e14dcfSSatish Balay 543*a7e14dcfSSatish Balay if (f != 0.0) { 544*a7e14dcfSSatish Balay delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 545*a7e14dcfSSatish Balay } 546*a7e14dcfSSatish Balay else { 547*a7e14dcfSSatish Balay delta = 2.0 / (gnorm*gnorm); 548*a7e14dcfSSatish Balay } 549*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(nlsP->M,delta); CHKERRQ(ierr); 550*a7e14dcfSSatish Balay ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr); 551*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr); 552*a7e14dcfSSatish Balay bfgsUpdates = 1; 553*a7e14dcfSSatish Balay } 554*a7e14dcfSSatish Balay 555*a7e14dcfSSatish Balay if (KSP_CONVERGED_ATOL == ksp_reason) { 556*a7e14dcfSSatish Balay ++nlsP->ksp_atol; 557*a7e14dcfSSatish Balay } 558*a7e14dcfSSatish Balay else if (KSP_CONVERGED_RTOL == ksp_reason) { 559*a7e14dcfSSatish Balay ++nlsP->ksp_rtol; 560*a7e14dcfSSatish Balay } 561*a7e14dcfSSatish Balay else if (KSP_CONVERGED_CG_CONSTRAINED == ksp_reason) { 562*a7e14dcfSSatish Balay ++nlsP->ksp_ctol; 563*a7e14dcfSSatish Balay } 564*a7e14dcfSSatish Balay else if (KSP_CONVERGED_CG_NEG_CURVE == ksp_reason) { 565*a7e14dcfSSatish Balay ++nlsP->ksp_negc; 566*a7e14dcfSSatish Balay } 567*a7e14dcfSSatish Balay else if (KSP_DIVERGED_DTOL == ksp_reason) { 568*a7e14dcfSSatish Balay ++nlsP->ksp_dtol; 569*a7e14dcfSSatish Balay } 570*a7e14dcfSSatish Balay else if (KSP_DIVERGED_ITS == ksp_reason) { 571*a7e14dcfSSatish Balay ++nlsP->ksp_iter; 572*a7e14dcfSSatish Balay } 573*a7e14dcfSSatish Balay else { 574*a7e14dcfSSatish Balay ++nlsP->ksp_othr; 575*a7e14dcfSSatish Balay } 576*a7e14dcfSSatish Balay 577*a7e14dcfSSatish Balay /* Check for success (descent direction) */ 578*a7e14dcfSSatish Balay ierr = VecDot(nlsP->D, tao->gradient, &gdx); CHKERRQ(ierr); 579*a7e14dcfSSatish Balay if ((gdx >= 0.0) || PetscIsInfOrNanReal(gdx)) { 580*a7e14dcfSSatish Balay /* Newton step is not descent or direction produced Inf or NaN 581*a7e14dcfSSatish Balay Update the perturbation for next time */ 582*a7e14dcfSSatish Balay if (pert <= 0.0) { 583*a7e14dcfSSatish Balay /* Initialize the perturbation */ 584*a7e14dcfSSatish Balay pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm)); 585*a7e14dcfSSatish Balay if (NLS_KSP_GLTR == nlsP->ksp_type) { 586*a7e14dcfSSatish Balay ierr = KSPGLTRGetMinEig(tao->ksp,&e_min); CHKERRQ(ierr); 587*a7e14dcfSSatish Balay pert = PetscMax(pert, -e_min); 588*a7e14dcfSSatish Balay } 589*a7e14dcfSSatish Balay } 590*a7e14dcfSSatish Balay else { 591*a7e14dcfSSatish Balay /* Increase the perturbation */ 592*a7e14dcfSSatish Balay pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm)); 593*a7e14dcfSSatish Balay } 594*a7e14dcfSSatish Balay 595*a7e14dcfSSatish Balay if (NLS_PC_BFGS != nlsP->pc_type) { 596*a7e14dcfSSatish Balay /* We don't have the bfgs matrix around and updated 597*a7e14dcfSSatish Balay Must use gradient direction in this case */ 598*a7e14dcfSSatish Balay ierr = VecCopy(tao->gradient, nlsP->D); CHKERRQ(ierr); 599*a7e14dcfSSatish Balay ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr); 600*a7e14dcfSSatish Balay ++nlsP->grad; 601*a7e14dcfSSatish Balay stepType = NLS_GRADIENT; 602*a7e14dcfSSatish Balay } 603*a7e14dcfSSatish Balay else { 604*a7e14dcfSSatish Balay /* Attempt to use the BFGS direction */ 605*a7e14dcfSSatish Balay ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr); 606*a7e14dcfSSatish Balay ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr); 607*a7e14dcfSSatish Balay 608*a7e14dcfSSatish Balay /* Check for success (descent direction) */ 609*a7e14dcfSSatish Balay ierr = VecDot(tao->gradient, nlsP->D, &gdx); CHKERRQ(ierr); 610*a7e14dcfSSatish Balay if ((gdx >= 0) || PetscIsInfOrNanReal(gdx)) { 611*a7e14dcfSSatish Balay /* BFGS direction is not descent or direction produced not a number 612*a7e14dcfSSatish Balay We can assert bfgsUpdates > 1 in this case because 613*a7e14dcfSSatish Balay the first solve produces the scaled gradient direction, 614*a7e14dcfSSatish Balay which is guaranteed to be descent */ 615*a7e14dcfSSatish Balay 616*a7e14dcfSSatish Balay /* Use steepest descent direction (scaled) */ 617*a7e14dcfSSatish Balay 618*a7e14dcfSSatish Balay if (f != 0.0) { 619*a7e14dcfSSatish Balay delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 620*a7e14dcfSSatish Balay } 621*a7e14dcfSSatish Balay else { 622*a7e14dcfSSatish Balay delta = 2.0 / (gnorm*gnorm); 623*a7e14dcfSSatish Balay } 624*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(nlsP->M, delta); CHKERRQ(ierr); 625*a7e14dcfSSatish Balay ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr); 626*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr); 627*a7e14dcfSSatish Balay ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr); 628*a7e14dcfSSatish Balay ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr); 629*a7e14dcfSSatish Balay 630*a7e14dcfSSatish Balay bfgsUpdates = 1; 631*a7e14dcfSSatish Balay ++nlsP->sgrad; 632*a7e14dcfSSatish Balay stepType = NLS_SCALED_GRADIENT; 633*a7e14dcfSSatish Balay } 634*a7e14dcfSSatish Balay else { 635*a7e14dcfSSatish Balay if (1 == bfgsUpdates) { 636*a7e14dcfSSatish Balay /* The first BFGS direction is always the scaled gradient */ 637*a7e14dcfSSatish Balay ++nlsP->sgrad; 638*a7e14dcfSSatish Balay stepType = NLS_SCALED_GRADIENT; 639*a7e14dcfSSatish Balay } 640*a7e14dcfSSatish Balay else { 641*a7e14dcfSSatish Balay ++nlsP->bfgs; 642*a7e14dcfSSatish Balay stepType = NLS_BFGS; 643*a7e14dcfSSatish Balay } 644*a7e14dcfSSatish Balay } 645*a7e14dcfSSatish Balay } 646*a7e14dcfSSatish Balay } 647*a7e14dcfSSatish Balay else { 648*a7e14dcfSSatish Balay /* Computed Newton step is descent */ 649*a7e14dcfSSatish Balay switch (ksp_reason) { 650*a7e14dcfSSatish Balay case KSP_DIVERGED_NANORINF: 651*a7e14dcfSSatish Balay case KSP_DIVERGED_BREAKDOWN: 652*a7e14dcfSSatish Balay case KSP_DIVERGED_INDEFINITE_MAT: 653*a7e14dcfSSatish Balay case KSP_DIVERGED_INDEFINITE_PC: 654*a7e14dcfSSatish Balay case KSP_CONVERGED_CG_NEG_CURVE: 655*a7e14dcfSSatish Balay /* Matrix or preconditioner is indefinite; increase perturbation */ 656*a7e14dcfSSatish Balay if (pert <= 0.0) { 657*a7e14dcfSSatish Balay /* Initialize the perturbation */ 658*a7e14dcfSSatish Balay pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm)); 659*a7e14dcfSSatish Balay if (NLS_KSP_GLTR == nlsP->ksp_type) { 660*a7e14dcfSSatish Balay ierr = KSPGLTRGetMinEig(tao->ksp, &e_min); CHKERRQ(ierr); 661*a7e14dcfSSatish Balay pert = PetscMax(pert, -e_min); 662*a7e14dcfSSatish Balay } 663*a7e14dcfSSatish Balay } 664*a7e14dcfSSatish Balay else { 665*a7e14dcfSSatish Balay /* Increase the perturbation */ 666*a7e14dcfSSatish Balay pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm)); 667*a7e14dcfSSatish Balay } 668*a7e14dcfSSatish Balay break; 669*a7e14dcfSSatish Balay 670*a7e14dcfSSatish Balay default: 671*a7e14dcfSSatish Balay /* Newton step computation is good; decrease perturbation */ 672*a7e14dcfSSatish Balay pert = PetscMin(nlsP->psfac * pert, nlsP->pmsfac * gnorm); 673*a7e14dcfSSatish Balay if (pert < nlsP->pmin) { 674*a7e14dcfSSatish Balay pert = 0.0; 675*a7e14dcfSSatish Balay } 676*a7e14dcfSSatish Balay break; 677*a7e14dcfSSatish Balay } 678*a7e14dcfSSatish Balay 679*a7e14dcfSSatish Balay ++nlsP->newt; 680*a7e14dcfSSatish Balay stepType = NLS_NEWTON; 681*a7e14dcfSSatish Balay } 682*a7e14dcfSSatish Balay 683*a7e14dcfSSatish Balay /* Perform the linesearch */ 684*a7e14dcfSSatish Balay fold = f; 685*a7e14dcfSSatish Balay ierr = VecCopy(tao->solution, nlsP->Xold); CHKERRQ(ierr); 686*a7e14dcfSSatish Balay ierr = VecCopy(tao->gradient, nlsP->Gold); CHKERRQ(ierr); 687*a7e14dcfSSatish Balay 688*a7e14dcfSSatish Balay ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, nlsP->D, &step, &ls_reason); CHKERRQ(ierr); 689*a7e14dcfSSatish Balay ierr = TaoAddLineSearchCounts(tao); CHKERRQ(ierr); 690*a7e14dcfSSatish Balay 691*a7e14dcfSSatish Balay while (ls_reason != TAOLINESEARCH_SUCCESS && 692*a7e14dcfSSatish Balay ls_reason != TAOLINESEARCH_SUCCESS_USER && 693*a7e14dcfSSatish Balay stepType != NLS_GRADIENT) { /* Linesearch failed */ 694*a7e14dcfSSatish Balay f = fold; 695*a7e14dcfSSatish Balay ierr = VecCopy(nlsP->Xold, tao->solution); CHKERRQ(ierr); 696*a7e14dcfSSatish Balay ierr = VecCopy(nlsP->Gold, tao->gradient); CHKERRQ(ierr); 697*a7e14dcfSSatish Balay 698*a7e14dcfSSatish Balay switch(stepType) { 699*a7e14dcfSSatish Balay case NLS_NEWTON: 700*a7e14dcfSSatish Balay /* Failed to obtain acceptable iterate with Newton 1step 701*a7e14dcfSSatish Balay Update the perturbation for next time */ 702*a7e14dcfSSatish Balay if (pert <= 0.0) { 703*a7e14dcfSSatish Balay /* Initialize the perturbation */ 704*a7e14dcfSSatish Balay pert = PetscMin(nlsP->imax, PetscMax(nlsP->imin, nlsP->imfac * gnorm)); 705*a7e14dcfSSatish Balay if (NLS_KSP_GLTR == nlsP->ksp_type) { 706*a7e14dcfSSatish Balay ierr = KSPGLTRGetMinEig(tao->ksp,&e_min); CHKERRQ(ierr); 707*a7e14dcfSSatish Balay pert = PetscMax(pert, -e_min); 708*a7e14dcfSSatish Balay } 709*a7e14dcfSSatish Balay } 710*a7e14dcfSSatish Balay else { 711*a7e14dcfSSatish Balay /* Increase the perturbation */ 712*a7e14dcfSSatish Balay pert = PetscMin(nlsP->pmax, PetscMax(nlsP->pgfac * pert, nlsP->pmgfac * gnorm)); 713*a7e14dcfSSatish Balay } 714*a7e14dcfSSatish Balay 715*a7e14dcfSSatish Balay if (NLS_PC_BFGS != nlsP->pc_type) { 716*a7e14dcfSSatish Balay /* We don't have the bfgs matrix around and being updated 717*a7e14dcfSSatish Balay Must use gradient direction in this case */ 718*a7e14dcfSSatish Balay ierr = VecCopy(tao->gradient, nlsP->D); CHKERRQ(ierr); 719*a7e14dcfSSatish Balay ++nlsP->grad; 720*a7e14dcfSSatish Balay stepType = NLS_GRADIENT; 721*a7e14dcfSSatish Balay } 722*a7e14dcfSSatish Balay else { 723*a7e14dcfSSatish Balay /* Attempt to use the BFGS direction */ 724*a7e14dcfSSatish Balay ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr); 725*a7e14dcfSSatish Balay /* Check for success (descent direction) */ 726*a7e14dcfSSatish Balay ierr = VecDot(tao->solution, nlsP->D, &gdx); CHKERRQ(ierr); 727*a7e14dcfSSatish Balay if ((gdx <= 0) || PetscIsInfOrNanReal(gdx)) { 728*a7e14dcfSSatish Balay /* BFGS direction is not descent or direction produced not a number 729*a7e14dcfSSatish Balay We can assert bfgsUpdates > 1 in this case 730*a7e14dcfSSatish Balay Use steepest descent direction (scaled) */ 731*a7e14dcfSSatish Balay 732*a7e14dcfSSatish Balay if (f != 0.0) { 733*a7e14dcfSSatish Balay delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 734*a7e14dcfSSatish Balay } 735*a7e14dcfSSatish Balay else { 736*a7e14dcfSSatish Balay delta = 2.0 / (gnorm*gnorm); 737*a7e14dcfSSatish Balay } 738*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(nlsP->M, delta); CHKERRQ(ierr); 739*a7e14dcfSSatish Balay ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr); 740*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr); 741*a7e14dcfSSatish Balay ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr); 742*a7e14dcfSSatish Balay 743*a7e14dcfSSatish Balay bfgsUpdates = 1; 744*a7e14dcfSSatish Balay ++nlsP->sgrad; 745*a7e14dcfSSatish Balay stepType = NLS_SCALED_GRADIENT; 746*a7e14dcfSSatish Balay } 747*a7e14dcfSSatish Balay else { 748*a7e14dcfSSatish Balay if (1 == bfgsUpdates) { 749*a7e14dcfSSatish Balay /* The first BFGS direction is always the scaled gradient */ 750*a7e14dcfSSatish Balay ++nlsP->sgrad; 751*a7e14dcfSSatish Balay stepType = NLS_SCALED_GRADIENT; 752*a7e14dcfSSatish Balay } 753*a7e14dcfSSatish Balay else { 754*a7e14dcfSSatish Balay ++nlsP->bfgs; 755*a7e14dcfSSatish Balay stepType = NLS_BFGS; 756*a7e14dcfSSatish Balay } 757*a7e14dcfSSatish Balay } 758*a7e14dcfSSatish Balay } 759*a7e14dcfSSatish Balay break; 760*a7e14dcfSSatish Balay 761*a7e14dcfSSatish Balay case NLS_BFGS: 762*a7e14dcfSSatish Balay /* Can only enter if pc_type == NLS_PC_BFGS 763*a7e14dcfSSatish Balay Failed to obtain acceptable iterate with BFGS step 764*a7e14dcfSSatish Balay Attempt to use the scaled gradient direction */ 765*a7e14dcfSSatish Balay 766*a7e14dcfSSatish Balay if (f != 0.0) { 767*a7e14dcfSSatish Balay delta = 2.0 * PetscAbsScalar(f) / (gnorm*gnorm); 768*a7e14dcfSSatish Balay } 769*a7e14dcfSSatish Balay else { 770*a7e14dcfSSatish Balay delta = 2.0 / (gnorm*gnorm); 771*a7e14dcfSSatish Balay } 772*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(nlsP->M, delta); CHKERRQ(ierr); 773*a7e14dcfSSatish Balay ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr); 774*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr); 775*a7e14dcfSSatish Balay ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr); 776*a7e14dcfSSatish Balay 777*a7e14dcfSSatish Balay bfgsUpdates = 1; 778*a7e14dcfSSatish Balay ++nlsP->sgrad; 779*a7e14dcfSSatish Balay stepType = NLS_SCALED_GRADIENT; 780*a7e14dcfSSatish Balay break; 781*a7e14dcfSSatish Balay 782*a7e14dcfSSatish Balay case NLS_SCALED_GRADIENT: 783*a7e14dcfSSatish Balay /* Can only enter if pc_type == NLS_PC_BFGS 784*a7e14dcfSSatish Balay The scaled gradient step did not produce a new iterate; 785*a7e14dcfSSatish Balay attemp to use the gradient direction. 786*a7e14dcfSSatish Balay Need to make sure we are not using a different diagonal scaling */ 787*a7e14dcfSSatish Balay 788*a7e14dcfSSatish Balay ierr = MatLMVMSetScale(nlsP->M,0); CHKERRQ(ierr); 789*a7e14dcfSSatish Balay ierr = MatLMVMSetDelta(nlsP->M,1.0); CHKERRQ(ierr); 790*a7e14dcfSSatish Balay ierr = MatLMVMReset(nlsP->M); CHKERRQ(ierr); 791*a7e14dcfSSatish Balay ierr = MatLMVMUpdate(nlsP->M, tao->solution, tao->gradient); CHKERRQ(ierr); 792*a7e14dcfSSatish Balay ierr = MatLMVMSolve(nlsP->M, tao->gradient, nlsP->D); CHKERRQ(ierr); 793*a7e14dcfSSatish Balay 794*a7e14dcfSSatish Balay bfgsUpdates = 1; 795*a7e14dcfSSatish Balay ++nlsP->grad; 796*a7e14dcfSSatish Balay stepType = NLS_GRADIENT; 797*a7e14dcfSSatish Balay break; 798*a7e14dcfSSatish Balay } 799*a7e14dcfSSatish Balay ierr = VecScale(nlsP->D, -1.0); CHKERRQ(ierr); 800*a7e14dcfSSatish Balay 801*a7e14dcfSSatish Balay ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &f, tao->gradient, nlsP->D, &step, &ls_reason); CHKERRQ(ierr); 802*a7e14dcfSSatish Balay ierr = TaoLineSearchGetFullStepObjective(tao->linesearch, &f_full); CHKERRQ(ierr); 803*a7e14dcfSSatish Balay ierr = TaoAddLineSearchCounts(tao); CHKERRQ(ierr); 804*a7e14dcfSSatish Balay } 805*a7e14dcfSSatish Balay 806*a7e14dcfSSatish Balay if (ls_reason != TAOLINESEARCH_SUCCESS && 807*a7e14dcfSSatish Balay ls_reason != TAOLINESEARCH_SUCCESS_USER) { 808*a7e14dcfSSatish Balay /* Failed to find an improving point */ 809*a7e14dcfSSatish Balay f = fold; 810*a7e14dcfSSatish Balay ierr = VecCopy(nlsP->Xold, tao->solution); CHKERRQ(ierr); 811*a7e14dcfSSatish Balay ierr = VecCopy(nlsP->Gold, tao->gradient); CHKERRQ(ierr); 812*a7e14dcfSSatish Balay step = 0.0; 813*a7e14dcfSSatish Balay reason = TAO_DIVERGED_LS_FAILURE; 814*a7e14dcfSSatish Balay tao->reason = TAO_DIVERGED_LS_FAILURE; 815*a7e14dcfSSatish Balay break; 816*a7e14dcfSSatish Balay } 817*a7e14dcfSSatish Balay 818*a7e14dcfSSatish Balay /* Update trust region radius */ 819*a7e14dcfSSatish Balay if (NLS_KSP_NASH == nlsP->ksp_type || 820*a7e14dcfSSatish Balay NLS_KSP_STCG == nlsP->ksp_type || 821*a7e14dcfSSatish Balay NLS_KSP_GLTR == nlsP->ksp_type) { 822*a7e14dcfSSatish Balay switch(nlsP->update_type) { 823*a7e14dcfSSatish Balay case NLS_UPDATE_STEP: 824*a7e14dcfSSatish Balay if (stepType == NLS_NEWTON) { 825*a7e14dcfSSatish Balay if (step < nlsP->nu1) { 826*a7e14dcfSSatish Balay /* Very bad step taken; reduce radius */ 827*a7e14dcfSSatish Balay tao->trust = nlsP->omega1 * PetscMin(norm_d, tao->trust); 828*a7e14dcfSSatish Balay } 829*a7e14dcfSSatish Balay else if (step < nlsP->nu2) { 830*a7e14dcfSSatish Balay /* Reasonably bad step taken; reduce radius */ 831*a7e14dcfSSatish Balay tao->trust = nlsP->omega2 * PetscMin(norm_d, tao->trust); 832*a7e14dcfSSatish Balay } 833*a7e14dcfSSatish Balay else if (step < nlsP->nu3) { 834*a7e14dcfSSatish Balay /* Reasonable step was taken; leave radius alone */ 835*a7e14dcfSSatish Balay if (nlsP->omega3 < 1.0) { 836*a7e14dcfSSatish Balay tao->trust = nlsP->omega3 * PetscMin(norm_d, tao->trust); 837*a7e14dcfSSatish Balay } 838*a7e14dcfSSatish Balay else if (nlsP->omega3 > 1.0) { 839*a7e14dcfSSatish Balay tao->trust = PetscMax(nlsP->omega3 * norm_d, tao->trust); 840*a7e14dcfSSatish Balay } 841*a7e14dcfSSatish Balay } 842*a7e14dcfSSatish Balay else if (step < nlsP->nu4) { 843*a7e14dcfSSatish Balay /* Full step taken; increase the radius */ 844*a7e14dcfSSatish Balay tao->trust = PetscMax(nlsP->omega4 * norm_d, tao->trust); 845*a7e14dcfSSatish Balay } 846*a7e14dcfSSatish Balay else { 847*a7e14dcfSSatish Balay /* More than full step taken; increase the radius */ 848*a7e14dcfSSatish Balay tao->trust = PetscMax(nlsP->omega5 * norm_d, tao->trust); 849*a7e14dcfSSatish Balay } 850*a7e14dcfSSatish Balay } 851*a7e14dcfSSatish Balay else { 852*a7e14dcfSSatish Balay /* Newton step was not good; reduce the radius */ 853*a7e14dcfSSatish Balay tao->trust = nlsP->omega1 * PetscMin(norm_d, tao->trust); 854*a7e14dcfSSatish Balay } 855*a7e14dcfSSatish Balay break; 856*a7e14dcfSSatish Balay 857*a7e14dcfSSatish Balay case NLS_UPDATE_REDUCTION: 858*a7e14dcfSSatish Balay if (stepType == NLS_NEWTON) { 859*a7e14dcfSSatish Balay /* Get predicted reduction */ 860*a7e14dcfSSatish Balay 861*a7e14dcfSSatish Balay if (NLS_KSP_STCG == nlsP->ksp_type) { 862*a7e14dcfSSatish Balay ierr = KSPSTCGGetObjFcn(tao->ksp,&prered); 863*a7e14dcfSSatish Balay } else if (NLS_KSP_NASH == nlsP->ksp_type) { 864*a7e14dcfSSatish Balay ierr = KSPNASHGetObjFcn(tao->ksp,&prered); 865*a7e14dcfSSatish Balay } else { 866*a7e14dcfSSatish Balay ierr = KSPGLTRGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 867*a7e14dcfSSatish Balay } 868*a7e14dcfSSatish Balay 869*a7e14dcfSSatish Balay 870*a7e14dcfSSatish Balay 871*a7e14dcfSSatish Balay 872*a7e14dcfSSatish Balay if (prered >= 0.0) { 873*a7e14dcfSSatish Balay /* The predicted reduction has the wrong sign. This cannot */ 874*a7e14dcfSSatish Balay /* happen in infinite precision arithmetic. Step should */ 875*a7e14dcfSSatish Balay /* be rejected! */ 876*a7e14dcfSSatish Balay tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d); 877*a7e14dcfSSatish Balay } 878*a7e14dcfSSatish Balay else { 879*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(f_full)) { 880*a7e14dcfSSatish Balay tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d); 881*a7e14dcfSSatish Balay } 882*a7e14dcfSSatish Balay else { 883*a7e14dcfSSatish Balay /* Compute and actual reduction */ 884*a7e14dcfSSatish Balay actred = fold - f_full; 885*a7e14dcfSSatish Balay prered = -prered; 886*a7e14dcfSSatish Balay if ((PetscAbsScalar(actred) <= nlsP->epsilon) && 887*a7e14dcfSSatish Balay (PetscAbsScalar(prered) <= nlsP->epsilon)) { 888*a7e14dcfSSatish Balay kappa = 1.0; 889*a7e14dcfSSatish Balay } 890*a7e14dcfSSatish Balay else { 891*a7e14dcfSSatish Balay kappa = actred / prered; 892*a7e14dcfSSatish Balay } 893*a7e14dcfSSatish Balay 894*a7e14dcfSSatish Balay /* Accept of reject the step and update radius */ 895*a7e14dcfSSatish Balay if (kappa < nlsP->eta1) { 896*a7e14dcfSSatish Balay /* Very bad step */ 897*a7e14dcfSSatish Balay tao->trust = nlsP->alpha1 * PetscMin(tao->trust, norm_d); 898*a7e14dcfSSatish Balay } 899*a7e14dcfSSatish Balay else if (kappa < nlsP->eta2) { 900*a7e14dcfSSatish Balay /* Marginal bad step */ 901*a7e14dcfSSatish Balay tao->trust = nlsP->alpha2 * PetscMin(tao->trust, norm_d); 902*a7e14dcfSSatish Balay } 903*a7e14dcfSSatish Balay else if (kappa < nlsP->eta3) { 904*a7e14dcfSSatish Balay /* Reasonable step */ 905*a7e14dcfSSatish Balay if (nlsP->alpha3 < 1.0) { 906*a7e14dcfSSatish Balay tao->trust = nlsP->alpha3 * PetscMin(norm_d, tao->trust); 907*a7e14dcfSSatish Balay } 908*a7e14dcfSSatish Balay else if (nlsP->alpha3 > 1.0) { 909*a7e14dcfSSatish Balay tao->trust = PetscMax(nlsP->alpha3 * norm_d, tao->trust); 910*a7e14dcfSSatish Balay } 911*a7e14dcfSSatish Balay } 912*a7e14dcfSSatish Balay else if (kappa < nlsP->eta4) { 913*a7e14dcfSSatish Balay /* Good step */ 914*a7e14dcfSSatish Balay tao->trust = PetscMax(nlsP->alpha4 * norm_d, tao->trust); 915*a7e14dcfSSatish Balay } 916*a7e14dcfSSatish Balay else { 917*a7e14dcfSSatish Balay /* Very good step */ 918*a7e14dcfSSatish Balay tao->trust = PetscMax(nlsP->alpha5 * norm_d, tao->trust); 919*a7e14dcfSSatish Balay } 920*a7e14dcfSSatish Balay } 921*a7e14dcfSSatish Balay } 922*a7e14dcfSSatish Balay } 923*a7e14dcfSSatish Balay else { 924*a7e14dcfSSatish Balay /* Newton step was not good; reduce the radius */ 925*a7e14dcfSSatish Balay tao->trust = nlsP->alpha1 * PetscMin(norm_d, tao->trust); 926*a7e14dcfSSatish Balay } 927*a7e14dcfSSatish Balay break; 928*a7e14dcfSSatish Balay 929*a7e14dcfSSatish Balay default: 930*a7e14dcfSSatish Balay if (stepType == NLS_NEWTON) { 931*a7e14dcfSSatish Balay 932*a7e14dcfSSatish Balay if (NLS_KSP_STCG == nlsP->ksp_type) { 933*a7e14dcfSSatish Balay ierr = KSPSTCGGetObjFcn(tao->ksp,&prered); 934*a7e14dcfSSatish Balay } else if (NLS_KSP_NASH == nlsP->ksp_type) { 935*a7e14dcfSSatish Balay ierr = KSPNASHGetObjFcn(tao->ksp,&prered); 936*a7e14dcfSSatish Balay } else { 937*a7e14dcfSSatish Balay ierr = KSPGLTRGetObjFcn(tao->ksp,&prered); CHKERRQ(ierr); 938*a7e14dcfSSatish Balay } 939*a7e14dcfSSatish Balay if (prered >= 0.0) { 940*a7e14dcfSSatish Balay /* The predicted reduction has the wrong sign. This cannot */ 941*a7e14dcfSSatish Balay /* happen in infinite precision arithmetic. Step should */ 942*a7e14dcfSSatish Balay /* be rejected! */ 943*a7e14dcfSSatish Balay tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d); 944*a7e14dcfSSatish Balay } 945*a7e14dcfSSatish Balay else { 946*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(f_full)) { 947*a7e14dcfSSatish Balay tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d); 948*a7e14dcfSSatish Balay } 949*a7e14dcfSSatish Balay else { 950*a7e14dcfSSatish Balay actred = fold - f_full; 951*a7e14dcfSSatish Balay prered = -prered; 952*a7e14dcfSSatish Balay if ((PetscAbsScalar(actred) <= nlsP->epsilon) && 953*a7e14dcfSSatish Balay (PetscAbsScalar(prered) <= nlsP->epsilon)) { 954*a7e14dcfSSatish Balay kappa = 1.0; 955*a7e14dcfSSatish Balay } 956*a7e14dcfSSatish Balay else { 957*a7e14dcfSSatish Balay kappa = actred / prered; 958*a7e14dcfSSatish Balay } 959*a7e14dcfSSatish Balay 960*a7e14dcfSSatish Balay tau_1 = nlsP->theta * gdx / (nlsP->theta * gdx - (1.0 - nlsP->theta) * prered + actred); 961*a7e14dcfSSatish Balay tau_2 = nlsP->theta * gdx / (nlsP->theta * gdx + (1.0 + nlsP->theta) * prered - actred); 962*a7e14dcfSSatish Balay tau_min = PetscMin(tau_1, tau_2); 963*a7e14dcfSSatish Balay tau_max = PetscMax(tau_1, tau_2); 964*a7e14dcfSSatish Balay 965*a7e14dcfSSatish Balay if (kappa >= 1.0 - nlsP->mu1) { 966*a7e14dcfSSatish Balay /* Great agreement */ 967*a7e14dcfSSatish Balay if (tau_max < 1.0) { 968*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, nlsP->gamma3 * norm_d); 969*a7e14dcfSSatish Balay } 970*a7e14dcfSSatish Balay else if (tau_max > nlsP->gamma4) { 971*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, nlsP->gamma4 * norm_d); 972*a7e14dcfSSatish Balay } 973*a7e14dcfSSatish Balay else { 974*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tau_max * norm_d); 975*a7e14dcfSSatish Balay } 976*a7e14dcfSSatish Balay } 977*a7e14dcfSSatish Balay else if (kappa >= 1.0 - nlsP->mu2) { 978*a7e14dcfSSatish Balay /* Good agreement */ 979*a7e14dcfSSatish Balay 980*a7e14dcfSSatish Balay if (tau_max < nlsP->gamma2) { 981*a7e14dcfSSatish Balay tao->trust = nlsP->gamma2 * PetscMin(tao->trust, norm_d); 982*a7e14dcfSSatish Balay } 983*a7e14dcfSSatish Balay else if (tau_max > nlsP->gamma3) { 984*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, nlsP->gamma3 * norm_d); 985*a7e14dcfSSatish Balay } 986*a7e14dcfSSatish Balay else if (tau_max < 1.0) { 987*a7e14dcfSSatish Balay tao->trust = tau_max * PetscMin(tao->trust, norm_d); 988*a7e14dcfSSatish Balay } 989*a7e14dcfSSatish Balay else { 990*a7e14dcfSSatish Balay tao->trust = PetscMax(tao->trust, tau_max * norm_d); 991*a7e14dcfSSatish Balay } 992*a7e14dcfSSatish Balay } 993*a7e14dcfSSatish Balay else { 994*a7e14dcfSSatish Balay /* Not good agreement */ 995*a7e14dcfSSatish Balay if (tau_min > 1.0) { 996*a7e14dcfSSatish Balay tao->trust = nlsP->gamma2 * PetscMin(tao->trust, norm_d); 997*a7e14dcfSSatish Balay } 998*a7e14dcfSSatish Balay else if (tau_max < nlsP->gamma1) { 999*a7e14dcfSSatish Balay tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d); 1000*a7e14dcfSSatish Balay } 1001*a7e14dcfSSatish Balay else if ((tau_min < nlsP->gamma1) && (tau_max >= 1.0)) { 1002*a7e14dcfSSatish Balay tao->trust = nlsP->gamma1 * PetscMin(tao->trust, norm_d); 1003*a7e14dcfSSatish Balay } 1004*a7e14dcfSSatish Balay else if ((tau_1 >= nlsP->gamma1) && (tau_1 < 1.0) && 1005*a7e14dcfSSatish Balay ((tau_2 < nlsP->gamma1) || (tau_2 >= 1.0))) { 1006*a7e14dcfSSatish Balay tao->trust = tau_1 * PetscMin(tao->trust, norm_d); 1007*a7e14dcfSSatish Balay } 1008*a7e14dcfSSatish Balay else if ((tau_2 >= nlsP->gamma1) && (tau_2 < 1.0) && 1009*a7e14dcfSSatish Balay ((tau_1 < nlsP->gamma1) || (tau_2 >= 1.0))) { 1010*a7e14dcfSSatish Balay tao->trust = tau_2 * PetscMin(tao->trust, norm_d); 1011*a7e14dcfSSatish Balay } 1012*a7e14dcfSSatish Balay else { 1013*a7e14dcfSSatish Balay tao->trust = tau_max * PetscMin(tao->trust, norm_d); 1014*a7e14dcfSSatish Balay } 1015*a7e14dcfSSatish Balay } 1016*a7e14dcfSSatish Balay } 1017*a7e14dcfSSatish Balay } 1018*a7e14dcfSSatish Balay } 1019*a7e14dcfSSatish Balay else { 1020*a7e14dcfSSatish Balay /* Newton step was not good; reduce the radius */ 1021*a7e14dcfSSatish Balay tao->trust = nlsP->gamma1 * PetscMin(norm_d, tao->trust); 1022*a7e14dcfSSatish Balay } 1023*a7e14dcfSSatish Balay break; 1024*a7e14dcfSSatish Balay } 1025*a7e14dcfSSatish Balay 1026*a7e14dcfSSatish Balay /* The radius may have been increased; modify if it is too large */ 1027*a7e14dcfSSatish Balay tao->trust = PetscMin(tao->trust, nlsP->max_radius); 1028*a7e14dcfSSatish Balay } 1029*a7e14dcfSSatish Balay 1030*a7e14dcfSSatish Balay /* Check for termination */ 1031*a7e14dcfSSatish Balay ierr = VecNorm(tao->gradient, NORM_2, &gnorm); CHKERRQ(ierr); 1032*a7e14dcfSSatish Balay if (PetscIsInfOrNanReal(f) || PetscIsInfOrNanReal(gnorm)) { 1033*a7e14dcfSSatish Balay SETERRQ(PETSC_COMM_SELF,1,"User provided compute function generated Not-a-Number"); 1034*a7e14dcfSSatish Balay } 1035*a7e14dcfSSatish Balay needH = 1; 1036*a7e14dcfSSatish Balay 1037*a7e14dcfSSatish Balay ierr = TaoMonitor(tao, iter, f, gnorm, 0.0, step, &reason); CHKERRQ(ierr); 1038*a7e14dcfSSatish Balay } 1039*a7e14dcfSSatish Balay PetscFunctionReturn(0); 1040*a7e14dcfSSatish Balay } 1041*a7e14dcfSSatish Balay 1042*a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 1043*a7e14dcfSSatish Balay #undef __FUNCT__ 1044*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetUp_NLS" 1045*a7e14dcfSSatish Balay static PetscErrorCode TaoSetUp_NLS(TaoSolver tao) 1046*a7e14dcfSSatish Balay { 1047*a7e14dcfSSatish Balay TAO_NLS *nlsP = (TAO_NLS *)tao->data; 1048*a7e14dcfSSatish Balay PetscErrorCode ierr; 1049*a7e14dcfSSatish Balay 1050*a7e14dcfSSatish Balay PetscFunctionBegin; 1051*a7e14dcfSSatish Balay 1052*a7e14dcfSSatish Balay if (!tao->gradient) {ierr = VecDuplicate(tao->solution,&tao->gradient); CHKERRQ(ierr); } 1053*a7e14dcfSSatish Balay if (!tao->stepdirection) {ierr = VecDuplicate(tao->solution,&tao->stepdirection); CHKERRQ(ierr); } 1054*a7e14dcfSSatish Balay if (!nlsP->W) {ierr = VecDuplicate(tao->solution,&nlsP->W); CHKERRQ(ierr); } 1055*a7e14dcfSSatish Balay if (!nlsP->D) {ierr = VecDuplicate(tao->solution,&nlsP->D); CHKERRQ(ierr); } 1056*a7e14dcfSSatish Balay if (!nlsP->Xold) {ierr = VecDuplicate(tao->solution,&nlsP->Xold); CHKERRQ(ierr); } 1057*a7e14dcfSSatish Balay if (!nlsP->Gold) {ierr = VecDuplicate(tao->solution,&nlsP->Gold); CHKERRQ(ierr); } 1058*a7e14dcfSSatish Balay 1059*a7e14dcfSSatish Balay nlsP->Diag = 0; 1060*a7e14dcfSSatish Balay nlsP->M = 0; 1061*a7e14dcfSSatish Balay 1062*a7e14dcfSSatish Balay PetscFunctionReturn(0); 1063*a7e14dcfSSatish Balay } 1064*a7e14dcfSSatish Balay 1065*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 1066*a7e14dcfSSatish Balay #undef __FUNCT__ 1067*a7e14dcfSSatish Balay #define __FUNCT__ "TaoDestroy_NLS" 1068*a7e14dcfSSatish Balay static PetscErrorCode TaoDestroy_NLS(TaoSolver tao) 1069*a7e14dcfSSatish Balay { 1070*a7e14dcfSSatish Balay TAO_NLS *nlsP = (TAO_NLS *)tao->data; 1071*a7e14dcfSSatish Balay PetscErrorCode ierr; 1072*a7e14dcfSSatish Balay 1073*a7e14dcfSSatish Balay PetscFunctionBegin; 1074*a7e14dcfSSatish Balay if (tao->setupcalled) { 1075*a7e14dcfSSatish Balay ierr = VecDestroy(&nlsP->D); CHKERRQ(ierr); 1076*a7e14dcfSSatish Balay ierr = VecDestroy(&nlsP->W); CHKERRQ(ierr); 1077*a7e14dcfSSatish Balay ierr = VecDestroy(&nlsP->Xold); CHKERRQ(ierr); 1078*a7e14dcfSSatish Balay ierr = VecDestroy(&nlsP->Gold); CHKERRQ(ierr); 1079*a7e14dcfSSatish Balay } 1080*a7e14dcfSSatish Balay if (nlsP->Diag) { 1081*a7e14dcfSSatish Balay ierr = VecDestroy(&nlsP->Diag); CHKERRQ(ierr); 1082*a7e14dcfSSatish Balay } 1083*a7e14dcfSSatish Balay if (nlsP->M) { 1084*a7e14dcfSSatish Balay ierr = MatDestroy(&nlsP->M); CHKERRQ(ierr); 1085*a7e14dcfSSatish Balay } 1086*a7e14dcfSSatish Balay 1087*a7e14dcfSSatish Balay ierr = PetscFree(tao->data); CHKERRQ(ierr); 1088*a7e14dcfSSatish Balay tao->data = PETSC_NULL; 1089*a7e14dcfSSatish Balay 1090*a7e14dcfSSatish Balay PetscFunctionReturn(0); 1091*a7e14dcfSSatish Balay } 1092*a7e14dcfSSatish Balay 1093*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 1094*a7e14dcfSSatish Balay #undef __FUNCT__ 1095*a7e14dcfSSatish Balay #define __FUNCT__ "TaoSetFromOptions_NLS" 1096*a7e14dcfSSatish Balay static PetscErrorCode TaoSetFromOptions_NLS(TaoSolver tao) 1097*a7e14dcfSSatish Balay { 1098*a7e14dcfSSatish Balay TAO_NLS *nlsP = (TAO_NLS *)tao->data; 1099*a7e14dcfSSatish Balay PetscErrorCode ierr; 1100*a7e14dcfSSatish Balay 1101*a7e14dcfSSatish Balay PetscFunctionBegin; 1102*a7e14dcfSSatish Balay ierr = PetscOptionsHead("Newton line search method for unconstrained optimization"); CHKERRQ(ierr); 1103*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_nls_ksp_type", "ksp type", "", NLS_KSP, NLS_KSP_TYPES, NLS_KSP[nlsP->ksp_type], &nlsP->ksp_type, 0); CHKERRQ(ierr); 1104*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_nls_pc_type", "pc type", "", NLS_PC, NLS_PC_TYPES, NLS_PC[nlsP->pc_type], &nlsP->pc_type, 0); CHKERRQ(ierr); 1105*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_nls_bfgs_scale_type", "bfgs scale type", "", BFGS_SCALE, BFGS_SCALE_TYPES, BFGS_SCALE[nlsP->bfgs_scale_type], &nlsP->bfgs_scale_type, 0); CHKERRQ(ierr); 1106*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_nls_init_type", "radius initialization type", "", NLS_INIT, NLS_INIT_TYPES, NLS_INIT[nlsP->init_type], &nlsP->init_type, 0); CHKERRQ(ierr); 1107*a7e14dcfSSatish Balay ierr = PetscOptionsEList("-tao_nls_update_type", "radius update type", "", NLS_UPDATE, NLS_UPDATE_TYPES, NLS_UPDATE[nlsP->update_type], &nlsP->update_type, 0); CHKERRQ(ierr); 1108*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_sval", "perturbation starting value", "", nlsP->sval, &nlsP->sval, 0); CHKERRQ(ierr); 1109*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_imin", "minimum initial perturbation", "", nlsP->imin, &nlsP->imin, 0); CHKERRQ(ierr); 1110*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_imax", "maximum initial perturbation", "", nlsP->imax, &nlsP->imax, 0); CHKERRQ(ierr); 1111*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_imfac", "initial merit factor", "", nlsP->imfac, &nlsP->imfac, 0); CHKERRQ(ierr); 1112*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_pmin", "minimum perturbation", "", nlsP->pmin, &nlsP->pmin, 0); CHKERRQ(ierr); 1113*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_pmax", "maximum perturbation", "", nlsP->pmax, &nlsP->pmax, 0); CHKERRQ(ierr); 1114*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_pgfac", "growth factor", "", nlsP->pgfac, &nlsP->pgfac, 0); CHKERRQ(ierr); 1115*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_psfac", "shrink factor", "", nlsP->psfac, &nlsP->psfac, 0); CHKERRQ(ierr); 1116*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_pmgfac", "merit growth factor", "", nlsP->pmgfac, &nlsP->pmgfac, 0); CHKERRQ(ierr); 1117*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_pmsfac", "merit shrink factor", "", nlsP->pmsfac, &nlsP->pmsfac, 0); CHKERRQ(ierr); 1118*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_eta1", "poor steplength; reduce radius", "", nlsP->eta1, &nlsP->eta1, 0); CHKERRQ(ierr); 1119*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_eta2", "reasonable steplength; leave radius alone", "", nlsP->eta2, &nlsP->eta2, 0); CHKERRQ(ierr); 1120*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_eta3", "good steplength; increase radius", "", nlsP->eta3, &nlsP->eta3, 0); CHKERRQ(ierr); 1121*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_eta4", "excellent steplength; greatly increase radius", "", nlsP->eta4, &nlsP->eta4, 0); CHKERRQ(ierr); 1122*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_alpha1", "", "", nlsP->alpha1, &nlsP->alpha1, 0); CHKERRQ(ierr); 1123*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_alpha2", "", "", nlsP->alpha2, &nlsP->alpha2, 0); CHKERRQ(ierr); 1124*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_alpha3", "", "", nlsP->alpha3, &nlsP->alpha3, 0); CHKERRQ(ierr); 1125*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_alpha4", "", "", nlsP->alpha4, &nlsP->alpha4, 0); CHKERRQ(ierr); 1126*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_alpha5", "", "", nlsP->alpha5, &nlsP->alpha5, 0); CHKERRQ(ierr); 1127*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_nu1", "poor steplength; reduce radius", "", nlsP->nu1, &nlsP->nu1, 0); CHKERRQ(ierr); 1128*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_nu2", "reasonable steplength; leave radius alone", "", nlsP->nu2, &nlsP->nu2, 0); CHKERRQ(ierr); 1129*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_nu3", "good steplength; increase radius", "", nlsP->nu3, &nlsP->nu3, 0); CHKERRQ(ierr); 1130*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_nu4", "excellent steplength; greatly increase radius", "", nlsP->nu4, &nlsP->nu4, 0); CHKERRQ(ierr); 1131*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_omega1", "", "", nlsP->omega1, &nlsP->omega1, 0); CHKERRQ(ierr); 1132*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_omega2", "", "", nlsP->omega2, &nlsP->omega2, 0); CHKERRQ(ierr); 1133*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_omega3", "", "", nlsP->omega3, &nlsP->omega3, 0); CHKERRQ(ierr); 1134*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_omega4", "", "", nlsP->omega4, &nlsP->omega4, 0); CHKERRQ(ierr); 1135*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_omega5", "", "", nlsP->omega5, &nlsP->omega5, 0); CHKERRQ(ierr); 1136*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_mu1_i", "", "", nlsP->mu1_i, &nlsP->mu1_i, 0); CHKERRQ(ierr); 1137*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_mu2_i", "", "", nlsP->mu2_i, &nlsP->mu2_i, 0); CHKERRQ(ierr); 1138*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma1_i", "", "", nlsP->gamma1_i, &nlsP->gamma1_i, 0); CHKERRQ(ierr); 1139*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma2_i", "", "", nlsP->gamma2_i, &nlsP->gamma2_i, 0); CHKERRQ(ierr); 1140*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma3_i", "", "", nlsP->gamma3_i, &nlsP->gamma3_i, 0); CHKERRQ(ierr); 1141*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma4_i", "", "", nlsP->gamma4_i, &nlsP->gamma4_i, 0); CHKERRQ(ierr); 1142*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_theta_i", "", "", nlsP->theta_i, &nlsP->theta_i, 0); CHKERRQ(ierr); 1143*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_mu1", "", "", nlsP->mu1, &nlsP->mu1, 0); CHKERRQ(ierr); 1144*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_mu2", "", "", nlsP->mu2, &nlsP->mu2, 0); CHKERRQ(ierr); 1145*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma1", "", "", nlsP->gamma1, &nlsP->gamma1, 0); CHKERRQ(ierr); 1146*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma2", "", "", nlsP->gamma2, &nlsP->gamma2, 0); CHKERRQ(ierr); 1147*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma3", "", "", nlsP->gamma3, &nlsP->gamma3, 0); CHKERRQ(ierr); 1148*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_gamma4", "", "", nlsP->gamma4, &nlsP->gamma4, 0); CHKERRQ(ierr); 1149*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_theta", "", "", nlsP->theta, &nlsP->theta, 0); CHKERRQ(ierr); 1150*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_min_radius", "lower bound on initial radius", "", nlsP->min_radius, &nlsP->min_radius, 0); CHKERRQ(ierr); 1151*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_max_radius", "upper bound on radius", "", nlsP->max_radius, &nlsP->max_radius, 0); CHKERRQ(ierr); 1152*a7e14dcfSSatish Balay ierr = PetscOptionsReal("-tao_nls_epsilon", "tolerance used when computing actual and predicted reduction", "", nlsP->epsilon, &nlsP->epsilon, 0); CHKERRQ(ierr); 1153*a7e14dcfSSatish Balay ierr = PetscOptionsTail(); CHKERRQ(ierr); 1154*a7e14dcfSSatish Balay ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr); 1155*a7e14dcfSSatish Balay ierr = KSPSetFromOptions(tao->ksp); CHKERRQ(ierr); 1156*a7e14dcfSSatish Balay PetscFunctionReturn(0); 1157*a7e14dcfSSatish Balay } 1158*a7e14dcfSSatish Balay 1159*a7e14dcfSSatish Balay 1160*a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 1161*a7e14dcfSSatish Balay #undef __FUNCT__ 1162*a7e14dcfSSatish Balay #define __FUNCT__ "TaoView_NLS" 1163*a7e14dcfSSatish Balay static PetscErrorCode TaoView_NLS(TaoSolver tao, PetscViewer viewer) 1164*a7e14dcfSSatish Balay { 1165*a7e14dcfSSatish Balay TAO_NLS *nlsP = (TAO_NLS *)tao->data; 1166*a7e14dcfSSatish Balay PetscInt nrejects; 1167*a7e14dcfSSatish Balay PetscBool isascii; 1168*a7e14dcfSSatish Balay PetscErrorCode ierr; 1169*a7e14dcfSSatish Balay 1170*a7e14dcfSSatish Balay PetscFunctionBegin; 1171*a7e14dcfSSatish Balay 1172*a7e14dcfSSatish Balay ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 1173*a7e14dcfSSatish Balay if (isascii) { 1174*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPushTab(viewer); CHKERRQ(ierr); 1175*a7e14dcfSSatish Balay if (NLS_PC_BFGS == nlsP->pc_type && nlsP->M) { 1176*a7e14dcfSSatish Balay ierr = MatLMVMGetRejects(nlsP->M,&nrejects); CHKERRQ(ierr); 1177*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "Rejected matrix updates: %D\n",nrejects); CHKERRQ(ierr); 1178*a7e14dcfSSatish Balay } 1179*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "Newton steps: %D\n", nlsP->newt); CHKERRQ(ierr); 1180*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "BFGS steps: %D\n", nlsP->bfgs); CHKERRQ(ierr); 1181*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "Scaled gradient steps: %D\n", nlsP->sgrad); CHKERRQ(ierr); 1182*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "Gradient steps: %D\n", nlsP->grad); CHKERRQ(ierr); 1183*a7e14dcfSSatish Balay 1184*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "nls ksp atol: %D\n", nlsP->ksp_atol); CHKERRQ(ierr); 1185*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "nls ksp rtol: %D\n", nlsP->ksp_rtol); CHKERRQ(ierr); 1186*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "nls ksp ctol: %D\n", nlsP->ksp_ctol); CHKERRQ(ierr); 1187*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "nls ksp negc: %D\n", nlsP->ksp_negc); CHKERRQ(ierr); 1188*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "nls ksp dtol: %D\n", nlsP->ksp_dtol); CHKERRQ(ierr); 1189*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "nls ksp iter: %D\n", nlsP->ksp_iter); CHKERRQ(ierr); 1190*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPrintf(viewer, "nls ksp othr: %D\n", nlsP->ksp_othr); CHKERRQ(ierr); 1191*a7e14dcfSSatish Balay ierr = PetscViewerASCIIPopTab(viewer); CHKERRQ(ierr); 1192*a7e14dcfSSatish Balay } else { 1193*a7e14dcfSSatish Balay SETERRQ1(((PetscObject)tao)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for TAO NLS",((PetscObject)viewer)->type_name); 1194*a7e14dcfSSatish Balay } 1195*a7e14dcfSSatish Balay PetscFunctionReturn(0); 1196*a7e14dcfSSatish Balay } 1197*a7e14dcfSSatish Balay 1198*a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 1199*a7e14dcfSSatish Balay EXTERN_C_BEGIN 1200*a7e14dcfSSatish Balay #undef __FUNCT__ 1201*a7e14dcfSSatish Balay #define __FUNCT__ "TaoCreate_NLS" 1202*a7e14dcfSSatish Balay PetscErrorCode TaoCreate_NLS(TaoSolver tao) 1203*a7e14dcfSSatish Balay { 1204*a7e14dcfSSatish Balay TAO_NLS *nlsP; 1205*a7e14dcfSSatish Balay const char *morethuente_type = TAOLINESEARCH_MT; 1206*a7e14dcfSSatish Balay PetscErrorCode ierr; 1207*a7e14dcfSSatish Balay 1208*a7e14dcfSSatish Balay PetscFunctionBegin; 1209*a7e14dcfSSatish Balay ierr = PetscNewLog(tao,TAO_NLS,&nlsP); CHKERRQ(ierr); 1210*a7e14dcfSSatish Balay 1211*a7e14dcfSSatish Balay tao->ops->setup = TaoSetUp_NLS; 1212*a7e14dcfSSatish Balay tao->ops->solve = TaoSolve_NLS; 1213*a7e14dcfSSatish Balay tao->ops->view = TaoView_NLS; 1214*a7e14dcfSSatish Balay tao->ops->setfromoptions = TaoSetFromOptions_NLS; 1215*a7e14dcfSSatish Balay tao->ops->destroy = TaoDestroy_NLS; 1216*a7e14dcfSSatish Balay 1217*a7e14dcfSSatish Balay tao->max_it = 50; 1218*a7e14dcfSSatish Balay tao->fatol = 1e-10; 1219*a7e14dcfSSatish Balay tao->frtol = 1e-10; 1220*a7e14dcfSSatish Balay tao->data = (void*)nlsP; 1221*a7e14dcfSSatish Balay tao->trust0 = 100.0; 1222*a7e14dcfSSatish Balay 1223*a7e14dcfSSatish Balay nlsP->sval = 0.0; 1224*a7e14dcfSSatish Balay nlsP->imin = 1.0e-4; 1225*a7e14dcfSSatish Balay nlsP->imax = 1.0e+2; 1226*a7e14dcfSSatish Balay nlsP->imfac = 1.0e-1; 1227*a7e14dcfSSatish Balay 1228*a7e14dcfSSatish Balay nlsP->pmin = 1.0e-12; 1229*a7e14dcfSSatish Balay nlsP->pmax = 1.0e+2; 1230*a7e14dcfSSatish Balay nlsP->pgfac = 1.0e+1; 1231*a7e14dcfSSatish Balay nlsP->psfac = 4.0e-1; 1232*a7e14dcfSSatish Balay nlsP->pmgfac = 1.0e-1; 1233*a7e14dcfSSatish Balay nlsP->pmsfac = 1.0e-1; 1234*a7e14dcfSSatish Balay 1235*a7e14dcfSSatish Balay /* Default values for trust-region radius update based on steplength */ 1236*a7e14dcfSSatish Balay nlsP->nu1 = 0.25; 1237*a7e14dcfSSatish Balay nlsP->nu2 = 0.50; 1238*a7e14dcfSSatish Balay nlsP->nu3 = 1.00; 1239*a7e14dcfSSatish Balay nlsP->nu4 = 1.25; 1240*a7e14dcfSSatish Balay 1241*a7e14dcfSSatish Balay nlsP->omega1 = 0.25; 1242*a7e14dcfSSatish Balay nlsP->omega2 = 0.50; 1243*a7e14dcfSSatish Balay nlsP->omega3 = 1.00; 1244*a7e14dcfSSatish Balay nlsP->omega4 = 2.00; 1245*a7e14dcfSSatish Balay nlsP->omega5 = 4.00; 1246*a7e14dcfSSatish Balay 1247*a7e14dcfSSatish Balay /* Default values for trust-region radius update based on reduction */ 1248*a7e14dcfSSatish Balay nlsP->eta1 = 1.0e-4; 1249*a7e14dcfSSatish Balay nlsP->eta2 = 0.25; 1250*a7e14dcfSSatish Balay nlsP->eta3 = 0.50; 1251*a7e14dcfSSatish Balay nlsP->eta4 = 0.90; 1252*a7e14dcfSSatish Balay 1253*a7e14dcfSSatish Balay nlsP->alpha1 = 0.25; 1254*a7e14dcfSSatish Balay nlsP->alpha2 = 0.50; 1255*a7e14dcfSSatish Balay nlsP->alpha3 = 1.00; 1256*a7e14dcfSSatish Balay nlsP->alpha4 = 2.00; 1257*a7e14dcfSSatish Balay nlsP->alpha5 = 4.00; 1258*a7e14dcfSSatish Balay 1259*a7e14dcfSSatish Balay /* Default values for trust-region radius update based on interpolation */ 1260*a7e14dcfSSatish Balay nlsP->mu1 = 0.10; 1261*a7e14dcfSSatish Balay nlsP->mu2 = 0.50; 1262*a7e14dcfSSatish Balay 1263*a7e14dcfSSatish Balay nlsP->gamma1 = 0.25; 1264*a7e14dcfSSatish Balay nlsP->gamma2 = 0.50; 1265*a7e14dcfSSatish Balay nlsP->gamma3 = 2.00; 1266*a7e14dcfSSatish Balay nlsP->gamma4 = 4.00; 1267*a7e14dcfSSatish Balay 1268*a7e14dcfSSatish Balay nlsP->theta = 0.05; 1269*a7e14dcfSSatish Balay 1270*a7e14dcfSSatish Balay /* Default values for trust region initialization based on interpolation */ 1271*a7e14dcfSSatish Balay nlsP->mu1_i = 0.35; 1272*a7e14dcfSSatish Balay nlsP->mu2_i = 0.50; 1273*a7e14dcfSSatish Balay 1274*a7e14dcfSSatish Balay nlsP->gamma1_i = 0.0625; 1275*a7e14dcfSSatish Balay nlsP->gamma2_i = 0.5; 1276*a7e14dcfSSatish Balay nlsP->gamma3_i = 2.0; 1277*a7e14dcfSSatish Balay nlsP->gamma4_i = 5.0; 1278*a7e14dcfSSatish Balay 1279*a7e14dcfSSatish Balay nlsP->theta_i = 0.25; 1280*a7e14dcfSSatish Balay 1281*a7e14dcfSSatish Balay /* Remaining parameters */ 1282*a7e14dcfSSatish Balay nlsP->min_radius = 1.0e-10; 1283*a7e14dcfSSatish Balay nlsP->max_radius = 1.0e10; 1284*a7e14dcfSSatish Balay nlsP->epsilon = 1.0e-6; 1285*a7e14dcfSSatish Balay 1286*a7e14dcfSSatish Balay nlsP->ksp_type = NLS_KSP_STCG; 1287*a7e14dcfSSatish Balay nlsP->pc_type = NLS_PC_BFGS; 1288*a7e14dcfSSatish Balay nlsP->bfgs_scale_type = BFGS_SCALE_PHESS; 1289*a7e14dcfSSatish Balay nlsP->init_type = NLS_INIT_INTERPOLATION; 1290*a7e14dcfSSatish Balay nlsP->update_type = NLS_UPDATE_STEP; 1291*a7e14dcfSSatish Balay 1292*a7e14dcfSSatish Balay ierr = TaoLineSearchCreate(((PetscObject)tao)->comm,&tao->linesearch); CHKERRQ(ierr); 1293*a7e14dcfSSatish Balay ierr = TaoLineSearchSetType(tao->linesearch,morethuente_type); CHKERRQ(ierr); 1294*a7e14dcfSSatish Balay ierr = TaoLineSearchUseTaoSolverRoutines(tao->linesearch,tao); CHKERRQ(ierr); 1295*a7e14dcfSSatish Balay 1296*a7e14dcfSSatish Balay /* Set linear solver to default for symmetric matrices */ 1297*a7e14dcfSSatish Balay ierr = KSPCreate(((PetscObject)tao)->comm,&tao->ksp); CHKERRQ(ierr); 1298*a7e14dcfSSatish Balay 1299*a7e14dcfSSatish Balay PetscFunctionReturn(0); 1300*a7e14dcfSSatish Balay } 1301*a7e14dcfSSatish Balay 1302*a7e14dcfSSatish Balay EXTERN_C_END 1303*a7e14dcfSSatish Balay 1304*a7e14dcfSSatish Balay 1305*a7e14dcfSSatish Balay 1306*a7e14dcfSSatish Balay 1307*a7e14dcfSSatish Balay #undef __FUNCT__ 1308*a7e14dcfSSatish Balay #define __FUNCT__ "MatLMVMSolveShell" 1309*a7e14dcfSSatish Balay static PetscErrorCode MatLMVMSolveShell(PC pc, Vec b, Vec x) 1310*a7e14dcfSSatish Balay { 1311*a7e14dcfSSatish Balay PetscErrorCode ierr; 1312*a7e14dcfSSatish Balay Mat M; 1313*a7e14dcfSSatish Balay PetscFunctionBegin; 1314*a7e14dcfSSatish Balay PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1315*a7e14dcfSSatish Balay PetscValidHeaderSpecific(b,VEC_CLASSID,2); 1316*a7e14dcfSSatish Balay PetscValidHeaderSpecific(x,VEC_CLASSID,3); 1317*a7e14dcfSSatish Balay ierr = PCShellGetContext(pc,(void**)&M); CHKERRQ(ierr); 1318*a7e14dcfSSatish Balay ierr = MatLMVMSolve(M, b, x); CHKERRQ(ierr); 1319*a7e14dcfSSatish Balay PetscFunctionReturn(0); 1320*a7e14dcfSSatish Balay } 1321