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