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