Actual source code: almmutils.c

  1: #include <../src/tao/constrained/impls/almm/almm.h>
  2: #include <petsctao.h>
  3: #include <petsc/private/petscimpl.h>
  4: #include <petsc/private/vecimpl.h>

  6: /*@
  7:    TaoALMMGetType - Retreive the augmented Lagrangian formulation type for the subproblem.

  9:    Input Parameters:
 10: .  tao - the Tao context for the TAOALMM solver

 12:    Output Parameters:
 13: .  type - augmented Lagragrangian type

 15:    Level: advanced

 17: .seealso: TAOALMM, TaoALMMSetType(), TaoALMMType
 18: @*/
 19: PetscErrorCode TaoALMMGetType(Tao tao, TaoALMMType *type)
 20: {

 26:   PetscUseMethod(tao,"TaoALMMGetType_C",(Tao,TaoALMMType *),(tao,type));
 27:   return(0);
 28: }

 30: PetscErrorCode TaoALMMGetType_Private(Tao tao, TaoALMMType *type)
 31: {
 32:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

 35:   *type = auglag->type;
 36:   return(0);
 37: }

 39: /*@
 40:    TaoALMMSetType - Determine the augmented Lagrangian formulation type for the subproblem.

 42:    Input Parameters:
 43: +  tao - the Tao context for the TAOALMM solver
 44: -  type - augmented Lagragrangian type

 46:    Level: advanced

 48: .seealso: TAOALMM, TaoALMMGetType(), TaoALMMType
 49: @*/
 50: PetscErrorCode TaoALMMSetType(Tao tao, TaoALMMType type)
 51: {
 52:   PetscErrorCode  ierr;

 56:   PetscTryMethod(tao,"TaoALMMSetType_C",(Tao,TaoALMMType),(tao,type));
 57:   return(0);
 58: }

 60: PetscErrorCode TaoALMMSetType_Private(Tao tao, TaoALMMType type)
 61: {
 62:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

 65:   if (tao->setupcalled) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoALMMSetType() must be called before TaoSetUp()");
 66:   auglag->type = type;
 67:   return(0);
 68: }

 70: /*@
 71:    TaoALMMGetSubsolver - Retrieve a pointer to the TAOALMM.

 73:    Input Parameters:
 74: .  tao - the Tao context for the TAOALMM solver

 76:    Output Parameter:
 77: .  subsolver - the Tao context for the subsolver

 79:    Level: advanced

 81: .seealso: TAOALMM, TaoALMMSetSubsolver()
 82: @*/
 83: PetscErrorCode TaoALMMGetSubsolver(Tao tao, Tao *subsolver)
 84: {
 85:   PetscErrorCode  ierr;

 90:   PetscUseMethod(tao,"TaoALMMGetSubsolver_C",(Tao,Tao *),(tao,subsolver));
 91:   return(0);
 92: }

 94: PetscErrorCode TaoALMMGetSubsolver_Private(Tao tao, Tao *subsolver)
 95: {
 96:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

 99:   *subsolver = auglag->subsolver;
100:   return(0);
101: }

103: /*@
104:    TaoALMMSetSubsolver - Changes the subsolver inside TAOALMM with the user provided one.

106:    Input Parameters:
107: +  tao - the Tao context for the TAOALMM solver
108: -  subsolver - the Tao context for the subsolver

110:    Level: advanced

112: .seealso: TAOALMM, TaoALMMGetSubsolver()
113: @*/
114: PetscErrorCode TaoALMMSetSubsolver(Tao tao, Tao subsolver)
115: {

121:    PetscTryMethod(tao,"TaoALMMSetSubsolver_C",(Tao,Tao),(tao,subsolver));
122:    return(0);
123: }

