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