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