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