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 = TaoSetObjectiveAndGradientRoutine(auglag->subsolver, TaoALMMSubsolverObjectiveAndGradient_Private, (void*)auglag);CHKERRQ(ierr); 147 ierr = TaoSetVariableBounds(auglag->subsolver, auglag->PL, auglag->PU);CHKERRQ(ierr); 148 } 149 PetscFunctionReturn(0); 150 } 151 152 /*@ 153 TaoALMMGetMultipliers - Retreive a pointer to the Lagrange multipliers. 154 155 Input Parameters: 156 . tao - the Tao context for the TAOALMM solver 157 158 Output Parameters: 159 . Y - vector of Lagrange multipliers 160 161 Level: advanced 162 163 Notes: 164 For problems with both equality and inequality constraints, 165 the multipliers are combined together as Y = (Ye, Yi). Users 166 can recover copies of the subcomponents using index sets 167 provided by TaoALMMGetDualIS() and use VecGetSubVector(). 168 169 .seealso: TAOALMM, TaoALMMSetMultipliers(), TaoALMMGetDualIS() 170 @*/ 171 PetscErrorCode TaoALMMGetMultipliers(Tao tao, Vec *Y) 172 { 173 PetscErrorCode ierr; 174 175 PetscFunctionBegin; 176 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 177 PetscValidPointer(Y, 2); 178 ierr = PetscUseMethod(tao,"TaoALMMGetMultipliers_C",(Tao,Vec *),(tao,Y));CHKERRQ(ierr); 179 PetscFunctionReturn(0); 180 } 181 182 PetscErrorCode TaoALMMGetMultipliers_Private(Tao tao, Vec *Y) 183 { 184 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 185 186 PetscFunctionBegin; 187 if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for scatters to be constructed"); 188 *Y = auglag->Y; 189 PetscFunctionReturn(0); 190 } 191 192 /*@ 193 TaoALMMSetMultipliers - Set user-defined Lagrange multipliers. The vector type and 194 parallel structure of the given vectormust match equality and 195 inequality constraints. The vector must have a local size equal 196 to the sum of the local sizes for the constraint vectors, and a 197 global size equal to the sum of the global sizes of the constraint 198 vectors. 199 200 Input Parameters: 201 + tao - the Tao context for the TAOALMM solver 202 - Y - vector of Lagrange multipliers 203 204 Level: advanced 205 206 Notes: 207 This routine is only useful if the user wants to change the 208 parallel distribution of the combined dual vector in problems that 209 feature both equality and inequality constraints. For other tasks, 210 it is strongly recommended that the user retreive the dual vector 211 created by the solver using TaoALMMGetMultipliers(). 212 213 .seealso: TAOALMM, TaoALMMGetMultipliers() 214 @*/ 215 PetscErrorCode TaoALMMSetMultipliers(Tao tao, Vec Y) 216 { 217 PetscErrorCode ierr; 218 219 PetscFunctionBegin; 220 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 221 PetscValidHeaderSpecific(Y, VEC_CLASSID, 2); 222 ierr = PetscTryMethod(tao,"TaoALMMSetMultipliers_C",(Tao,Vec),(tao,Y));CHKERRQ(ierr); 223 PetscFunctionReturn(0); 224 } 225 226 PetscErrorCode TaoALMMSetMultipliers_Private(Tao tao, Vec Y) 227 { 228 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 229 VecType Ytype; 230 PetscInt Nuser, Neq, Nineq, N; 231 PetscBool same = PETSC_FALSE; 232 PetscErrorCode ierr; 233 234 PetscFunctionBegin; 235 /* no-op if user provides vector from TaoALMMGetMultipliers() */ 236 if (Y == auglag->Y) PetscFunctionReturn(0); 237 /* make sure vector type is same as equality and inequality constraints */ 238 if (tao->eq_constrained) { 239 ierr = VecGetType(tao->constraints_equality, &Ytype);CHKERRQ(ierr); 240 } else { 241 ierr = VecGetType(tao->constraints_inequality, &Ytype);CHKERRQ(ierr); 242 } 243 ierr = PetscObjectTypeCompare((PetscObject)Y, Ytype, &same);CHKERRQ(ierr); 244 if (!same) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector for multipliers is not the same type as constraint vectors"); 245 /* make sure global size matches sum of equality and inequality */ 246 if (tao->eq_constrained) { 247 ierr = VecGetSize(tao->constraints_equality, &Neq);CHKERRQ(ierr); 248 } else { 249 Neq = 0; 250 } 251 if (tao->ineq_constrained) { 252 ierr = VecGetSize(tao->constraints_inequality, &Nineq);CHKERRQ(ierr); 253 } else { 254 Nineq = 0; 255 } 256 N = Neq + Nineq; 257 ierr = VecGetSize(Y, &Nuser);CHKERRQ(ierr); 258 if (Nuser != N) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong global size"); 259 /* if there is only one type of constraint, then we need the local size to match too */ 260 if (Neq == 0) { 261 ierr = VecGetLocalSize(tao->constraints_inequality, &Nineq);CHKERRQ(ierr); 262 ierr = VecGetLocalSize(Y, &Nuser);CHKERRQ(ierr); 263 if (Nuser != Nineq) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong local size"); 264 } 265 if (Nineq == 0) { 266 ierr = VecGetLocalSize(tao->constraints_equality, &Neq);CHKERRQ(ierr); 267 ierr = VecGetLocalSize(Y, &Nuser);CHKERRQ(ierr); 268 if (Nuser != Neq) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong local size"); 269 } 270 /* if we got here, the given vector is compatible so we can replace the current one */ 271 ierr = PetscObjectReference((PetscObject)Y);CHKERRQ(ierr); 272 ierr = VecDestroy(&auglag->Y);CHKERRQ(ierr); 273 auglag->Y = Y; 274 /* if there are both types of constraints and the solver has already been set up, 275 then we need to regenerate VecScatter objects for the new combined dual vector */ 276 if (tao->setupcalled && tao->eq_constrained && tao->ineq_constrained) { 277 ierr = VecDestroy(&auglag->C);CHKERRQ(ierr); 278 ierr = VecDuplicate(auglag->Y, &auglag->C);CHKERRQ(ierr); 279 ierr = VecScatterDestroy(&auglag->Yscatter[0]);CHKERRQ(ierr); 280 ierr = VecScatterCreate(auglag->Y, auglag->Yis[0], auglag->Ye, NULL, &auglag->Yscatter[0]);CHKERRQ(ierr); 281 ierr = VecScatterDestroy(&auglag->Yscatter[1]);CHKERRQ(ierr); 282 ierr = VecScatterCreate(auglag->Y, auglag->Yis[1], auglag->Yi, NULL, &auglag->Yscatter[1]);CHKERRQ(ierr); 283 } 284 PetscFunctionReturn(0); 285 } 286 287 /*@ 288 TaoALMMGetPrimalIS - Retreive a pointer to the index set that identifies optimization 289 and slack variable components of the subsolver's solution vector. 290 Not valid for problems with only equality constraints. 291 292 Input Parameter: 293 . tao - the Tao context for the TAOALMM solver 294 295 Output Parameters: 296 + opt_is - index set associated with the optimization variables (NULL if not needed) 297 - slack_is - index set associated with the slack variables (NULL if not needed) 298 299 Level: advanced 300 301 .seealso: TAOALMM, TaoALMMGetPrimalVector() 302 @*/ 303 PetscErrorCode TaoALMMGetPrimalIS(Tao tao, IS *opt_is, IS *slack_is) 304 { 305 PetscErrorCode ierr; 306 307 PetscFunctionBegin; 308 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 309 ierr = PetscUseMethod(tao,"TaoALMMGetPrimalIS_C",(Tao,IS *,IS *),(tao,opt_is,slack_is));CHKERRQ(ierr); 310 PetscFunctionReturn(0); 311 } 312 313 PetscErrorCode TaoALMMGetPrimalIS_Private(Tao tao, IS *opt_is, IS *slack_is) 314 { 315 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 316 317 PetscFunctionBegin; 318 if (!tao->ineq_constrained) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "Primal space has index sets only for inequality constrained problems"); 319 if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for index sets to be constructed"); 320 if (!opt_is && !slack_is) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_NULL, "Both index set pointers cannot be NULL"); 321 if (opt_is) { 322 *opt_is = auglag->Pis[0]; 323 } 324 if (slack_is) { 325 *slack_is = auglag->Pis[1]; 326 } 327 PetscFunctionReturn(0); 328 } 329 330 /*@ 331 TaoALMMGetDualIS - Retreive a pointer to the index set that identifies equality 332 and inequality constraint components of the dual vector returned 333 by TaoALMMGetMultipliers(). Not valid for problems with only one 334 type of constraint. 335 336 Input Parameter: 337 . tao - the Tao context for the TAOALMM solver 338 339 Output Parameters: 340 + eq_is - index set associated with the equality constraints (NULL if not needed) 341 - ineq_is - index set associated with the inequality constraints (NULL if not needed) 342 343 Level: advanced 344 345 .seealso: TAOALMM, TaoALMMGetMultipliers() 346 @*/ 347 PetscErrorCode TaoALMMGetDualIS(Tao tao, IS *eq_is, IS *ineq_is) 348 { 349 PetscErrorCode ierr; 350 351 PetscFunctionBegin; 352 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 353 ierr = PetscUseMethod(tao,"TaoALMMGetDualIS_C",(Tao,IS *,IS *),(tao,eq_is,ineq_is));CHKERRQ(ierr); 354 PetscFunctionReturn(0); 355 } 356 357 PetscErrorCode TaoALMMGetDualIS_Private(Tao tao, IS *eq_is, IS *ineq_is) 358 { 359 TAO_ALMM *auglag = (TAO_ALMM*)tao->data; 360 361 PetscFunctionBegin; 362 PetscValidHeaderSpecific(tao, TAO_CLASSID, 1); 363 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"); 364 if (!tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetUp() must be called first for index sets to be constructed"); 365 if (!eq_is && !ineq_is) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_NULL, "Both index set pointers cannot be NULL"); 366 if (eq_is) { 367 *eq_is = auglag->Yis[0]; 368 } 369 if (ineq_is) { 370 *ineq_is = auglag->Yis[1]; 371 } 372 PetscFunctionReturn(0); 373 } 374