xref: /petsc/src/sys/objects/state.c (revision bfe80ac4a46d58cb7760074b25f5e81b2f541d8a)
1 /*
2      Provides utility routines for manulating any type of PETSc object.
3 */
4 #include <petsc/private/petscimpl.h> /*I   "petscsys.h"    I*/
5 
6 /*@
7   PetscObjectStateGet - Gets the state of any `PetscObject`,
8   regardless of the type.
9 
10   Not Collective
11 
12   Input Parameter:
13 . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
14          cast with a (`PetscObject`), for example,
15          `PetscObjectStateGet`((`PetscObject`)mat,&state);
16 
17   Output Parameter:
18 . state - the object state
19 
20   Level: advanced
21 
22   Note:
23   Object state is an integer which gets increased every time
24   the object is changed. By saving and later querying the object state
25   one can determine whether information about the object is still current.
26   Currently, state is maintained for `Vec` and `Mat` objects.
27 
28 .seealso: `PetscObjectStateIncrease()`, `PetscObjectStateSet()`
29 @*/
30 PetscErrorCode PetscObjectStateGet(PetscObject obj, PetscObjectState *state)
31 {
32   PetscFunctionBegin;
33   PetscValidHeader(obj, 1);
34   PetscAssertPointer(state, 2);
35   *state = obj->state;
36   PetscFunctionReturn(PETSC_SUCCESS);
37 }
38 
39 /*@
40   PetscObjectStateSet - Sets the state of any `PetscObject`,
41   regardless of the type.
42 
43   Logically Collective
44 
45   Input Parameters:
46 + obj   - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
47          cast with a (`PetscObject`), for example,
48          `PetscObjectStateSet`((`PetscObject`)mat,state);
49 - state - the object state
50 
51   Level: advanced
52 
53   Note:
54   This function should be used with extreme caution. There is
55   essentially only one use for it: if the user calls `Mat`(`Vec`)GetRow(Array),
56   which increases the state, but does not alter the data, then this
57   routine can be used to reset the state.  Such a reset must be collective.
58 
59 .seealso: `PetscObjectStateGet()`, `PetscObjectStateIncrease()`
60 @*/
61 PetscErrorCode PetscObjectStateSet(PetscObject obj, PetscObjectState state)
62 {
63   PetscFunctionBegin;
64   PetscValidHeader(obj, 1);
65   obj->state = state;
66   PetscFunctionReturn(PETSC_SUCCESS);
67 }
68 
69 PetscInt PetscObjectComposedDataMax = 10;
70 
71 /*@C
72   PetscObjectComposedDataRegister - Get an available id for composing data with a `PetscObject`
73 
74   Not Collective
75 
76   Output Parameter:
77 . id - an identifier under which data can be stored
78 
79   Level: developer
80 
81   Notes:
82   You must keep this value (for example in a global variable) in order to attach the data to an object or access in an object.
83 
84   `PetscObjectCompose()` and  `PetscObjectQuery()` provide a way to attach any data to an object
85 
86 .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
87           `PetscObjectComposedDataGetInt()`, `PetscObject`,
88           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`,
89           `PetscObjectComposedDataSetScalarstar()`
90 @*/
91 PetscErrorCode PetscObjectComposedDataRegister(PetscInt *id)
92 {
93   static PetscInt globalcurrentstate = 0;
94 
95   PetscFunctionBegin;
96   PetscAssertPointer(id, 1);
97   *id = globalcurrentstate++;
98   if (globalcurrentstate > PetscObjectComposedDataMax) PetscObjectComposedDataMax += 10;
99   PetscFunctionReturn(PETSC_SUCCESS);
100 }
101 
102 static PetscErrorCode PetscObjectComposedDataIncrease_(PetscInt *id_max, char **composed, PetscObjectState **composed_state, size_t obj_size)
103 {
104   // must use char here since PetscCalloc2() and PetscMemcpy() use sizeof(**ptr), so if
105   // composed is void ** (to match PetscObjectComposedDataStarIncrease_()) that would expand to
106   // sizeof(void) which is illegal.
107   char             *ar = *composed;
108   PetscObjectState *ir = *composed_state;
109   const PetscInt    n = *id_max, new_n = PetscObjectComposedDataMax;
110   char             *new_ar;
111   PetscObjectState *new_ir;
112 
113   PetscFunctionBegin;
114   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of composed data ids: %" PetscInt_FMT " < 0", n);
115   PetscCall(PetscCalloc2(new_n * obj_size, &new_ar, new_n, &new_ir));
116   PetscCall(PetscMemcpy(new_ar, ar, n * obj_size));
117   PetscCall(PetscArraycpy(new_ir, ir, n));
118   PetscCall(PetscFree2(ar, ir));
119   *id_max         = new_n;
120   *composed       = new_ar;
121   *composed_state = new_ir;
122   PetscFunctionReturn(PETSC_SUCCESS);
123 }
124 
125 #define PetscObjectComposedDataIncrease(id_max, composed, composed_state) PetscObjectComposedDataIncrease_(id_max, (char **)(composed), composed_state, sizeof(**(composed)))
126 
127 static PetscErrorCode PetscObjectComposedDataStarIncrease_(PetscInt *id_max, void ***composed, PetscObjectState **composed_state, size_t obj_size)
128 {
129   void                  **ar = *composed;
130   const PetscObjectState *ir = *composed_state;
131   const PetscInt          n = *id_max, new_n = PetscObjectComposedDataMax;
132   void                  **new_ar;
133   PetscObjectState       *new_ir;
134 
135   PetscFunctionBegin;
136   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of composed star data ids: %" PetscInt_FMT " < 0", n);
137   PetscCall(PetscCalloc2(new_n, &new_ar, new_n, &new_ir));
138   PetscCall(PetscMemcpy(new_ar, ar, n * obj_size));
139   PetscCall(PetscArraycpy(new_ir, ir, n));
140   PetscCall(PetscFree2(ar, ir));
141   *id_max         = new_n;
142   *composed       = new_ar;
143   *composed_state = new_ir;
144   PetscFunctionReturn(PETSC_SUCCESS);
145 }
146 
147 #define PetscObjectComposedDataStarIncrease(id_max, composed, composed_state) PetscObjectComposedDataStarIncrease_(id_max, (void ***)(composed), composed_state, sizeof(**(composed)))
148 
149 PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject obj)
150 {
151   PetscFunctionBegin;
152   PetscCall(PetscObjectComposedDataIncrease(&obj->int_idmax, &obj->intcomposeddata, &obj->intcomposedstate));
153   PetscFunctionReturn(PETSC_SUCCESS);
154 }
155 
156 PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject obj)
157 {
158   PetscFunctionBegin;
159   PetscCall(PetscObjectComposedDataStarIncrease(&obj->intstar_idmax, &obj->intstarcomposeddata, &obj->intstarcomposedstate));
160   PetscFunctionReturn(PETSC_SUCCESS);
161 }
162 
163 PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject obj)
164 {
165   PetscFunctionBegin;
166   PetscCall(PetscObjectComposedDataIncrease(&obj->real_idmax, &obj->realcomposeddata, &obj->realcomposedstate));
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject obj)
171 {
172   PetscFunctionBegin;
173   PetscCall(PetscObjectComposedDataStarIncrease(&obj->realstar_idmax, &obj->realstarcomposeddata, &obj->realstarcomposedstate));
174   PetscFunctionReturn(PETSC_SUCCESS);
175 }
176 
177 PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject obj)
178 {
179   PetscFunctionBegin;
180 #if PetscDefined(USE_COMPLEX)
181   PetscCall(PetscObjectComposedDataIncrease(&obj->scalar_idmax, &obj->scalarcomposeddata, &obj->scalarcomposedstate));
182 #else
183   PetscCall(PetscObjectComposedDataIncreaseReal(obj));
184 #endif
185   PetscFunctionReturn(PETSC_SUCCESS);
186 }
187 
188 PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject obj)
189 {
190   PetscFunctionBegin;
191 #if PetscDefined(USE_COMPLEX)
192   PetscCall(PetscObjectComposedDataStarIncrease(&obj->scalarstar_idmax, &obj->scalarstarcomposeddata, &obj->scalarstarcomposedstate));
193 #else
194   PetscCall(PetscObjectComposedDataIncreaseRealstar(obj));
195 #endif
196   PetscFunctionReturn(PETSC_SUCCESS);
197 }
198 
199 /*@
200   PetscObjectGetId - get a unique object ID for the `PetscObject`
201 
202   Not Collective
203 
204   Input Parameter:
205 . obj - object
206 
207   Output Parameter:
208 . id - integer ID
209 
210   Level: developer
211 
212   Note:
213   The object ID may be different on different processes, but object IDs are never reused so local equality implies global equality.
214 
215 .seealso: `PetscObjectStateGet()`, `PetscObjectCompareId()`
216 @*/
217 PetscErrorCode PetscObjectGetId(PetscObject obj, PetscObjectId *id)
218 {
219   PetscFunctionBegin;
220   PetscValidHeader(obj, 1);
221   PetscAssertPointer(id, 2);
222   *id = obj->id;
223   PetscFunctionReturn(PETSC_SUCCESS);
224 }
225 
226 /*@
227   PetscObjectCompareId - compares the objects ID with a given id
228 
229   Not Collective
230 
231   Input Parameters:
232 + obj - object
233 - id  - integer ID
234 
235   Output Parameter:
236 . eq - the ids are equal
237 
238   Level: developer
239 
240   Note:
241   The object ID may be different on different processes, but object IDs are never reused so
242   local equality implies global equality.
243 
244 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
245 @*/
246 PetscErrorCode PetscObjectCompareId(PetscObject obj, PetscObjectId id, PetscBool *eq)
247 {
248   PetscObjectId oid;
249 
250   PetscFunctionBegin;
251   PetscValidHeader(obj, 1);
252   PetscAssertPointer(eq, 3);
253   PetscCall(PetscObjectGetId(obj, &oid));
254   *eq = (id == oid) ? PETSC_TRUE : PETSC_FALSE;
255   PetscFunctionReturn(PETSC_SUCCESS);
256 }
257