xref: /petsc/src/tao/constrained/impls/almm/almmutils.c (revision ccb4e88a40f0b86eaeca07ff64c64e4de2fae686)
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