1 #include <petsctaolinesearch.h> 2 #include <../src/tao/bound/impls/bncg/bncg.h> 3 4 #define CG_FletcherReeves 0 5 #define CG_PolakRibiere 1 6 #define CG_PolakRibierePlus 2 7 #define CG_HestenesStiefel 3 8 #define CG_DaiYuan 4 9 #define CG_Types 5 10 11 static const char *CG_Table[64] = {"fr", "pr", "prp", "hs", "dy"}; 12 13 #define CG_AS_NONE 0 14 #define CG_AS_BERTSEKAS 1 15 #define CG_AS_SIZE 2 16 17 static const char *CG_AS_TYPE[64] = {"none", "bertsekas"}; 18 19 PetscErrorCode TaoBNCGSetRecycleFlag(Tao tao, PetscBool recycle) 20 { 21 TAO_BNCG *cg = (TAO_BNCG*)tao->data; 22 23 PetscFunctionBegin; 24 cg->recycle = recycle; 25 PetscFunctionReturn(0); 26 } 27 28 PetscErrorCode TaoBNCGEstimateActiveSet(Tao tao, PetscInt asType) 29 { 30 PetscErrorCode ierr; 31 TAO_BNCG *cg = (TAO_BNCG *)tao->data; 32 33 PetscFunctionBegin; 34 ierr = ISDestroy(&cg->inactive_old);CHKERRQ(ierr); 35 if (cg->inactive_idx) { 36 ierr = ISDuplicate(cg->inactive_idx, &cg->inactive_old);CHKERRQ(ierr); 37 ierr = ISCopy(cg->inactive_idx, cg->inactive_old);CHKERRQ(ierr); 38 } 39 switch (asType) { 40 case CG_AS_NONE: 41 ierr = ISDestroy(&cg->inactive_idx);CHKERRQ(ierr); 42 ierr = VecWhichInactive(tao->XL, tao->solution, cg->unprojected_gradient, tao->XU, PETSC_TRUE, &cg->inactive_idx);CHKERRQ(ierr); 43 ierr = ISDestroy(&cg->active_idx);CHKERRQ(ierr); 44 ierr = ISComplementVec(cg->inactive_idx, tao->solution, &cg->active_idx);CHKERRQ(ierr); 45 break; 46 47 case CG_AS_BERTSEKAS: 48 /* Use gradient descent to estimate the active set */ 49 ierr = VecCopy(cg->unprojected_gradient, cg->W);CHKERRQ(ierr); 50 ierr = VecScale(cg->W, -1.0);CHKERRQ(ierr); 51 ierr = TaoEstimateActiveBounds(tao->solution, tao->XL, tao->XU, cg->unprojected_gradient, cg->W, cg->work, cg->as_step, &cg->as_tol, 52 &cg->active_lower, &cg->active_upper, &cg->active_fixed, &cg->active_idx, &cg->inactive_idx);CHKERRQ(ierr); 53 break; 54 55 default: 56 break; 57 } 58 PetscFunctionReturn(0); 59 } 60 61 PetscErrorCode TaoBNCGBoundStep(Tao tao, PetscInt asType, Vec step) 62 { 63 PetscErrorCode ierr; 64 TAO_BNCG *cg = (TAO_BNCG *)tao->data; 65 66 PetscFunctionBegin; 67 switch (asType) { 68 case CG_AS_NONE: 69 ierr = VecISSet(step, cg->active_idx, 0.0);CHKERRQ(ierr); 70 break; 71 72 case CG_AS_BERTSEKAS: 73 ierr = TaoBoundStep(tao->solution, tao->XL, tao->XU, cg->active_lower, cg->active_upper, cg->active_fixed, 1.0, step);CHKERRQ(ierr); 74 break; 75 76 default: 77 break; 78 } 79 PetscFunctionReturn(0); 80 } 81 82 static PetscErrorCode TaoSolve_BNCG(Tao tao) 83 { 84 TAO_BNCG *cg = (TAO_BNCG*)tao->data; 85 PetscErrorCode ierr; 86 TaoLineSearchConvergedReason ls_status = TAOLINESEARCH_CONTINUE_ITERATING; 87 PetscReal step=1.0,gnorm,gnorm2,gd,ginner,beta,dnorm; 88 PetscReal gd_old,gnorm2_old,f_old,resnorm; 89 PetscBool cg_restart; 90 PetscInt nDiff; 91 92 PetscFunctionBegin; 93 /* Project the current point onto the feasible set */ 94 ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 95 ierr = TaoLineSearchSetVariableBounds(tao->linesearch,tao->XL,tao->XU);CHKERRQ(ierr); 96 97 /* Project the initial point onto the feasible region */ 98 ierr = TaoBoundSolution(tao->solution, tao->XL,tao->XU, 0.0, &nDiff, tao->solution);CHKERRQ(ierr); 99 100 if (nDiff > 0 || !cg->recycle) { 101 /* Solver is not being recycled so just compute the objective function and criteria */ 102 ierr = TaoComputeObjectiveAndGradient(tao, tao->solution, &cg->f, cg->unprojected_gradient);CHKERRQ(ierr); 103 } else { 104 /* We are recycling, so we have to compute ||g_old||^2 for use in the CG step calculation */ 105 ierr = VecDot(cg->G_old, cg->G_old, &gnorm2_old);CHKERRQ(ierr); 106 } 107 ierr = VecNorm(cg->unprojected_gradient,NORM_2,&gnorm);CHKERRQ(ierr); 108 if (PetscIsInfOrNanReal(cg->f) || PetscIsInfOrNanReal(gnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 109 110 /* Estimate the active set and compute the projected gradient */ 111 ierr = TaoBNCGEstimateActiveSet(tao, cg->as_type);CHKERRQ(ierr); 112 113 /* Project the gradient and calculate the norm */ 114 ierr = VecCopy(cg->unprojected_gradient, tao->gradient);CHKERRQ(ierr); 115 ierr = VecISSet(tao->gradient, cg->active_idx, 0.0);CHKERRQ(ierr); 116 ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 117 gnorm2 = gnorm*gnorm; 118 119 /* Convergence check */ 120 tao->niter = 0; 121 tao->reason = TAO_CONTINUE_ITERATING; 122 ierr = TaoLogConvergenceHistory(tao, cg->f, gnorm, 0.0, tao->ksp_its);CHKERRQ(ierr); 123 ierr = TaoMonitor(tao, tao->niter, cg->f, gnorm, 0.0, step);CHKERRQ(ierr); 124 ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 125 if (tao->reason != TAO_CONTINUE_ITERATING) PetscFunctionReturn(0); 126 127 /* Start optimization iterations */ 128 cg->ls_fails = cg->broken_ortho = cg->descent_error = 0; 129 cg->resets = -1; 130 while (tao->reason == TAO_CONTINUE_ITERATING) { 131 ++tao->niter; 132 133 /* Check restart conditions for using steepest descent */ 134 cg_restart = PETSC_FALSE; 135 ierr = VecDot(tao->gradient, cg->G_old, &ginner);CHKERRQ(ierr); 136 ierr = VecNorm(tao->stepdirection, NORM_2, &dnorm);CHKERRQ(ierr); 137 if (tao->niter == 1 && !cg->recycle && dnorm != 0.0) { 138 /* 1) First iteration, with recycle disabled, and a non-zero previous step */ 139 cg_restart = PETSC_TRUE; 140 } else if (PetscAbsScalar(ginner) >= cg->eta * gnorm2) { 141 /* 2) Gradients are far from orthogonal */ 142 cg_restart = PETSC_TRUE; 143 ++cg->broken_ortho; 144 } 145 146 /* Compute CG step */ 147 if (cg_restart) { 148 beta = 0.0; 149 ++cg->resets; 150 } else { 151 switch (cg->cg_type) { 152 case CG_FletcherReeves: 153 beta = gnorm2 / gnorm2_old; 154 break; 155 156 case CG_PolakRibiere: 157 beta = (gnorm2 - ginner) / gnorm2_old; 158 break; 159 160 case CG_PolakRibierePlus: 161 beta = PetscMax((gnorm2-ginner)/gnorm2_old, 0.0); 162 break; 163 164 case CG_HestenesStiefel: 165 ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 166 ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 167 beta = (gnorm2 - ginner) / (gd - gd_old); 168 break; 169 170 case CG_DaiYuan: 171 ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 172 ierr = VecDot(cg->G_old, tao->stepdirection, &gd_old);CHKERRQ(ierr); 173 beta = gnorm2 / (gd - gd_old); 174 break; 175 176 default: 177 beta = 0.0; 178 break; 179 } 180 } 181 182 /* Compute the direction d=-g + beta*d */ 183 ierr = VecAXPBY(tao->stepdirection, -1.0, beta, tao->gradient);CHKERRQ(ierr); 184 ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 185 186 /* Figure out which previously active variables became inactive this iteration */ 187 ierr = ISDestroy(&cg->new_inactives);CHKERRQ(ierr); 188 if (cg->inactive_idx && cg->inactive_old) { 189 ierr = ISDifference(cg->inactive_idx, cg->inactive_old, &cg->new_inactives);CHKERRQ(ierr); 190 } 191 192 /* Selectively reset the CG step those freshly inactive variables */ 193 if (cg->new_inactives) { 194 ierr = VecGetSubVector(tao->stepdirection, cg->new_inactives, &cg->inactive_step);CHKERRQ(ierr); 195 ierr = VecGetSubVector(cg->unprojected_gradient, cg->new_inactives, &cg->inactive_grad);CHKERRQ(ierr); 196 ierr = VecCopy(cg->inactive_grad, cg->inactive_step);CHKERRQ(ierr); 197 ierr = VecScale(cg->inactive_step, -1.0);CHKERRQ(ierr); 198 ierr = VecRestoreSubVector(tao->stepdirection, cg->new_inactives, &cg->inactive_step);CHKERRQ(ierr); 199 ierr = VecRestoreSubVector(cg->unprojected_gradient, cg->new_inactives, &cg->inactive_grad);CHKERRQ(ierr); 200 } 201 202 /* Verify that this is a descent direction */ 203 ierr = VecDot(tao->gradient, tao->stepdirection, &gd);CHKERRQ(ierr); 204 ierr = VecNorm(tao->stepdirection, NORM_2, &dnorm);CHKERRQ(ierr); 205 if (gd > -cg->rho*PetscPowReal(dnorm, cg->pow)) { 206 /* Not a descent direction, so we reset back to projected gradient descent */ 207 ierr = VecAXPBY(tao->stepdirection, -1.0, 0.0, tao->gradient);CHKERRQ(ierr); 208 ++cg->resets; 209 ++cg->descent_error; 210 } 211 212 /* Store solution and gradient info before it changes */ 213 ierr = VecCopy(tao->solution, cg->X_old);CHKERRQ(ierr); 214 ierr = VecCopy(tao->gradient, cg->G_old);CHKERRQ(ierr); 215 ierr = VecCopy(cg->unprojected_gradient, cg->unprojected_gradient_old);CHKERRQ(ierr); 216 gnorm2_old = gnorm2; 217 f_old = cg->f; 218 219 /* Perform bounded line search */ 220 ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &cg->f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr); 221 ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 222 223 /* Check linesearch failure */ 224 if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER) { 225 ++cg->ls_fails; 226 /* Restore previous point */ 227 gnorm2 = gnorm2_old; 228 cg->f = f_old; 229 ierr = VecCopy(cg->X_old, tao->solution);CHKERRQ(ierr); 230 ierr = VecCopy(cg->G_old, tao->gradient);CHKERRQ(ierr); 231 ierr = VecCopy(cg->unprojected_gradient_old, cg->unprojected_gradient);CHKERRQ(ierr); 232 233 /* Fall back on the gradient descent step */ 234 ierr = VecCopy(tao->gradient, tao->stepdirection);CHKERRQ(ierr); 235 ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); 236 ierr = TaoBNCGBoundStep(tao, cg->as_type, tao->stepdirection);CHKERRQ(ierr); 237 ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &cg->f, cg->unprojected_gradient, tao->stepdirection, &step, &ls_status);CHKERRQ(ierr); 238 ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); 239 240 if (ls_status != TAOLINESEARCH_SUCCESS && ls_status != TAOLINESEARCH_SUCCESS_USER){ 241 ++cg->ls_fails; 242 /* Restore previous point */ 243 gnorm2 = gnorm2_old; 244 cg->f = f_old; 245 ierr = VecCopy(cg->X_old, tao->solution);CHKERRQ(ierr); 246 ierr = VecCopy(cg->G_old, tao->gradient);CHKERRQ(ierr); 247 ierr = VecCopy(cg->unprojected_gradient_old, cg->unprojected_gradient);CHKERRQ(ierr); 248 249 /* Nothing left to do but fail out of the optimization */ 250 step = 0.0; 251 tao->reason = TAO_DIVERGED_LS_FAILURE; 252 } 253 } 254 255 if (tao->reason != TAO_DIVERGED_LS_FAILURE) { 256 /* Estimate the active set at the new solution */ 257 ierr = TaoBNCGEstimateActiveSet(tao, cg->as_type);CHKERRQ(ierr); 258 259 /* Compute the projected gradient and its norm */ 260 ierr = VecCopy(cg->unprojected_gradient, tao->gradient);CHKERRQ(ierr); 261 ierr = VecISSet(tao->gradient, cg->active_idx, 0.0);CHKERRQ(ierr); 262 ierr = VecNorm(tao->gradient,NORM_2,&gnorm);CHKERRQ(ierr); 263 gnorm2 = gnorm*gnorm; 264 } 265 266 /* Convergence test */ 267 ierr = VecFischer(tao->solution, cg->unprojected_gradient, tao->XL, tao->XU, cg->W);CHKERRQ(ierr); 268 ierr = VecNorm(cg->W, NORM_2, &resnorm);CHKERRQ(ierr); 269 if (PetscIsInfOrNanReal(resnorm)) SETERRQ(PETSC_COMM_SELF,1, "User provided compute function generated Inf or NaN"); 270 ierr = TaoLogConvergenceHistory(tao, cg->f, resnorm, 0.0, tao->ksp_its);CHKERRQ(ierr); 271 ierr = TaoMonitor(tao, tao->niter, cg->f, resnorm, 0.0, step);CHKERRQ(ierr); 272 ierr = (*tao->ops->convergencetest)(tao,tao->cnvP);CHKERRQ(ierr); 273 } 274 PetscFunctionReturn(0); 275 } 276 277 static PetscErrorCode TaoSetUp_BNCG(Tao tao) 278 { 279 TAO_BNCG *cg = (TAO_BNCG*)tao->data; 280 PetscErrorCode ierr; 281 282 PetscFunctionBegin; 283 if (!tao->gradient) { 284 ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr); 285 } 286 if (!tao->stepdirection) { 287 ierr = VecDuplicate(tao->solution,&tao->stepdirection);CHKERRQ(ierr); 288 } 289 if (!cg->W) { 290 ierr = VecDuplicate(tao->solution,&cg->W);CHKERRQ(ierr); 291 } 292 if (!cg->work) { 293 ierr = VecDuplicate(tao->solution,&cg->work);CHKERRQ(ierr); 294 } 295 if (!cg->X_old) { 296 ierr = VecDuplicate(tao->solution,&cg->X_old);CHKERRQ(ierr); 297 } 298 if (!cg->G_old) { 299 ierr = VecDuplicate(tao->gradient,&cg->G_old);CHKERRQ(ierr); 300 } 301 if (!cg->unprojected_gradient) { 302 ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient);CHKERRQ(ierr); 303 } 304 if (!cg->unprojected_gradient_old) { 305 ierr = VecDuplicate(tao->gradient,&cg->unprojected_gradient_old);CHKERRQ(ierr); 306 } 307 PetscFunctionReturn(0); 308 } 309 310 static PetscErrorCode TaoDestroy_BNCG(Tao tao) 311 { 312 TAO_BNCG *cg = (TAO_BNCG*) tao->data; 313 PetscErrorCode ierr; 314 315 PetscFunctionBegin; 316 if (tao->setupcalled) { 317 ierr = VecDestroy(&cg->W);CHKERRQ(ierr); 318 ierr = VecDestroy(&cg->work);CHKERRQ(ierr); 319 ierr = VecDestroy(&cg->X_old);CHKERRQ(ierr); 320 ierr = VecDestroy(&cg->G_old);CHKERRQ(ierr); 321 ierr = VecDestroy(&cg->unprojected_gradient);CHKERRQ(ierr); 322 ierr = VecDestroy(&cg->unprojected_gradient_old);CHKERRQ(ierr); 323 } 324 ierr = ISDestroy(&cg->active_lower);CHKERRQ(ierr); 325 ierr = ISDestroy(&cg->active_upper);CHKERRQ(ierr); 326 ierr = ISDestroy(&cg->active_fixed);CHKERRQ(ierr); 327 ierr = ISDestroy(&cg->active_idx);CHKERRQ(ierr); 328 ierr = ISDestroy(&cg->inactive_idx);CHKERRQ(ierr); 329 ierr = ISDestroy(&cg->inactive_old);CHKERRQ(ierr); 330 ierr = ISDestroy(&cg->new_inactives);CHKERRQ(ierr); 331 ierr = PetscFree(tao->data);CHKERRQ(ierr); 332 PetscFunctionReturn(0); 333 } 334 335 static PetscErrorCode TaoSetFromOptions_BNCG(PetscOptionItems *PetscOptionsObject,Tao tao) 336 { 337 TAO_BNCG *cg = (TAO_BNCG*)tao->data; 338 PetscErrorCode ierr; 339 340 PetscFunctionBegin; 341 ierr = TaoLineSearchSetFromOptions(tao->linesearch);CHKERRQ(ierr); 342 ierr = PetscOptionsHead(PetscOptionsObject,"Nonlinear Conjugate Gradient method for unconstrained optimization");CHKERRQ(ierr); 343 ierr = PetscOptionsReal("-tao_bncg_eta","restart tolerance", "", cg->eta,&cg->eta,NULL);CHKERRQ(ierr); 344 ierr = PetscOptionsReal("-tao_bncg_rho","descent direction tolerance", "", cg->rho,&cg->rho,NULL);CHKERRQ(ierr); 345 ierr = PetscOptionsReal("-tao_bncg_pow","descent direction exponent", "", cg->pow,&cg->pow,NULL);CHKERRQ(ierr); 346 ierr = PetscOptionsEList("-tao_bncg_type","cg formula", "", CG_Table, CG_Types, CG_Table[cg->cg_type], &cg->cg_type,NULL);CHKERRQ(ierr); 347 ierr = PetscOptionsEList("-tao_bncg_as_type","active set estimation method", "", CG_AS_TYPE, CG_AS_SIZE, CG_AS_TYPE[cg->cg_type], &cg->cg_type,NULL);CHKERRQ(ierr); 348 ierr = PetscOptionsBool("-tao_bncg_recycle","enable recycling the existing solution and gradient at the start of a new solve","",cg->recycle,&cg->recycle,NULL);CHKERRQ(ierr); 349 ierr = PetscOptionsReal("-tao_bncg_as_tol", "initial tolerance used when estimating actively bounded variables","",cg->as_tol,&cg->as_tol,NULL);CHKERRQ(ierr); 350 ierr = PetscOptionsReal("-tao_bncg_as_step", "step length used when estimating actively bounded variables","",cg->as_step,&cg->as_step,NULL);CHKERRQ(ierr); 351 ierr = PetscOptionsTail();CHKERRQ(ierr); 352 PetscFunctionReturn(0); 353 } 354 355 static PetscErrorCode TaoView_BNCG(Tao tao, PetscViewer viewer) 356 { 357 PetscBool isascii; 358 TAO_BNCG *cg = (TAO_BNCG*)tao->data; 359 PetscErrorCode ierr; 360 361 PetscFunctionBegin; 362 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 363 if (isascii) { 364 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 365 ierr = PetscViewerASCIIPrintf(viewer, "CG Type: %s\n", CG_Table[cg->cg_type]);CHKERRQ(ierr); 366 ierr = PetscViewerASCIIPrintf(viewer, "Resets: %i\n", cg->resets);CHKERRQ(ierr); 367 ierr = PetscViewerASCIIPrintf(viewer, " Broken ortho: %i\n", cg->broken_ortho);CHKERRQ(ierr); 368 ierr = PetscViewerASCIIPrintf(viewer, " Not a descent dir.: %i\n", cg->descent_error);CHKERRQ(ierr); 369 ierr = PetscViewerASCIIPrintf(viewer, "Line search fails: %i\n", cg->ls_fails);CHKERRQ(ierr); 370 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 371 } 372 PetscFunctionReturn(0); 373 } 374 375 /*MC 376 TAOBNCG - Bound-constrained Nonlinear Conjugate Gradient method. 377 378 Options Database Keys: 379 + -tao_bncg_recycle - enable recycling the latest calculated gradient vector in subsequent TaoSolve() calls 380 . -tao_bncg_eta <r> - restart tolerance 381 . -tao_bncg_type <taocg_type> - cg formula 382 . -tao_bncg_as_type <none,bertsekas> - active set estimation method 383 . -tao_bncg_as_tol <r> - tolerance used in Bertsekas active-set estimation 384 . -tao_bncg_as_step <r> - trial step length used in Bertsekas active-set estimation 385 386 Notes: 387 CG formulas are: 388 "fr" - Fletcher-Reeves 389 "pr" - Polak-Ribiere 390 "prp" - Polak-Ribiere-Plus 391 "hs" - Hestenes-Steifel 392 "dy" - Dai-Yuan 393 Level: beginner 394 M*/ 395 396 397 PETSC_EXTERN PetscErrorCode TaoCreate_BNCG(Tao tao) 398 { 399 TAO_BNCG *cg; 400 const char *morethuente_type = TAOLINESEARCHMT; 401 PetscErrorCode ierr; 402 403 PetscFunctionBegin; 404 tao->ops->setup = TaoSetUp_BNCG; 405 tao->ops->solve = TaoSolve_BNCG; 406 tao->ops->view = TaoView_BNCG; 407 tao->ops->setfromoptions = TaoSetFromOptions_BNCG; 408 tao->ops->destroy = TaoDestroy_BNCG; 409 410 /* Override default settings (unless already changed) */ 411 if (!tao->max_it_changed) tao->max_it = 2000; 412 if (!tao->max_funcs_changed) tao->max_funcs = 4000; 413 414 /* Note: nondefault values should be used for nonlinear conjugate gradient */ 415 /* method. In particular, gtol should be less that 0.5; the value used in */ 416 /* Nocedal and Wright is 0.10. We use the default values for the */ 417 /* linesearch because it seems to work better. */ 418 ierr = TaoLineSearchCreate(((PetscObject)tao)->comm, &tao->linesearch);CHKERRQ(ierr); 419 ierr = PetscObjectIncrementTabLevel((PetscObject)tao->linesearch, (PetscObject)tao, 1);CHKERRQ(ierr); 420 ierr = TaoLineSearchSetType(tao->linesearch, morethuente_type);CHKERRQ(ierr); 421 ierr = TaoLineSearchUseTaoRoutines(tao->linesearch, tao);CHKERRQ(ierr); 422 ierr = TaoLineSearchSetOptionsPrefix(tao->linesearch,tao->hdr.prefix);CHKERRQ(ierr); 423 424 ierr = PetscNewLog(tao,&cg);CHKERRQ(ierr); 425 tao->data = (void*)cg; 426 cg->rho = 1e-4; 427 cg->pow = 2.1; 428 cg->eta = 0.5; 429 cg->as_step = 0.001; 430 cg->as_tol = 0.001; 431 cg->as_type = CG_AS_BERTSEKAS; 432 cg->cg_type = CG_DaiYuan; 433 cg->recycle = PETSC_FALSE; 434 PetscFunctionReturn(0); 435 } 436