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: }