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 /*@ 7 TaoALMMGetType - Retreive the augmented Lagrangian formulation type for the subproblem. 8 9 Input Parameters: 10 . tao - the Tao context for the TAOALMM solver 11 12 Output Parameters: 13 . type - augmented Lagragrangian type 14 15 Level: advanced 16 17 .seealso: TAOALMM, TaoALMMSetType(), TaoALMMType 18 @*/ 19 PetscErrorCode TaoALMMGetType(Tao tao, TaoALMMType *type) 20 { 21 PetscErrorCode ierr; 22 23 PetscFunctionBegin; 24 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 25 PetscValidPointer(type, 2); 26 ierr = PetscUseMethod(tao,"TaoALMMGetType_C",(Tao,TaoALMMType *),(tao,type));CHKERRQ(ierr); 27 PetscFunctionReturn(0); 28 } 29 30 PetscErrorCode TaoALMMGetType_Private(Tao tao, TaoALMMType *type) 31 { 32 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 33 34 PetscFunctionBegin; 35 *type = auglag->type; 36 PetscFunctionReturn(0); 37 } 38 39 /*@ 40 TaoALMMSetType - Determine the augmented Lagrangian formulation type for the subproblem. 41 42 Input Parameters: 43 + tao - the Tao context for the TAOALMM solver 44 - type - augmented Lagragrangian type 45 46 Level: advanced 47 48 .seealso: TAOALMM, TaoALMMGetType(), TaoALMMType 49 @*/ 50 PetscErrorCode TaoALMMSetType(Tao tao, TaoALMMType type) 51 { 52 PetscErrorCode ierr; 53 54 PetscFunctionBegin; 55 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 56 ierr = PetscTryMethod(tao,"TaoALMMSetType_C",(Tao,TaoALMMType),(tao,type));CHKERRQ(ierr); 57 PetscFunctionReturn(0); 58 } 59 60 PetscErrorCode TaoALMMSetType_Private(Tao tao, TaoALMMType type) 61 { 62 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 63 64 PetscFunctionBegin; 65 if (tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoALMMSetType() must be called before TaoSetUp()"); 66 auglag->type = type; 67 PetscFunctionReturn(0); 68 } 69 70 /*@ 71 TaoALMMGetSubsolver - Retrieve a pointer to the TAOALMM. 72 73 Input Parameters: 74 . tao - the Tao context for the TAOALMM solver 75 76 Output Parameter: 77 . subsolver - the Tao context for the subsolver 78 79 Level: advanced 80 81 .seealso: TAOALMM, TaoALMMSetSubsolver() 82 @*/ 83 PetscErrorCode TaoALMMGetSubsolver(Tao tao, Tao *subsolver) 84 { 85 PetscErrorCode ierr; 86 87 PetscFunctionBegin; 88 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 89 PetscValidPointer(subsolver, 2); 90 ierr = PetscUseMethod(tao,"TaoALMMGetSubsolver_C",(Tao,Tao *),(tao,subsolver));CHKERRQ(ierr); 91 PetscFunctionReturn(0); 92 } 93 94 PetscErrorCode TaoALMMGetSubsolver_Private(Tao tao, Tao *subsolver) 95 { 96 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 97 98 PetscFunctionBegin; 99 *subsolver = auglag->subsolver; 100 PetscFunctionReturn(0); 101 } 102 103 /*@ 104 TaoALMMSetSubsolver - Changes the subsolver inside TAOALMM with the user provided one. 105 106 Input Parameters: 107 + tao - the Tao context for the TAOALMM solver 108 - subsolver - the Tao context for the subsolver 109 110 Level: advanced 111 112 .seealso: TAOALMM, TaoALMMGetSubsolver() 113 @*/ 114 PetscErrorCode TaoALMMSetSubsolver(Tao tao, Tao subsolver) 115 { 116 PetscErrorCode ierr; 117 118 PetscFunctionBegin; 119 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 120 PetscValidHeaderSpecific(subsolver, TAO_CLASSID, 2); 121 ierr = PetscTryMethod(tao,"TaoALMMSetSubsolver_C",(Tao,Tao),(tao,subsolver));CHKERRQ(ierr); 122 PetscFunctionReturn(0); 123 } 124 125 PetscErrorCode TaoALMMSetSubsolver_Private(Tao tao, Tao subsolver) 126 { 127 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 128 PetscBool compatible; 129 PetscErrorCode ierr; 130 131 PetscFunctionBegin; 132 if (subsolver == auglag->subsolver) PetscFunctionReturn(0); 133 if (tao->bounded) { 134 ierr = PetscObjectTypeCompareAny((PetscObject)subsolver, &compatible, TAOSHELL, TAOBNCG, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, "");CHKERRQ(ierr); 135 if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a bound-constrained first-order method"); 136 } else { 137 ierr = PetscObjectTypeCompareAny((PetscObject)subsolver, &compatible, TAOSHELL, TAOCG, TAOLMVM, TAOBNCG, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, "");CHKERRQ(ierr); 138 if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a first-order method"); 139 } 140 if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a first-order method"); 141 ierr = PetscObjectReference((PetscObject)subsolver);CHKERRQ(ierr); 142 ierr = TaoDestroy(&auglag->subsolver);CHKERRQ(ierr); 143 auglag->subsolver = subsolver; 144 if (tao->setupcalled) { 145 ierr = TaoSetInitialVector(auglag->subsolver, auglag->P);CHKERRQ(ierr); 146 ierr = TaoSetObjectiveRoutine(auglag->subsolver, TaoALMMSubsolverObjective_Private, (void*)auglag);CHKERRQ(ierr); 147 ierr = TaoSetObjectiveAndGradientRoutine(auglag->subsolver, TaoALMMSubsolverObjectiveAndGradient_Private, (void*)auglag);CHKERRQ(ierr); 148 ierr = TaoSetVariableBounds(auglag->subsolver, auglag->PL, auglag->PU);CHKERRQ(ierr); 149 } 150 PetscFunctionReturn(0); 151 } 152 153 /*@ 154 TaoALMMGetMultipliers - Retreive a pointer to the Lagrange multipliers. 155 156 Input Parameters: 157 . tao - the Tao context for the TAOALMM solver 158 159 Output Parameters: 160 . Y - vector of Lagrange multipliers 161 162 Level: advanced 163 164 Notes: 165 For problems with both equality and inequality constraints, 166 the multipliers are combined together as Y = (Ye, Yi). Users 167 can recover copies of the subcomponents using index sets 168 provided by TaoALMMGetDualIS() and use VecGetSubVector(). 169 170 .seealso: TAOALMM, TaoALMMSetMultipliers(), TaoALMMGetDualIS() 171 @*/ 172 PetscErrorCode TaoALMMGetMultipliers(Tao tao, Vec *Y) 173 { 174 PetscErrorCode ierr; 175 176 PetscFunctionBegin; 177 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 178 PetscValidPointer(Y, 2); 179 ierr = PetscUseMethod(tao,"TaoALMMGetMultipliers_C",(Tao,Vec *),(tao,Y));CHKERRQ(ierr); 180 PetscFunctionReturn(0); 181 } 182 183 PetscErrorCode TaoALMMGetMultipliers_Private(Tao tao, Vec *Y) 184 { 185 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 186 187 PetscFunctionBegin; 188 if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for scatters to be constructed"); 189 *Y = auglag->Y; 190 PetscFunctionReturn(0); 191 } 192 193 /*@ 194 TaoALMMSetMultipliers - Set user-defined Lagrange multipliers. The vector type and 195 parallel structure of the given vectormust match equality and 196 inequality constraints. The vector must have a local size equal 197 to the sum of the local sizes for the constraint vectors, and a 198 global size equal to the sum of the global sizes of the constraint 199 vectors. 200 201 Input Parameters: 202 + tao - the Tao context for the TAOALMM solver 203 - Y - vector of Lagrange multipliers 204 205 Level: advanced 206 207 Notes: 208 This routine is only useful if the user wants to change the 209 parallel distribution of the combined dual vector in problems that 210 feature both equality and inequality constraints. For other tasks, 211 it is strongly recommended that the user retreive the dual vector 212 created by the solver using TaoALMMGetMultipliers(). 213 214 .seealso: TAOALMM, TaoALMMGetMultipliers() 215 @*/ 216 PetscErrorCode TaoALMMSetMultipliers(Tao tao, Vec Y) 217 { 218 PetscErrorCode ierr; 219 220 PetscFunctionBegin; 221 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 222 PetscValidHeaderSpecific(Y, VEC_CLASSID, 2); 223 ierr = PetscTryMethod(tao,"TaoALMMSetMultipliers_C",(Tao,Vec),(tao,Y));CHKERRQ(ierr); 224 PetscFunctionReturn(0); 225 } 226 227 PetscErrorCode TaoALMMSetMultipliers_Private(Tao tao, Vec Y) 228 { 229 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 230 VecType Ytype; 231 PetscInt Nuser, Neq, Nineq, N; 232 PetscBool same = PETSC_FALSE; 233 PetscErrorCode ierr; 234 235 PetscFunctionBegin; 236 /* no-op if user provides vector from TaoALMMGetMultipliers() */ 237 if (Y == auglag->Y) PetscFunctionReturn(0); 238 /* make sure vector type is same as equality and inequality constraints */ 239 if (tao->eq_constrained) { 240 ierr = VecGetType(tao->constraints_equality, &Ytype);CHKERRQ(ierr); 241 } else { 242 ierr = VecGetType(tao->constraints_inequality, &Ytype);CHKERRQ(ierr); 243 } 244 ierr = PetscObjectTypeCompare((PetscObject)Y, Ytype, &same);CHKERRQ(ierr); 245 if (!same) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector for multipliers is not the same type as constraint vectors"); 246 /* make sure global size matches sum of equality and inequality */ 247 if (tao->eq_constrained) { 248 ierr = VecGetSize(tao->constraints_equality, &Neq);CHKERRQ(ierr); 249 } else { 250 Neq = 0; 251 } 252 if (tao->ineq_constrained) { 253 ierr = VecGetSize(tao->constraints_inequality, &Nineq);CHKERRQ(ierr); 254 } else { 255 Nineq = 0; 256 } 257 N = Neq + Nineq; 258 ierr = VecGetSize(Y, &Nuser);CHKERRQ(ierr); 259 if (Nuser != N) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong global size"); 260 /* if there is only one type of constraint, then we need the local size to match too */ 261 if (Neq == 0) { 262 ierr = VecGetLocalSize(tao->constraints_inequality, &Nineq);CHKERRQ(ierr); 263 ierr = VecGetLocalSize(Y, &Nuser);CHKERRQ(ierr); 264 if (Nuser != Nineq) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong local size"); 265 } 266 if (Nineq == 0) { 267 ierr = VecGetLocalSize(tao->constraints_equality, &Neq);CHKERRQ(ierr); 268 ierr = VecGetLocalSize(Y, &Nuser);CHKERRQ(ierr); 269 if (Nuser != Neq) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong local size"); 270 } 271 /* if we got here, the given vector is compatible so we can replace the current one */ 272 ierr = PetscObjectReference((PetscObject)Y);CHKERRQ(ierr); 273 ierr = VecDestroy(&auglag->Y);CHKERRQ(ierr); 274 auglag->Y = Y; 275 /* if there are both types of constraints and the solver has already been set up, 276 then we need to regenerate VecScatter objects for the new combined dual vector */ 277 if (tao->setupcalled && tao->eq_constrained && tao->ineq_constrained) { 278 ierr = VecDestroy(&auglag->C);CHKERRQ(ierr); 279 ierr = VecDuplicate(auglag->Y, &auglag->C);CHKERRQ(ierr); 280 ierr = VecScatterDestroy(&auglag->Yscatter[0]);CHKERRQ(ierr); 281 ierr = VecScatterCreate(auglag->Y, auglag->Yis[0], auglag->Ye, NULL, &auglag->Yscatter[0]);CHKERRQ(ierr); 282 ierr = VecScatterDestroy(&auglag->Yscatter[1]);CHKERRQ(ierr); 283 ierr = VecScatterCreate(auglag->Y, auglag->Yis[1], auglag->Yi, NULL, &auglag->Yscatter[1]);CHKERRQ(ierr); 284 } 285 PetscFunctionReturn(0); 286 } 287 288 /*@ 289 TaoALMMGetPrimalIS - Retreive a pointer to the index set that identifies optimization 290 and slack variable components of the subsolver's solution vector. 291 Not valid for problems with only equality constraints. 292 293 Input Parameter: 294 . tao - the Tao context for the TAOALMM solver 295 296 Output Parameters: 297 + opt_is - index set associated with the optimization variables (NULL if not needed) 298 - slack_is - index set associated with the slack variables (NULL if not needed) 299 300 Level: advanced 301 302 .seealso: TAOALMM, TaoALMMGetPrimalVector() 303 @*/ 304 PetscErrorCode TaoALMMGetPrimalIS(Tao tao, IS *opt_is, IS *slack_is) 305 { 306 PetscErrorCode ierr; 307 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 310 ierr = PetscUseMethod(tao,"TaoALMMGetPrimalIS_C",(Tao,IS *,IS *),(tao,opt_is,slack_is));CHKERRQ(ierr); 311 PetscFunctionReturn(0); 312 } 313 314 PetscErrorCode TaoALMMGetPrimalIS_Private(Tao tao, IS *opt_is, IS *slack_is) 315 { 316 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 317 318 PetscFunctionBegin; 319 if (!tao->ineq_constrained) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Primal space has index sets only for inequality constrained problems"); 320 if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for index sets to be constructed"); 321 if (opt_is) *opt_is = auglag->Pis[0]; 322 if (slack_is) *slack_is = auglag->Pis[1]; 323 PetscFunctionReturn(0); 324 } 325 326 /*@ 327 TaoALMMGetDualIS - Retreive a pointer to the index set that identifies equality 328 and inequality constraint components of the dual vector returned 329 by TaoALMMGetMultipliers(). Not valid for problems with only one 330 type of constraint. 331 332 Input Parameter: 333 . tao - the Tao context for the TAOALMM solver 334 335 Output Parameters: 336 + eq_is - index set associated with the equality constraints (NULL if not needed) 337 - ineq_is - index set associated with the inequality constraints (NULL if not needed) 338 339 Level: advanced 340 341 .seealso: TAOALMM, TaoALMMGetMultipliers() 342 @*/ 343 PetscErrorCode TaoALMMGetDualIS(Tao tao, IS *eq_is, IS *ineq_is) 344 { 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 349 ierr = PetscUseMethod(tao,"TaoALMMGetDualIS_C",(Tao,IS *,IS *),(tao,eq_is,ineq_is));CHKERRQ(ierr); 350 PetscFunctionReturn(0); 351 } 352 353 PetscErrorCode TaoALMMGetDualIS_Private(Tao tao, IS *eq_is, IS *ineq_is) 354 { 355 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 356 357 PetscFunctionBegin; 358 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 359 if (!tao->ineq_constrained || !tao->ineq_constrained) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Dual space has index sets only when problem has both equality and inequality constraints"); 360 if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for index sets to be constructed"); 361 if (eq_is) *eq_is = auglag->Yis[0]; 362 if (ineq_is) *ineq_is = auglag->Yis[1]; 363 PetscFunctionReturn(0); 364 } 365