1 #include <../src/tao/constrained/impls/almm/almm.h> /*I "petsctao.h" I*/ /*I "petscvec.h" I*/ 2 #include <petsctao.h> 3 #include <petsc/private/petscimpl.h> 4 #include <petsc/private/vecimpl.h> 5 6 static PetscErrorCode TaoALMMCombinePrimal_Private(Tao,Vec,Vec,Vec); 7 static PetscErrorCode TaoALMMCombineDual_Private(Tao,Vec,Vec,Vec); 8 static PetscErrorCode TaoALMMSplitPrimal_Private(Tao,Vec,Vec,Vec); 9 static PetscErrorCode TaoALMMComputeOptimalityNorms_Private(Tao); 10 static PetscErrorCode TaoALMMComputeAugLagAndGradient_Private(Tao); 11 static PetscErrorCode TaoALMMComputePHRLagAndGradient_Private(Tao); 12 13 static PetscErrorCode TaoSolve_ALMM(Tao tao) 14 { 15 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 16 TaoConvergedReason reason; 17 PetscReal updated; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 /* reset initial multiplier/slack guess */ 22 if (!tao->recycle) { 23 if (tao->ineq_constrained) { 24 ierr = VecZeroEntries(auglag->Ps);CHKERRQ(ierr); 25 ierr = TaoALMMCombinePrimal_Private(tao, auglag->Px, auglag->Ps, auglag->P);CHKERRQ(ierr); 26 ierr = VecZeroEntries(auglag->Yi);CHKERRQ(ierr); 27 } 28 if (tao->eq_constrained) { 29 ierr = VecZeroEntries(auglag->Ye);CHKERRQ(ierr); 30 } 31 } 32 33 /* compute initial nonlinear Lagrangian and its derivatives */ 34 ierr = (*auglag->sub_obj)(tao);CHKERRQ(ierr); 35 ierr = TaoALMMComputeOptimalityNorms_Private(tao);CHKERRQ(ierr); 36 /* print initial step and check convergence */ 37 ierr = PetscInfo1(tao,"Solving with %s formulation\n",TaoALMMTypes[auglag->type]);CHKERRQ(ierr); 38 ierr = TaoLogConvergenceHistory(tao, auglag->Lval, auglag->gnorm, auglag->cnorm, tao->ksp_its);CHKERRQ(ierr); 39 ierr = TaoMonitor(tao, tao->niter, auglag->fval, auglag->gnorm, auglag->cnorm, 0.0);CHKERRQ(ierr); 40 ierr = (*tao->ops->convergencetest)(tao, tao->cnvP);CHKERRQ(ierr); 41 /* set initial penalty factor and inner solver tolerance */ 42 switch (auglag->type) { 43 case TAO_ALMM_CLASSIC: 44 auglag->mu = auglag->mu0; 45 break; 46 case TAO_ALMM_PHR: 47 auglag->cenorm = 0.0; 48 if (tao->eq_constrained) { 49 ierr = VecDot(auglag->Ce, auglag->Ce, &auglag->cenorm);CHKERRQ(ierr); 50 } 51 auglag->cinorm = 0.0; 52 if (tao->ineq_constrained) { 53 ierr = VecCopy(auglag->Ci, auglag->Ciwork);CHKERRQ(ierr); 54 ierr = VecScale(auglag->Ciwork, -1.0);CHKERRQ(ierr); 55 ierr = VecPointwiseMax(auglag->Ciwork, auglag->Cizero, auglag->Ciwork);CHKERRQ(ierr); 56 ierr = VecDot(auglag->Ciwork, auglag->Ciwork, &auglag->cinorm);CHKERRQ(ierr); 57 } 58 /* determine initial penalty factor based on the balance of constraint violation and objective function value */ 59 auglag->mu = PetscMax(1.e-6, PetscMin(10.0, 2.0*PetscAbsReal(auglag->fval)/(auglag->cenorm + auglag->cinorm))); 60 break; 61 default: 62 break; 63 } 64 auglag->gtol = auglag->gtol0; 65 ierr = PetscInfo1(tao,"Initial penalty: %.2f\n",auglag->mu);CHKERRQ(ierr); 66 67 /* start aug-lag outer loop */ 68 while (tao->reason == TAO_CONTINUE_ITERATING) { 69 ++tao->niter; 70 /* update subsolver tolerance */ 71 ierr = PetscInfo1(tao,"Subsolver tolerance: ||G|| <= %e\n",auglag->gtol);CHKERRQ(ierr); 72 ierr = TaoSetTolerances(auglag->subsolver, auglag->gtol, 0.0, 0.0);CHKERRQ(ierr); 73 /* solve the bound-constrained or unconstrained subproblem */ 74 ierr = TaoSolve(auglag->subsolver);CHKERRQ(ierr); 75 ierr = TaoGetConvergedReason(auglag->subsolver, &reason);CHKERRQ(ierr); 76 tao->ksp_its += auglag->subsolver->ksp_its; 77 if (reason != TAO_CONVERGED_GATOL) { 78 ierr = PetscInfo1(tao,"Subsolver failed to converge, reason: %s\n",TaoConvergedReasons[reason]);CHKERRQ(ierr); 79 } 80 /* evaluate solution and test convergence */ 81 ierr = (*auglag->sub_obj)(tao);CHKERRQ(ierr); 82 ierr = TaoALMMComputeOptimalityNorms_Private(tao);CHKERRQ(ierr); 83 /* decide whether to update multipliers or not */ 84 updated = 0.0; 85 if (auglag->cnorm <= auglag->ytol) { 86 ierr = PetscInfo1(tao,"Multipliers updated: ||C|| <= %e\n",auglag->ytol);CHKERRQ(ierr); 87 /* constraints are good, update multipliers and convergence tolerances */ 88 if (tao->eq_constrained) { 89 ierr = VecAXPY(auglag->Ye, auglag->mu, auglag->Ce);CHKERRQ(ierr); 90 ierr = VecSet(auglag->Cework, auglag->ye_max);CHKERRQ(ierr); 91 ierr = VecPointwiseMin(auglag->Ye, auglag->Cework, auglag->Ye);CHKERRQ(ierr); 92 ierr = VecSet(auglag->Cework, auglag->ye_min);CHKERRQ(ierr); 93 ierr = VecPointwiseMax(auglag->Ye, auglag->Cework, auglag->Ye);CHKERRQ(ierr); 94 } 95 if (tao->ineq_constrained) { 96 ierr = VecAXPY(auglag->Yi, auglag->mu, auglag->Ci);CHKERRQ(ierr); 97 ierr = VecSet(auglag->Ciwork, auglag->yi_max);CHKERRQ(ierr); 98 ierr = VecPointwiseMin(auglag->Yi, auglag->Ciwork, auglag->Yi);CHKERRQ(ierr); 99 ierr = VecSet(auglag->Ciwork, auglag->yi_min);CHKERRQ(ierr); 100 ierr = VecPointwiseMax(auglag->Yi, auglag->Ciwork, auglag->Yi);CHKERRQ(ierr); 101 } 102 /* tolerances are updated only for non-PHR methods */ 103 if (auglag->type != TAO_ALMM_PHR) { 104 auglag->ytol = PetscMax(tao->catol, auglag->ytol/PetscPowReal(auglag->mu, auglag->mu_pow_good)); 105 auglag->gtol = PetscMax(tao->gatol, auglag->gtol/auglag->mu); 106 } 107 updated = 1.0; 108 } else { 109 /* constraints are bad, update penalty factor */ 110 auglag->mu = PetscMin(auglag->mu_max, auglag->mu_fac*auglag->mu); 111 /* tolerances are reset only for non-PHR methods */ 112 if (auglag->type != TAO_ALMM_PHR) { 113 auglag->ytol = PetscMax(tao->catol, 0.1/PetscPowReal(auglag->mu, auglag->mu_pow_bad)); 114 auglag->gtol = PetscMax(tao->gatol, 1.0/auglag->mu); 115 } 116 ierr = PetscInfo1(tao,"Penalty increased: mu = %.2f\n",auglag->mu);CHKERRQ(ierr); 117 } 118 ierr = TaoLogConvergenceHistory(tao, auglag->fval, auglag->gnorm, auglag->cnorm, tao->ksp_its);CHKERRQ(ierr); 119 ierr = TaoMonitor(tao, tao->niter, auglag->fval, auglag->gnorm, auglag->cnorm, updated);CHKERRQ(ierr); 120 ierr = (*tao->ops->convergencetest)(tao, tao->cnvP);CHKERRQ(ierr); 121 } 122 123 PetscFunctionReturn(0); 124 } 125 126 static PetscErrorCode TaoView_ALMM(Tao tao,PetscViewer viewer) 127 { 128 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 129 PetscBool isascii; 130 PetscErrorCode ierr; 131 132 PetscFunctionBegin; 133 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 134 ierr = TaoView(auglag->subsolver,viewer);CHKERRQ(ierr); 135 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 136 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 137 if (isascii) { 138 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 139 ierr = PetscViewerASCIIPrintf(viewer, "ALMM Formulation Type: %s\n", TaoALMMTypes[auglag->type]);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 141 } 142 PetscFunctionReturn(0); 143 } 144 145 static PetscErrorCode TaoSetUp_ALMM(Tao tao) 146 { 147 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 148 VecType vec_type; 149 Vec SL, SU; 150 PetscBool is_cg = PETSC_FALSE, is_lmvm = PETSC_FALSE; 151 PetscErrorCode ierr; 152 153 PetscFunctionBegin; 154 if (tao->ineq_doublesided) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TAOALMM does not support double-sided inequality constraint definition. Please restructure your inequality constrainst to fit the form c(x) >= 0."); 155 if (!tao->eq_constrained && !tao->ineq_constrained) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "Equality and/or inequality constraints must be defined before solver setup."); 156 ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); 157 /* alias base vectors and create extras */ 158 ierr = VecGetType(tao->solution, &vec_type);CHKERRQ(ierr); 159 auglag->Px = tao->solution; 160 if (!tao->gradient) { /* base gradient */ 161 ierr = VecDuplicate(tao->solution, &tao->gradient);CHKERRQ(ierr); 162 } 163 auglag->LgradX = tao->gradient; 164 if (!auglag->Xwork) { /* opt var work vector */ 165 ierr = VecDuplicate(tao->solution, &auglag->Xwork);CHKERRQ(ierr); 166 } 167 if (tao->eq_constrained) { 168 auglag->Ce = tao->constraints_equality; 169 auglag->Ae = tao->jacobian_equality; 170 if (!auglag->Ye) { /* equality multipliers */ 171 ierr = VecDuplicate(auglag->Ce, &auglag->Ye);CHKERRQ(ierr); 172 } 173 if (!auglag->Cework) { 174 ierr = VecDuplicate(auglag->Ce, &auglag->Cework);CHKERRQ(ierr); 175 } 176 } 177 if (tao->ineq_constrained) { 178 auglag->Ci = tao->constraints_inequality; 179 auglag->Ai = tao->jacobian_inequality; 180 if (!auglag->Yi) { /* inequality multipliers */ 181 ierr = VecDuplicate(auglag->Ci, &auglag->Yi);CHKERRQ(ierr); 182 } 183 if (!auglag->Ciwork) { 184 ierr = VecDuplicate(auglag->Ci, &auglag->Ciwork);CHKERRQ(ierr); 185 } 186 if (!auglag->Cizero) { 187 ierr = VecDuplicate(auglag->Ci, &auglag->Cizero);CHKERRQ(ierr); 188 ierr = VecZeroEntries(auglag->Cizero);CHKERRQ(ierr); 189 } 190 if (!auglag->Ps) { /* slack vars */ 191 ierr = VecDuplicate(auglag->Ci, &auglag->Ps);CHKERRQ(ierr); 192 } 193 if (!auglag->LgradS) { /* slack component of Lagrangian gradient */ 194 ierr = VecDuplicate(auglag->Ci, &auglag->LgradS);CHKERRQ(ierr); 195 } 196 /* create vector for combined primal space and the associated communication objects */ 197 if (!auglag->P) { 198 ierr = PetscMalloc1(2, &auglag->Parr);CHKERRQ(ierr); 199 auglag->Parr[0] = auglag->Px; auglag->Parr[1] = auglag->Ps; 200 ierr = VecConcatenate(2, auglag->Parr, &auglag->P, &auglag->Pis);CHKERRQ(ierr); 201 ierr = PetscMalloc1(2, &auglag->Pscatter);CHKERRQ(ierr); 202 ierr = VecScatterCreate(auglag->P, auglag->Pis[0], auglag->Px, NULL, &auglag->Pscatter[0]);CHKERRQ(ierr); 203 ierr = VecScatterCreate(auglag->P, auglag->Pis[1], auglag->Ps, NULL, &auglag->Pscatter[1]);CHKERRQ(ierr); 204 } 205 if (tao->eq_constrained) { 206 /* create vector for combined dual space and the associated communication objects */ 207 if (!auglag->Y) { 208 ierr = PetscMalloc1(2, &auglag->Yarr);CHKERRQ(ierr); 209 auglag->Yarr[0] = auglag->Ye; auglag->Yarr[1] = auglag->Yi; 210 ierr = VecConcatenate(2, auglag->Yarr, &auglag->Y, &auglag->Yis);CHKERRQ(ierr); 211 ierr = PetscMalloc1(2, &auglag->Yscatter);CHKERRQ(ierr); 212 ierr = VecScatterCreate(auglag->Y, auglag->Yis[0], auglag->Ye, NULL, &auglag->Yscatter[0]);CHKERRQ(ierr); 213 ierr = VecScatterCreate(auglag->Y, auglag->Yis[1], auglag->Yi, NULL, &auglag->Yscatter[1]);CHKERRQ(ierr); 214 } 215 if (!auglag->C) { 216 ierr = VecDuplicate(auglag->Y, &auglag->C);CHKERRQ(ierr); 217 } 218 } else { 219 if (!auglag->C) { 220 auglag->C = auglag->Ci; 221 } 222 if (!auglag->Y) { 223 auglag->Y = auglag->Yi; 224 } 225 } 226 } else { 227 if (!auglag->P) { 228 auglag->P = auglag->Px; 229 } 230 if (!auglag->G) { 231 auglag->G = auglag->LgradX; 232 } 233 if (!auglag->C) { 234 auglag->C = auglag->Ce; 235 } 236 if (!auglag->Y) { 237 auglag->Y = auglag->Ye; 238 } 239 } 240 /* initialize parameters */ 241 if (auglag->type == TAO_ALMM_PHR) { 242 auglag->mu_fac = 10.0; 243 auglag->yi_min = 0.0; 244 auglag->ytol0 = 0.5; 245 auglag->gtol0 = tao->gatol; 246 if (tao->gatol_changed && tao->catol_changed) { 247 ierr = PetscInfo(tao,"TAOALMM with PHR: different gradient and constraint tolerances are not supported, setting catol = gatol\n");CHKERRQ(ierr); 248 tao->catol = tao->gatol; 249 } 250 } 251 /* set the Lagrangian formulation type for the subsolver */ 252 switch (auglag->type) { 253 case TAO_ALMM_CLASSIC: 254 auglag->sub_obj = TaoALMMComputeAugLagAndGradient_Private; 255 break; 256 case TAO_ALMM_PHR: 257 auglag->sub_obj = TaoALMMComputePHRLagAndGradient_Private; 258 break; 259 default: 260 break; 261 } 262 /* set up the subsolver */ 263 ierr = TaoSetInitialVector(auglag->subsolver, auglag->P);CHKERRQ(ierr); 264 ierr = TaoSetObjectiveRoutine(auglag->subsolver, TaoALMMSubsolverObjective_Private, (void*)auglag);CHKERRQ(ierr); 265 ierr = TaoSetObjectiveAndGradientRoutine(auglag->subsolver, TaoALMMSubsolverObjectiveAndGradient_Private, (void*)auglag);CHKERRQ(ierr); 266 if (tao->bounded) { 267 /* make sure that the subsolver is a bound-constrained method */ 268 ierr = PetscObjectTypeCompare((PetscObject)auglag->subsolver, TAOCG, &is_cg);CHKERRQ(ierr); 269 ierr = PetscObjectTypeCompare((PetscObject)auglag->subsolver, TAOLMVM, &is_lmvm);CHKERRQ(ierr); 270 if (is_cg) { 271 ierr = TaoSetType(auglag->subsolver, TAOBNCG);CHKERRQ(ierr); 272 ierr = PetscInfo(tao,"TAOCG detected for bound-constrained problem, switching to TAOBNCG instead.");CHKERRQ(ierr); 273 } 274 if (is_lmvm) { 275 ierr = TaoSetType(auglag->subsolver, TAOBQNLS);CHKERRQ(ierr); 276 ierr = PetscInfo(tao,"TAOLMVM detected for bound-constrained problem, switching to TAOBQNLS instead.");CHKERRQ(ierr); 277 } 278 /* create lower and upper bound clone vectors for subsolver */ 279 if (!auglag->PL) { 280 ierr = VecDuplicate(auglag->P, &auglag->PL);CHKERRQ(ierr); 281 } 282 if (!auglag->PU) { 283 ierr = VecDuplicate(auglag->P, &auglag->PU);CHKERRQ(ierr); 284 } 285 if (tao->ineq_constrained) { 286 /* create lower and upper bounds for slack, set lower to 0 */ 287 ierr = VecDuplicate(auglag->Ci, &SL);CHKERRQ(ierr); 288 ierr = VecSet(SL, 0.0);CHKERRQ(ierr); 289 ierr = VecDuplicate(auglag->Ci, &SU);CHKERRQ(ierr); 290 ierr = VecSet(SU, PETSC_INFINITY);CHKERRQ(ierr); 291 /* combine opt var bounds with slack bounds */ 292 ierr = TaoALMMCombinePrimal_Private(tao, tao->XL, SL, auglag->PL);CHKERRQ(ierr); 293 ierr = TaoALMMCombinePrimal_Private(tao, tao->XU, SU, auglag->PU);CHKERRQ(ierr); 294 /* destroy work vectors */ 295 ierr = VecDestroy(&SL);CHKERRQ(ierr); 296 ierr = VecDestroy(&SU);CHKERRQ(ierr); 297 } else { 298 /* no inequality constraints, just copy bounds into the subsolver */ 299 ierr = VecCopy(tao->XL, auglag->PL);CHKERRQ(ierr); 300 ierr = VecCopy(tao->XU, auglag->PU);CHKERRQ(ierr); 301 } 302 ierr = TaoSetVariableBounds(auglag->subsolver, auglag->PL, auglag->PU);CHKERRQ(ierr); 303 } 304 ierr = TaoSetUp(auglag->subsolver);CHKERRQ(ierr); 305 auglag->G = auglag->subsolver->gradient; 306 307 PetscFunctionReturn(0); 308 } 309 310 static PetscErrorCode TaoDestroy_ALMM(Tao tao) 311 { 312 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 313 PetscErrorCode ierr; 314 315 PetscFunctionBegin; 316 ierr = TaoDestroy(&auglag->subsolver);CHKERRQ(ierr); 317 if (tao->setupcalled) { 318 ierr = VecDestroy(&auglag->Xwork);CHKERRQ(ierr); /* opt work */ 319 if (tao->eq_constrained) { 320 ierr = VecDestroy(&auglag->Ye);CHKERRQ(ierr); /* equality multipliers */ 321 ierr = VecDestroy(&auglag->Cework);CHKERRQ(ierr); /* equality work vector */ 322 } 323 if (tao->ineq_constrained) { 324 ierr = VecDestroy(&auglag->Ps);CHKERRQ(ierr); /* slack vars */ 325 auglag->Parr[0] = NULL; /* clear pointer to tao->solution, will be destroyed by TaoDestroy() shell */ 326 ierr = PetscFree(auglag->Parr);CHKERRQ(ierr); /* array of primal vectors */ 327 ierr = VecDestroy(&auglag->LgradS);CHKERRQ(ierr); /* slack grad */ 328 ierr = VecDestroy(&auglag->Cizero);CHKERRQ(ierr); /* zero vector for pointwise max */ 329 ierr = VecDestroy(&auglag->Yi);CHKERRQ(ierr); /* inequality multipliers */ 330 ierr = VecDestroy(&auglag->Ciwork);CHKERRQ(ierr); /* inequality work vector */ 331 ierr = VecDestroy(&auglag->P);CHKERRQ(ierr); /* combo primal */ 332 ierr = ISDestroy(&auglag->Pis[0]);CHKERRQ(ierr); /* index set for X inside P */ 333 ierr = ISDestroy(&auglag->Pis[1]);CHKERRQ(ierr); /* index set for S inside P */ 334 ierr = PetscFree(auglag->Pis);CHKERRQ(ierr); /* array of P index sets */ 335 ierr = VecScatterDestroy(&auglag->Pscatter[0]);CHKERRQ(ierr); 336 ierr = VecScatterDestroy(&auglag->Pscatter[1]);CHKERRQ(ierr); 337 ierr = PetscFree(auglag->Pscatter);CHKERRQ(ierr); 338 if (tao->eq_constrained) { 339 ierr = VecDestroy(&auglag->Y);CHKERRQ(ierr); /* combo multipliers */ 340 ierr = PetscFree(auglag->Yarr);CHKERRQ(ierr); /* array of dual vectors */ 341 ierr = VecDestroy(&auglag->C);CHKERRQ(ierr); /* combo constraints */ 342 ierr = ISDestroy(&auglag->Yis[0]);CHKERRQ(ierr); /* index set for Ye inside Y */ 343 ierr = ISDestroy(&auglag->Yis[1]);CHKERRQ(ierr); /* index set for Yi inside Y */ 344 ierr = PetscFree(auglag->Yis);CHKERRQ(ierr); 345 ierr = VecScatterDestroy(&auglag->Yscatter[0]);CHKERRQ(ierr); 346 ierr = VecScatterDestroy(&auglag->Yscatter[1]);CHKERRQ(ierr); 347 ierr = PetscFree(auglag->Yscatter);CHKERRQ(ierr); 348 } 349 } 350 if (tao->bounded) { 351 ierr = VecDestroy(&auglag->PL);CHKERRQ(ierr); /* lower bounds for subsolver */ 352 ierr = VecDestroy(&auglag->PU);CHKERRQ(ierr); /* upper bounds for subsolver */ 353 } 354 } 355 ierr = PetscFree(tao->data);CHKERRQ(ierr); 356 PetscFunctionReturn(0); 357 } 358 359 static PetscErrorCode TaoSetFromOptions_ALMM(PetscOptionItems *PetscOptionsObject,Tao tao) 360 { 361 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 362 PetscInt i; 363 PetscErrorCode ierr; 364 365 PetscFunctionBegin; 366 ierr = PetscOptionsHead(PetscOptionsObject,"Augmented Lagrangian multipler method solves problems with general constraints by converting them into a sequence of unconstrained problems.");CHKERRQ(ierr); 367 ierr = PetscOptionsReal("-tao_almm_mu_init","initial penalty parameter","",auglag->mu0,&auglag->mu0,NULL);CHKERRQ(ierr); 368 ierr = PetscOptionsReal("-tao_almm_mu_factor","increase factor for the penalty parameter","",auglag->mu_fac,&auglag->mu_fac,NULL);CHKERRQ(ierr); 369 ierr = PetscOptionsReal("-tao_almm_mu_power_good","exponential for penalty parameter when multiplier update is accepted","",auglag->mu_pow_good,&auglag->mu_pow_good,NULL);CHKERRQ(ierr); 370 ierr = PetscOptionsReal("-tao_almm_mu_power_bad","exponential for penalty parameter when multiplier update is rejected","",auglag->mu_pow_bad,&auglag->mu_pow_bad,NULL);CHKERRQ(ierr); 371 ierr = PetscOptionsReal("-tao_almm_mu_max","maximum safeguard for penalty parameter updates","",auglag->mu_max,&auglag->mu_max,NULL);CHKERRQ(ierr); 372 ierr = PetscOptionsReal("-tao_almm_ye_min","minimum safeguard for equality multiplier updates","",auglag->ye_min,&auglag->ye_min,NULL);CHKERRQ(ierr); 373 ierr = PetscOptionsReal("-tao_almm_ye_max","maximum safeguard for equality multipliers updates","",auglag->ye_max,&auglag->ye_max,NULL);CHKERRQ(ierr); 374 ierr = PetscOptionsReal("-tao_almm_yi_min","minimum safeguard for inequality multipliers updates","",auglag->yi_min,&auglag->yi_min,NULL);CHKERRQ(ierr); 375 ierr = PetscOptionsReal("-tao_almm_yi_max","maximum safeguard for inequality multipliers updates","",auglag->yi_max,&auglag->yi_max,NULL);CHKERRQ(ierr); 376 ierr = PetscOptionsEnum("-tao_almm_type","augmented Lagrangian formulation type for the subproblem","TaoALMMType",TaoALMMTypes,(PetscEnum)auglag->type,(PetscEnum*)&auglag->type,NULL);CHKERRQ(ierr); 377 ierr = PetscOptionsTail();CHKERRQ(ierr); 378 ierr = TaoSetOptionsPrefix(auglag->subsolver,((PetscObject)tao)->prefix);CHKERRQ(ierr); 379 ierr = TaoAppendOptionsPrefix(auglag->subsolver,"tao_almm_subsolver_");CHKERRQ(ierr); 380 ierr = TaoSetFromOptions(auglag->subsolver);CHKERRQ(ierr); 381 for (i=0; i<tao->numbermonitors; i++) { 382 ierr = PetscObjectReference((PetscObject)tao->monitorcontext[i]);CHKERRQ(ierr); 383 ierr = TaoSetMonitor(auglag->subsolver, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr); 384 if (tao->monitor[i] == TaoMonitorDefault || tao->monitor[i] == TaoDefaultCMonitor || tao->monitor[i] == TaoDefaultGMonitor || tao->monitor[i] == TaoDefaultSMonitor) { 385 auglag->info = PETSC_TRUE; 386 } 387 } 388 PetscFunctionReturn(0); 389 } 390 391 /* -------------------------------------------------------- */ 392 393 /*MC 394 TaoALMM - Augmented Lagrangian multiplier method for solving nonlinear optimization problems with general constraints. 395 396 Options Database Keys: 397 + -tao_almm_mu_init <real> - initial penalty parameter (default: 10.) 398 . -tao_almm_mu_factor <real> - increase factor for the penalty parameter (default: 100.) 399 . -tao_almm_mu_max <real> - maximum safeguard for penalty parameter updates (default: 1.e20) 400 . -tao_almm_mu_power_good <real> - exponential for penalty parameter when multiplier update is accepted (default: 0.9) 401 . -tao_almm_mu_power_bad <real> - exponential for penalty parameter when multiplier update is rejected (default: 0.1) 402 . -tao_almm_ye_min <real> - minimum safeguard for equality multiplier updates (default: -1.e20) 403 . -tao_almm_ye_max <real> - maximum safeguard for equality multiplier updates (default: 1.e20) 404 . -tao_almm_yi_min <real> - minimum safeguard for inequality multiplier updates (default: -1.e20) 405 . -tao_almm_yi_max <real> - maximum safeguard for inequality multiplier updates (default: 1.e20) 406 - -tao_almm_type <classic,phr> - change formulation of the augmented Lagrangian merit function for the subproblem (default: classic) 407 408 Level: beginner 409 410 Notes: 411 This method converts a constrained problem into a sequence of unconstrained problems via the augmented 412 Lagrangian merit function. Bound constraints are pushed down to the subproblem without any modifications. 413 414 Two formulations are offered for the subproblem: canonical Hestenes-Powell augmented Lagrangian with slack 415 variables for inequality constraints, and a slack-less Powell-Hestenes-Rockafellar (PHR) formulation utilizing a 416 pointwise max() penalty on inequality constraints. The canonical augmented Lagrangian formulation typically 417 converges faster for most problems. However, PHR may be desirable for problems featuring a large number 418 of inequality constraints because it avoids inflating the size of the subproblem with slack variables. 419 420 The subproblem is solved using a nested first-order TAO solver. The user can retrieve a pointer to 421 the subsolver via TaoALMMGetSubsolver() or pass command line arguments to it using the 422 "-tao_almm_subsolver_" prefix. Currently, TaoALMM does not support second-order methods for the 423 subproblem. It is also highly recommended that the subsolver chosen by the user utilize a trust-region 424 strategy for globalization (default: TAOBQNKTR) especially if the outer problem features bound constraints. 425 426 .vb 427 while unconverged 428 solve argmin_x L(x) s.t. l <= x <= u 429 if ||c|| <= y_tol 430 if ||c|| <= c_tol && ||Lgrad|| <= g_tol: 431 problem converged, return solution 432 else 433 constraints sufficiently improved 434 update multipliers and tighten tolerances 435 endif 436 else 437 constraints did not improve 438 update penalty and loosen tolerances 439 endif 440 endwhile 441 .ve 442 443 .seealso: TaoALMMGetType(), TaoALMMSetType(), TaoALMMSetSubsolver(), TaoALMMGetSubsolver(), 444 TaoALMMGetMultipliers(), TaoALMMSetMultipliers(), TaoALMMGetPrimalIS(), TaoALMMGetDualIS() 445 M*/ 446 PETSC_EXTERN PetscErrorCode TaoCreate_ALMM(Tao tao) 447 { 448 TAO_ALMM *auglag; 449 PetscErrorCode ierr; 450 451 PetscFunctionBegin; 452 ierr = PetscNewLog(tao, &auglag);CHKERRQ(ierr); 453 454 tao->ops->destroy = TaoDestroy_ALMM; 455 tao->ops->setup = TaoSetUp_ALMM; 456 tao->ops->setfromoptions = TaoSetFromOptions_ALMM; 457 tao->ops->view = TaoView_ALMM; 458 tao->ops->solve = TaoSolve_ALMM; 459 460 tao->gatol = 1.e-5; 461 tao->grtol = 0.0; 462 tao->gttol = 0.0; 463 tao->catol = 1.e-5; 464 tao->crtol = 0.0; 465 466 tao->data = (void*)auglag; 467 auglag->parent = tao; 468 auglag->mu0 = 10.0; 469 auglag->mu = auglag->mu0; 470 auglag->mu_fac = 10.0; 471 auglag->mu_max = PETSC_INFINITY; 472 auglag->mu_pow_good = 0.9; 473 auglag->mu_pow_bad = 0.1; 474 auglag->ye_min = PETSC_NINFINITY; 475 auglag->ye_max = PETSC_INFINITY; 476 auglag->yi_min = PETSC_NINFINITY; 477 auglag->yi_max = PETSC_INFINITY; 478 auglag->ytol0 = 0.1/PetscPowReal(auglag->mu0, auglag->mu_pow_bad); 479 auglag->ytol = auglag->ytol0; 480 auglag->gtol0 = 1.0/auglag->mu0; 481 auglag->gtol = auglag->gtol0; 482 483 auglag->sub_obj = TaoALMMComputeAugLagAndGradient_Private; 484 auglag->type = TAO_ALMM_CLASSIC; 485 auglag->info = PETSC_FALSE; 486 487 ierr = TaoCreate(PetscObjectComm((PetscObject)tao),&auglag->subsolver);CHKERRQ(ierr); 488 ierr = TaoSetType(auglag->subsolver, TAOBQNKTR);CHKERRQ(ierr); 489 ierr = TaoSetTolerances(auglag->subsolver, auglag->gtol, 0.0, 0.0);CHKERRQ(ierr); 490 ierr = TaoSetMaximumIterations(auglag->subsolver, 1000);CHKERRQ(ierr); 491 ierr = TaoSetMaximumFunctionEvaluations(auglag->subsolver, 10000);CHKERRQ(ierr); 492 ierr = TaoSetFunctionLowerBound(auglag->subsolver, PETSC_NINFINITY);CHKERRQ(ierr); 493 ierr = PetscObjectIncrementTabLevel((PetscObject)auglag->subsolver,(PetscObject)tao,1);CHKERRQ(ierr); 494 495 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetType_C", TaoALMMGetType_Private);CHKERRQ(ierr); 496 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMSetType_C", TaoALMMSetType_Private);CHKERRQ(ierr); 497 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetSubsolver_C", TaoALMMGetSubsolver_Private);CHKERRQ(ierr); 498 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMSetSubsolver_C", TaoALMMSetSubsolver_Private);CHKERRQ(ierr); 499 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetMultipliers_C", TaoALMMGetMultipliers_Private);CHKERRQ(ierr); 500 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMSetMultipliers_C", TaoALMMSetMultipliers_Private);CHKERRQ(ierr); 501 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetPrimalIS_C", TaoALMMGetPrimalIS_Private);CHKERRQ(ierr); 502 ierr = PetscObjectComposeFunction((PetscObject)tao, "TaoALMMGetDualIS_C", TaoALMMGetDualIS_Private);CHKERRQ(ierr); 503 PetscFunctionReturn(0); 504 } 505 506 static PetscErrorCode TaoALMMCombinePrimal_Private(Tao tao, Vec X, Vec S, Vec P) 507 { 508 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 509 PetscErrorCode ierr; 510 511 PetscFunctionBegin; 512 if (tao->ineq_constrained) { 513 ierr = VecScatterBegin(auglag->Pscatter[0], X, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 514 ierr = VecScatterEnd(auglag->Pscatter[0], X, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 515 ierr = VecScatterBegin(auglag->Pscatter[1], S, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 516 ierr = VecScatterEnd(auglag->Pscatter[1], S, P, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 517 } else { 518 ierr = VecCopy(X, P);CHKERRQ(ierr); 519 } 520 PetscFunctionReturn(0); 521 } 522 523 static PetscErrorCode TaoALMMCombineDual_Private(Tao tao, Vec EQ, Vec IN, Vec Y) 524 { 525 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 526 PetscErrorCode ierr; 527 528 PetscFunctionBegin; 529 if (tao->eq_constrained) { 530 if (tao->ineq_constrained) { 531 ierr = VecScatterBegin(auglag->Yscatter[0], EQ, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 532 ierr = VecScatterEnd(auglag->Yscatter[0], EQ, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 533 ierr = VecScatterBegin(auglag->Yscatter[1], IN, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 534 ierr = VecScatterEnd(auglag->Yscatter[1], IN, Y, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); 535 } else { 536 ierr = VecCopy(EQ, Y);CHKERRQ(ierr); 537 } 538 } else { 539 ierr = VecCopy(IN, Y);CHKERRQ(ierr); 540 } 541 PetscFunctionReturn(0); 542 } 543 544 static PetscErrorCode TaoALMMSplitPrimal_Private(Tao tao, Vec P, Vec X, Vec S) 545 { 546 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 547 PetscErrorCode ierr; 548 549 PetscFunctionBegin; 550 if (tao->ineq_constrained) { 551 ierr = VecScatterBegin(auglag->Pscatter[0], P, X, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 552 ierr = VecScatterEnd(auglag->Pscatter[0], P, X, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 553 ierr = VecScatterBegin(auglag->Pscatter[1], P, S, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 554 ierr = VecScatterEnd(auglag->Pscatter[1], P, S, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 555 } else { 556 ierr = VecCopy(P, X);CHKERRQ(ierr); 557 } 558 PetscFunctionReturn(0); 559 } 560 561 /* this assumes that the latest constraints are stored in Ce and Ci, and also combined in C */ 562 static PetscErrorCode TaoALMMComputeOptimalityNorms_Private(Tao tao) 563 { 564 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 565 PetscErrorCode ierr; 566 567 PetscFunctionBegin; 568 /* if bounded, project the gradient */ 569 if (tao->bounded) { 570 ierr = VecBoundGradientProjection(auglag->LgradX, auglag->Px, tao->XL, tao->XU, auglag->LgradX);CHKERRQ(ierr); 571 } 572 if (auglag->type == TAO_ALMM_PHR) { 573 ierr = VecNorm(auglag->LgradX, NORM_INFINITY, &auglag->gnorm);CHKERRQ(ierr); 574 auglag->cenorm = 0.0; 575 if (tao->eq_constrained) { 576 ierr = VecNorm(auglag->Ce, NORM_INFINITY, &auglag->cenorm);CHKERRQ(ierr); 577 } 578 auglag->cinorm = 0.0; 579 if (tao->ineq_constrained) { 580 ierr = VecCopy(auglag->Yi, auglag->Ciwork);CHKERRQ(ierr); 581 ierr = VecScale(auglag->Ciwork, -1.0/auglag->mu);CHKERRQ(ierr); 582 ierr = VecPointwiseMax(auglag->Ciwork, auglag->Ci, auglag->Ciwork);CHKERRQ(ierr); 583 ierr = VecNorm(auglag->Ciwork, NORM_INFINITY, &auglag->cinorm);CHKERRQ(ierr); 584 } 585 auglag->cnorm_old = auglag->cnorm; 586 auglag->cnorm = PetscMax(auglag->cenorm, auglag->cinorm); 587 auglag->ytol = auglag->ytol0 * auglag->cnorm_old; 588 } else { 589 ierr = VecNorm(auglag->LgradX, NORM_2, &auglag->gnorm);CHKERRQ(ierr); 590 ierr = VecNorm(auglag->C, NORM_2, &auglag->cnorm);CHKERRQ(ierr); 591 } 592 PetscFunctionReturn(0); 593 } 594 595 static PetscErrorCode TaoALMMEvaluateIterate_Private(Tao tao, Vec P) 596 { 597 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 598 PetscErrorCode ierr; 599 600 PetscFunctionBegin; 601 /* split solution into primal and slack components */ 602 ierr = TaoALMMSplitPrimal_Private(tao, auglag->P, auglag->Px, auglag->Ps);CHKERRQ(ierr); 603 604 /* compute f, df/dx and the constraints */ 605 ierr = TaoComputeObjectiveAndGradient(tao, auglag->Px, &auglag->fval, auglag->LgradX);CHKERRQ(ierr); 606 if (tao->eq_constrained) { 607 ierr = TaoComputeEqualityConstraints(tao, auglag->Px, auglag->Ce);CHKERRQ(ierr); 608 ierr = TaoComputeJacobianEquality(tao, auglag->Px, auglag->Ae, auglag->Ae);CHKERRQ(ierr); 609 } 610 if (tao->ineq_constrained) { 611 ierr = TaoComputeInequalityConstraints(tao, auglag->Px, auglag->Ci);CHKERRQ(ierr); 612 ierr = TaoComputeJacobianInequality(tao, auglag->Px, auglag->Ai, auglag->Ai);CHKERRQ(ierr); 613 switch (auglag->type) { 614 case TAO_ALMM_CLASSIC: 615 /* classic formulation converts inequality to equality constraints via slack variables */ 616 ierr = VecAXPY(auglag->Ci, -1.0, auglag->Ps);CHKERRQ(ierr); 617 break; 618 case TAO_ALMM_PHR: 619 /* PHR is based on Ci <= 0 while TAO defines Ci >= 0 so we hit it with a negative sign */ 620 ierr = VecScale(auglag->Ci, -1.0);CHKERRQ(ierr); 621 ierr = MatScale(auglag->Ai, -1.0);CHKERRQ(ierr); 622 break; 623 default: 624 break; 625 } 626 } 627 /* combine constraints into one vector */ 628 ierr = TaoALMMCombineDual_Private(tao, auglag->Ce, auglag->Ci, auglag->C);CHKERRQ(ierr); 629 PetscFunctionReturn(0); 630 } 631 632 /* 633 Lphr = f + 0.5*mu*[ (Ce + Ye/mu)^T (Ce + Ye/mu) + pmin(0, Ci + Yi/mu)^T pmin(0, Ci + Yi/mu)] 634 635 dLphr/dX = dF/dX + mu*[ (Ce + Ye/mu)^T Ae + pmin(0, Ci + Yi/mu)^T Ai] 636 637 dLphr/dS = 0 638 */ 639 static PetscErrorCode TaoALMMComputePHRLagAndGradient_Private(Tao tao) 640 { 641 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 642 PetscReal eq_norm=0.0, ineq_norm=0.0; 643 PetscErrorCode ierr; 644 645 PetscFunctionBegin; 646 ierr = TaoALMMEvaluateIterate_Private(tao, auglag->P);CHKERRQ(ierr); 647 if (tao->eq_constrained) { 648 /* Ce_work = mu*(Ce + Ye/mu) */ 649 ierr = VecWAXPY(auglag->Cework, 1.0/auglag->mu, auglag->Ye, auglag->Ce);CHKERRQ(ierr); 650 ierr = VecDot(auglag->Cework, auglag->Cework, &eq_norm);CHKERRQ(ierr); /* contribution to scalar Lagrangian */ 651 ierr = VecScale(auglag->Cework, auglag->mu);CHKERRQ(ierr); 652 /* dL/dX += mu*(Ce + Ye/mu)^T Ae */ 653 ierr = MatMultTransposeAdd(auglag->Ae, auglag->Cework, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 654 } 655 if (tao->ineq_constrained) { 656 /* Ci_work = mu * pmax(0, Ci + Yi/mu) where pmax() is pointwise max() */ 657 ierr = VecWAXPY(auglag->Ciwork, 1.0/auglag->mu, auglag->Yi, auglag->Ci);CHKERRQ(ierr); 658 ierr = VecPointwiseMax(auglag->Ciwork, auglag->Cizero, auglag->Ciwork);CHKERRQ(ierr); 659 ierr = VecDot(auglag->Ciwork, auglag->Ciwork, &ineq_norm);CHKERRQ(ierr); /* contribution to scalar Lagrangian */ 660 /* dL/dX += mu * pmax(0, Ci + Yi/mu)^T Ai */ 661 ierr = VecScale(auglag->Ciwork, auglag->mu);CHKERRQ(ierr); 662 ierr = MatMultTransposeAdd(auglag->Ai, auglag->Ciwork, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 663 /* dL/dS = 0 because there are no slacks in PHR */ 664 ierr = VecZeroEntries(auglag->LgradS);CHKERRQ(ierr); 665 } 666 /* combine gradient together */ 667 ierr = TaoALMMCombinePrimal_Private(tao, auglag->LgradX, auglag->LgradS, auglag->G);CHKERRQ(ierr); 668 /* compute L = f + 0.5 * mu * [(Ce + Ye/mu)^T (Ce + Ye/mu) + pmax(0, Ci + Yi/mu)^T pmax(0, Ci + Yi/mu)] */ 669 auglag->Lval = auglag->fval + 0.5*auglag->mu*(eq_norm + ineq_norm);CHKERRQ(ierr); 670 PetscFunctionReturn(0); 671 } 672 673 /* 674 Lc = F + Ye^TCe + Yi^T(Ci - S) + 0.5*mu*[Ce^TCe + (Ci - S)^T(Ci - S)] 675 676 dLc/dX = dF/dX + Ye^TAe + Yi^TAi + 0.5*mu*[Ce^TAe + (Ci - S)^TAi] 677 678 dLc/dS = -[Yi + mu*(Ci - S)] 679 */ 680 static PetscErrorCode TaoALMMComputeAugLagAndGradient_Private(Tao tao) 681 { 682 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 683 PetscReal yeTce=0.0, yiTcims=0.0, ceTce=0.0, cimsTcims=0.0; 684 PetscErrorCode ierr; 685 686 PetscFunctionBegin; 687 ierr = TaoALMMEvaluateIterate_Private(tao, auglag->P);CHKERRQ(ierr); 688 if (tao->eq_constrained) { 689 /* compute scalar contributions */ 690 ierr = VecDot(auglag->Ye, auglag->Ce, &yeTce);CHKERRQ(ierr); 691 ierr = VecDot(auglag->Ce, auglag->Ce, &ceTce);CHKERRQ(ierr); 692 /* dL/dX += ye^T Ae */ 693 ierr = MatMultTransposeAdd(auglag->Ae, auglag->Ye, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 694 /* dL/dX += mu * ce^T Ae */ 695 ierr = MatMultTranspose(auglag->Ae, auglag->Ce, auglag->Xwork);CHKERRQ(ierr); 696 ierr = VecAXPY(auglag->LgradX, auglag->mu, auglag->Xwork);CHKERRQ(ierr); 697 } 698 if (tao->ineq_constrained) { 699 /* compute scalar contributions */ 700 ierr = VecDot(auglag->Yi, auglag->Ci, &yiTcims);CHKERRQ(ierr); 701 ierr = VecDot(auglag->Ci, auglag->Ci, &cimsTcims);CHKERRQ(ierr); 702 /* dL/dX += yi^T Ai */ 703 ierr = MatMultTransposeAdd(auglag->Ai, auglag->Yi, auglag->LgradX, auglag->LgradX);CHKERRQ(ierr); 704 /* dL/dX += mu * (ci - s)^T Ai */ 705 ierr = MatMultTranspose(auglag->Ai, auglag->Ci, auglag->Xwork);CHKERRQ(ierr); 706 ierr = VecAXPY(auglag->LgradX, auglag->mu, auglag->Xwork);CHKERRQ(ierr); 707 /* dL/dS = -[yi + mu*(ci - s)] */ 708 ierr = VecWAXPY(auglag->LgradS, auglag->mu, auglag->Ci, auglag->Yi);CHKERRQ(ierr); 709 ierr = VecScale(auglag->LgradS, -1.0);CHKERRQ(ierr); 710 } 711 /* combine gradient together */ 712 ierr = TaoALMMCombinePrimal_Private(tao, auglag->LgradX, auglag->LgradS, auglag->G);CHKERRQ(ierr); 713 /* compute L = f + ye^T ce + yi^T (ci - s) + 0.5*mu*||ce||^2 + 0.5*mu*||ci - s||^2 */ 714 auglag->Lval = auglag->fval + yeTce + yiTcims + 0.5*auglag->mu*(ceTce + cimsTcims); 715 PetscFunctionReturn(0); 716 } 717 718 PetscErrorCode TaoALMMSubsolverObjective_Private(Tao tao, Vec P, PetscReal *Lval, void *ctx) 719 { 720 TAO_ALMM *auglag = (TAO_ALMM*)ctx; 721 PetscErrorCode ierr; 722 723 PetscFunctionBegin; 724 ierr = VecCopy(P, auglag->P);CHKERRQ(ierr); 725 ierr = (*auglag->sub_obj)(auglag->parent);CHKERRQ(ierr); 726 *Lval = auglag->Lval; 727 PetscFunctionReturn(0); 728 } 729 730 PetscErrorCode TaoALMMSubsolverObjectiveAndGradient_Private(Tao tao, Vec P, PetscReal *Lval, Vec G, void *ctx) 731 { 732 TAO_ALMM *auglag = (TAO_ALMM*)ctx; 733 PetscErrorCode ierr; 734 735 PetscFunctionBegin; 736 ierr = VecCopy(P, auglag->P);CHKERRQ(ierr); 737 ierr = (*auglag->sub_obj)(auglag->parent);CHKERRQ(ierr); 738 ierr = VecCopy(auglag->G, G);CHKERRQ(ierr); 739 *Lval = auglag->Lval; 740 PetscFunctionReturn(0); 741 } 742