125: PetscErrorCode TaoALMMSetSubsolver_Private(Tao tao, Tao subsolver)
126: {
127:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;
128:   PetscBool       compatible;
129:   PetscErrorCode  ierr;

132:   if (subsolver == auglag->subsolver) return(0);
133:   if (tao->bounded) {
134:     PetscObjectTypeCompareAny((PetscObject)subsolver, &compatible, TAOSHELL, TAOBNCG, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, "");
135:     if (!compatible) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Subsolver must be a bound-constrained first-order method");
136:   } else {
137:     PetscObjectTypeCompareAny((PetscObject)subsolver, &compatible, TAOSHELL, TAOCG, TAOLMVM, TAOBNCG, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, "");
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:   PetscObjectReference((PetscObject)subsolver);
142:   TaoDestroy(&auglag->subsolver);
143:   auglag->subsolver = subsolver;
144:   if (tao->setupcalled) {
145:     TaoSetInitialVector(auglag->subsolver, auglag->P);
146:     TaoSetObjectiveAndGradientRoutine(auglag->subsolver, TaoALMMSubsolverObjectiveAndGradient_Private, (void*)auglag);
147:     TaoSetVariableBounds(auglag->subsolver, auglag->PL, auglag->PU);
148:   }
149:   return(0);
150: }

152: /*@
153:    TaoALMMGetMultipliers - Retreive a pointer to the Lagrange multipliers.

155:    Input Parameters:
156: .  tao - the Tao context for the TAOALMM solver

158:    Output Parameters:
159: .  Y - vector of Lagrange multipliers

161:    Level: advanced

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().

169: .seealso: TAOALMM, TaoALMMSetMultipliers(), TaoALMMGetDualIS()
170: @*/
171: PetscErrorCode TaoALMMGetMultipliers(Tao tao, Vec *Y)
172: {
173:   PetscErrorCode  ierr;

178:   PetscUseMethod(tao,"TaoALMMGetMultipliers_C",(Tao,Vec *),(tao,Y));
179:   return(0);
180: }

182: PetscErrorCode TaoALMMGetMultipliers_Private(Tao tao, Vec *Y)
183: {
184:   TAO_ALMM        *auglag = (TAO_ALMM*)tao->data;

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:   return(0);
190: }

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.

200:    Input Parameters:
201: +  tao - the Tao context for the TAOALMM solver
202: -  Y - vector of Lagrange multipliers

204:    Level: advanced

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().

213: .seealso: TAOALMM, TaoALMMGetMultipliers()
214: @*/
215: PetscErrorCode TaoALMMSetMultipliers(Tao tao, Vec Y)
216: {
217:   PetscErrorCode  ierr;

222:   PetscTryMethod(tao,"TaoALMMSetMultipliers_C",(Tao,Vec),(tao,Y));
223:   return(0);
224: }

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;

235:   /* no-op if user provides vector from TaoALMMGetMultipliers() */
236:   if (Y == auglag->Y) return(0);
237:   /* make sure vector type is same as equality and inequality constraints */
238:   if (tao->eq_constrained) {
239:     VecGetType(tao->constraints_equality, &Ytype);
240:   } else {
241:     VecGetType(tao->constraints_inequality, &Ytype);
242:   }
243:   PetscObjectTypeCompare((PetscObject)Y, Ytype, &same);
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:     VecGetSize(tao->constraints_equality, &Neq);
248:   } else {
249:     Neq = 0;
250:   }
251:   if (tao->ineq_constrained) {
252:     VecGetSize(tao->constraints_inequality, &Nineq);
253:   } else {
254:     Nineq = 0;
255:   }
256:   N = Neq + Nineq;
257:   VecGetSize(Y, &Nuser);
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:     VecGetLocalSize(tao->constraints_inequality, &Nineq);
262:     VecGetLocalSize(Y, &Nuser);
263:     if (Nuser != Nineq) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given vector has wrong local size");
264:   }
265:   if (Nineq == 0) {
266:     VecGetLocalSize(tao->constraints_equality, &Neq);
267:     VecGetLocalSize(Y, &Nuser);
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:   PetscObjectReference((PetscObject)Y);
272:   VecDestroy(&auglag->Y);
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:     VecDestroy(&auglag->C);
278:     VecDuplicate(auglag->Y, &auglag->C);
279:     VecScatterDestroy(&auglag->Yscatter[0]);
280:     VecScatterCreate(auglag->Y, auglag->Yis[0], auglag->Ye, NULL, &auglag->Yscatter[0]);
281:     VecScatterDestroy(&auglag->Yscatter[1]);
282:     VecScatterCreate(auglag->Y, auglag->Yis[1], auglag->Yi, NULL, &auglag->Yscatter[1]);
283:   }
284:   return(0);
285: }

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.

292:    Input Parameter:
293: .  tao - the Tao context for the TAOALMM solver

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)

299:    Level: advanced

301: .seealso: TAOALMM, TaoALMMGetPrimalVector()
302: @*/
303: PetscErrorCode TaoALMMGetPrimalIS(Tao tao, IS *opt_is, IS *slack_is)
304: {

309:   PetscUseMethod(tao,"TaoALMMGetPrimalIS_C",(Tao,IS *,IS *),(tao,opt_is,slack_is));
310:   return(0);
311: }

313: PetscErrorCode TaoALMMGetPrimalIS_Private(Tao tao, IS *opt_is, IS *slack_is)
314: {
315:   TAO_ALMM   *auglag = (TAO_ALMM*)tao->data;

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:   return(0);
328: }

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.

336:    Input Parameter:
337: .  tao - the Tao context for the TAOALMM solver

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)

343:    Level: advanced

345: .seealso: TAOALMM, TaoALMMGetMultipliers()
346: @*/
347: PetscErrorCode TaoALMMGetDualIS(Tao tao, IS *eq_is, IS *ineq_is)
348: {

353:    PetscUseMethod(tao,"TaoALMMGetDualIS_C",(Tao,IS *,IS *),(tao,eq_is,ineq_is));
354:    return(0);
355: }

357: PetscErrorCode TaoALMMGetDualIS_Private(Tao tao, IS *eq_is, IS *ineq_is)
358: {
359:   TAO_ALMM   *auglag = (TAO_ALMM*)tao->data;

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:   return(0);
373: }