xref: /petsc/src/dm/label/dmlabel.c (revision 5552b385b77b214b234683fbe1b434751e6350f0)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I      "petscdmlabel.h"   I*/
3ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h> /*I      "petscsection.h"   I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5ea844a1aSMatthew Knepley #include <petscsection.h>
6c58f1c22SToby Isaac 
79f6c5813SMatthew G. Knepley PetscFunctionList DMLabelList              = NULL;
89f6c5813SMatthew G. Knepley PetscBool         DMLabelRegisterAllCalled = PETSC_FALSE;
99f6c5813SMatthew G. Knepley 
10cc4c1da9SBarry Smith /*@
1120f4b53cSBarry Smith   DMLabelCreate - Create a `DMLabel` object, which is a multimap
12c58f1c22SToby Isaac 
135b5e7992SMatthew G. Knepley   Collective
145b5e7992SMatthew G. Knepley 
1560225df5SJacob Faibussowitsch   Input Parameters:
1620f4b53cSBarry Smith + comm - The communicator, usually `PETSC_COMM_SELF`
17d67d17b1SMatthew G. Knepley - name - The label name
18c58f1c22SToby Isaac 
1960225df5SJacob Faibussowitsch   Output Parameter:
2020f4b53cSBarry Smith . label - The `DMLabel`
21c58f1c22SToby Isaac 
22c58f1c22SToby Isaac   Level: beginner
23c58f1c22SToby Isaac 
2405ab7a9fSVaclav Hapla   Notes:
2520f4b53cSBarry Smith   The label name is actually usually the `PetscObject` name.
2620f4b53cSBarry Smith   One can get/set it with `PetscObjectGetName()`/`PetscObjectSetName()`.
2705ab7a9fSVaclav Hapla 
2820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`
29c58f1c22SToby Isaac @*/
30d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
31d71ae5a4SJacob Faibussowitsch {
32c58f1c22SToby Isaac   PetscFunctionBegin;
334f572ea9SToby Isaac   PetscAssertPointer(label, 3);
349566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
35c58f1c22SToby Isaac 
369566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*label, DMLABEL_CLASSID, "DMLabel", "DMLabel", "DM", comm, DMLabelDestroy, DMLabelView));
37c58f1c22SToby Isaac   (*label)->numStrata     = 0;
385aa44df4SToby Isaac   (*label)->defaultValue  = -1;
39c58f1c22SToby Isaac   (*label)->stratumValues = NULL;
40ad8374ffSToby Isaac   (*label)->validIS       = NULL;
41c58f1c22SToby Isaac   (*label)->stratumSizes  = NULL;
42c58f1c22SToby Isaac   (*label)->points        = NULL;
43c58f1c22SToby Isaac   (*label)->ht            = NULL;
44c58f1c22SToby Isaac   (*label)->pStart        = -1;
45c58f1c22SToby Isaac   (*label)->pEnd          = -1;
46c58f1c22SToby Isaac   (*label)->bt            = NULL;
479566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*label, name));
499f6c5813SMatthew G. Knepley   PetscCall(DMLabelSetType(*label, DMLABELCONCRETE));
503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
519f6c5813SMatthew G. Knepley }
529f6c5813SMatthew G. Knepley 
53cc4c1da9SBarry Smith /*@
549f6c5813SMatthew G. Knepley   DMLabelSetUp - SetUp a `DMLabel` object
559f6c5813SMatthew G. Knepley 
569f6c5813SMatthew G. Knepley   Collective
579f6c5813SMatthew G. Knepley 
5860225df5SJacob Faibussowitsch   Input Parameters:
599f6c5813SMatthew G. Knepley . label - The `DMLabel`
609f6c5813SMatthew G. Knepley 
619f6c5813SMatthew G. Knepley   Level: intermediate
629f6c5813SMatthew G. Knepley 
6320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
649f6c5813SMatthew G. Knepley @*/
659f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetUp(DMLabel label)
669f6c5813SMatthew G. Knepley {
679f6c5813SMatthew G. Knepley   PetscFunctionBegin;
689f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
699f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, setup);
703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71c58f1c22SToby Isaac }
72c58f1c22SToby Isaac 
73c58f1c22SToby Isaac /*
74c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
75c58f1c22SToby Isaac 
765b5e7992SMatthew G. Knepley   Not collective
775b5e7992SMatthew G. Knepley 
78c58f1c22SToby Isaac   Input parameter:
7920f4b53cSBarry Smith + label - The `DMLabel`
80c58f1c22SToby Isaac - v - The stratum value
81c58f1c22SToby Isaac 
82c58f1c22SToby Isaac   Output parameter:
8320f4b53cSBarry Smith . label - The `DMLabel` with stratum in sorted list format
84c58f1c22SToby Isaac 
85c58f1c22SToby Isaac   Level: developer
86c58f1c22SToby Isaac 
8720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
88c58f1c22SToby Isaac */
89d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
90d71ae5a4SJacob Faibussowitsch {
91277ea44aSLisandro Dalcin   IS       is;
92b9907514SLisandro Dalcin   PetscInt off = 0, *pointArray, p;
93c58f1c22SToby Isaac 
94c58f1c22SToby Isaac   PetscFunctionBegin;
954d86920dSPierre Jolivet   if ((PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) || label->readonly) PetscFunctionReturn(PETSC_SUCCESS);
961dca8a05SBarry Smith   PetscCheck(v >= 0 && v < label->numStrata, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeValid_Private", v);
979566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
999566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
1009566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
1019566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
102c58f1c22SToby Isaac   if (label->bt) {
103c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
104ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
10563a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
1069566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
107c58f1c22SToby Isaac     }
108c58f1c22SToby Isaac   }
109ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v] - 1] == pointArray[0] + label->stratumSizes[v] - 1) {
1109566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
1119566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
112ba2698f1SMatthew G. Knepley   } else {
1139566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
114ba2698f1SMatthew G. Knepley   }
1159566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)is, "indices"));
116277ea44aSLisandro Dalcin   label->points[v]  = is;
117ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
1189566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120c58f1c22SToby Isaac }
121c58f1c22SToby Isaac 
122c58f1c22SToby Isaac /*
123c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
124c58f1c22SToby Isaac 
12520f4b53cSBarry Smith   Not Collective
1265b5e7992SMatthew G. Knepley 
127c58f1c22SToby Isaac   Input parameter:
12820f4b53cSBarry Smith . label - The `DMLabel`
129c58f1c22SToby Isaac 
130c58f1c22SToby Isaac   Output parameter:
13120f4b53cSBarry Smith . label - The `DMLabel` with all strata in sorted list format
132c58f1c22SToby Isaac 
133c58f1c22SToby Isaac   Level: developer
134c58f1c22SToby Isaac 
13520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
136c58f1c22SToby Isaac */
137d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
138d71ae5a4SJacob Faibussowitsch {
139c58f1c22SToby Isaac   PetscInt v;
140c58f1c22SToby Isaac 
141c58f1c22SToby Isaac   PetscFunctionBegin;
14248a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeValid_Private(label, v));
1433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
144c58f1c22SToby Isaac }
145c58f1c22SToby Isaac 
146c58f1c22SToby Isaac /*
147c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
148c58f1c22SToby Isaac 
14920f4b53cSBarry Smith   Not Collective
1505b5e7992SMatthew G. Knepley 
151c58f1c22SToby Isaac   Input parameter:
15220f4b53cSBarry Smith + label - The `DMLabel`
153c58f1c22SToby Isaac - v - The stratum value
154c58f1c22SToby Isaac 
155c58f1c22SToby Isaac   Output parameter:
15620f4b53cSBarry Smith . label - The `DMLabel` with stratum in hash format
157c58f1c22SToby Isaac 
158c58f1c22SToby Isaac   Level: developer
159c58f1c22SToby Isaac 
16020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
161c58f1c22SToby Isaac */
162d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
163d71ae5a4SJacob Faibussowitsch {
164c58f1c22SToby Isaac   PetscInt        p;
165ad8374ffSToby Isaac   const PetscInt *points;
166c58f1c22SToby Isaac 
167c58f1c22SToby Isaac   PetscFunctionBegin;
1684d86920dSPierre Jolivet   if ((PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) || label->readonly) PetscFunctionReturn(PETSC_SUCCESS);
1691dca8a05SBarry Smith   PetscCheck(v >= 0 && v < label->numStrata, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeInvalid_Private", v);
170ad8374ffSToby Isaac   if (label->points[v]) {
1719566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
17248a46eb9SPierre Jolivet     for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
1739566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
174f4f49eeaSPierre Jolivet     PetscCall(ISDestroy(&label->points[v]));
175ad8374ffSToby Isaac   }
176ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
1773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
178c58f1c22SToby Isaac }
179c58f1c22SToby Isaac 
180d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelMakeAllInvalid_Internal(DMLabel label)
181d71ae5a4SJacob Faibussowitsch {
182695799ffSMatthew G. Knepley   PetscInt v;
183695799ffSMatthew G. Knepley 
184695799ffSMatthew G. Knepley   PetscFunctionBegin;
18548a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeInvalid_Private(label, v));
1863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
187695799ffSMatthew G. Knepley }
188695799ffSMatthew G. Knepley 
189b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
190b9907514SLisandro Dalcin   #define DMLABEL_LOOKUP_THRESHOLD 16
191b9907514SLisandro Dalcin #endif
192b9907514SLisandro Dalcin 
1939f6c5813SMatthew G. Knepley PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
194d71ae5a4SJacob Faibussowitsch {
1950c3c4a36SLisandro Dalcin   PetscInt v;
1960e79e033SBarry Smith 
1970c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1980e79e033SBarry Smith   *index = -1;
1999f6c5813SMatthew G. Knepley   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD || label->readonly) {
200b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
2019371c9d4SSatish Balay       if (label->stratumValues[v] == value) {
2029371c9d4SSatish Balay         *index = v;
2039371c9d4SSatish Balay         break;
2049371c9d4SSatish Balay       }
205b9907514SLisandro Dalcin   } else {
2069566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(label->hmap, value, index));
2070e79e033SBarry Smith   }
2089f6c5813SMatthew G. Knepley   if (PetscDefined(USE_DEBUG) && !label->readonly) { /* Check strata hash map consistency */
20990e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
2109566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(label->hmap, &len));
21108401ef6SPierre Jolivet     PetscCheck(len == label->numStrata, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
21290e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
2139566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(label->hmap, value, &loc));
21490e9b2aeSLisandro Dalcin     } else {
21590e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
2169371c9d4SSatish Balay         if (label->stratumValues[v] == value) {
2179371c9d4SSatish Balay           loc = v;
2189371c9d4SSatish Balay           break;
2199371c9d4SSatish Balay         }
22090e9b2aeSLisandro Dalcin     }
22108401ef6SPierre Jolivet     PetscCheck(loc == *index, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
22290e9b2aeSLisandro Dalcin   }
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2240c3c4a36SLisandro Dalcin }
2250c3c4a36SLisandro Dalcin 
226d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
227d71ae5a4SJacob Faibussowitsch {
228b9907514SLisandro Dalcin   PetscInt    v;
229b9907514SLisandro Dalcin   PetscInt   *tmpV;
230b9907514SLisandro Dalcin   PetscInt   *tmpS;
231b9907514SLisandro Dalcin   PetscHSetI *tmpH, ht;
232b9907514SLisandro Dalcin   IS         *tmpP, is;
233c58f1c22SToby Isaac   PetscBool  *tmpB;
234b9907514SLisandro Dalcin   PetscHMapI  hmap = label->hmap;
235c58f1c22SToby Isaac 
236c58f1c22SToby Isaac   PetscFunctionBegin;
237b9907514SLisandro Dalcin   v    = label->numStrata;
238b9907514SLisandro Dalcin   tmpV = label->stratumValues;
239b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
240b9907514SLisandro Dalcin   tmpH = label->ht;
241b9907514SLisandro Dalcin   tmpP = label->points;
242b9907514SLisandro Dalcin   tmpB = label->validIS;
2438e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2448e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2458e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2468e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2478e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2488e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpV), &tmpV));
2509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpS), &tmpS));
2519f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc((v + 1) * sizeof(*tmpH), &tmpH));
2529f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc((v + 1) * sizeof(*tmpP), &tmpP));
2539566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpB), &tmpB));
2549566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpV, oldV, v));
2559566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpS, oldS, v));
2569566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpH, oldH, v));
2579566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpP, oldP, v));
2589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpB, oldB, v));
2599566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldV));
2609566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldS));
2619566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldH));
2629566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldP));
2639566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldB));
2648e1f8cf0SLisandro Dalcin   }
265b9907514SLisandro Dalcin   label->numStrata     = v + 1;
266c58f1c22SToby Isaac   label->stratumValues = tmpV;
267c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
268c58f1c22SToby Isaac   label->ht            = tmpH;
269c58f1c22SToby Isaac   label->points        = tmpP;
270ad8374ffSToby Isaac   label->validIS       = tmpB;
2719566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
2729566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
2739566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(hmap, value, v));
274b9907514SLisandro Dalcin   tmpV[v] = value;
275b9907514SLisandro Dalcin   tmpS[v] = 0;
276b9907514SLisandro Dalcin   tmpH[v] = ht;
277b9907514SLisandro Dalcin   tmpP[v] = is;
278b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
2799566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
2800c3c4a36SLisandro Dalcin   *index = v;
2813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2820c3c4a36SLisandro Dalcin }
2830c3c4a36SLisandro Dalcin 
284d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
285d71ae5a4SJacob Faibussowitsch {
286b9907514SLisandro Dalcin   PetscFunctionBegin;
2879566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, index));
2889566063dSJacob Faibussowitsch   if (*index < 0) PetscCall(DMLabelNewStratum(label, value, index));
2893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
290b9907514SLisandro Dalcin }
291b9907514SLisandro Dalcin 
2929f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
293d71ae5a4SJacob Faibussowitsch {
2949e63cc69SVaclav Hapla   PetscFunctionBegin;
2959e63cc69SVaclav Hapla   *size = 0;
2963ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
2979f6c5813SMatthew G. Knepley   if (label->readonly || label->validIS[v]) {
2989e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
2999e63cc69SVaclav Hapla   } else {
3009566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(label->ht[v], size));
3019e63cc69SVaclav Hapla   }
3023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3039e63cc69SVaclav Hapla }
3049e63cc69SVaclav Hapla 
305b9907514SLisandro Dalcin /*@
30620f4b53cSBarry Smith   DMLabelAddStratum - Adds a new stratum value in a `DMLabel`
307b9907514SLisandro Dalcin 
308d8d19677SJose E. Roman   Input Parameters:
30920f4b53cSBarry Smith + label - The `DMLabel`
310b9907514SLisandro Dalcin - value - The stratum value
311b9907514SLisandro Dalcin 
312b9907514SLisandro Dalcin   Level: beginner
313b9907514SLisandro Dalcin 
31420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
315b9907514SLisandro Dalcin @*/
316d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
317d71ae5a4SJacob Faibussowitsch {
3180c3c4a36SLisandro Dalcin   PetscInt v;
3190c3c4a36SLisandro Dalcin 
3200c3c4a36SLisandro Dalcin   PetscFunctionBegin;
321d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
3229f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
3239566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
3243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
325b9907514SLisandro Dalcin }
326b9907514SLisandro Dalcin 
327b9907514SLisandro Dalcin /*@
32820f4b53cSBarry Smith   DMLabelAddStrata - Adds new stratum values in a `DMLabel`
329b9907514SLisandro Dalcin 
33020f4b53cSBarry Smith   Not Collective
3315b5e7992SMatthew G. Knepley 
332d8d19677SJose E. Roman   Input Parameters:
33320f4b53cSBarry Smith + label         - The `DMLabel`
334b9907514SLisandro Dalcin . numStrata     - The number of stratum values
335b9907514SLisandro Dalcin - stratumValues - The stratum values
336b9907514SLisandro Dalcin 
337b9907514SLisandro Dalcin   Level: beginner
338b9907514SLisandro Dalcin 
33920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
340b9907514SLisandro Dalcin @*/
341d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
342d71ae5a4SJacob Faibussowitsch {
343b9907514SLisandro Dalcin   PetscInt *values, v;
344b9907514SLisandro Dalcin 
345b9907514SLisandro Dalcin   PetscFunctionBegin;
346b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
3474f572ea9SToby Isaac   if (numStrata) PetscAssertPointer(stratumValues, 3);
3489f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
3499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numStrata, &values));
3509566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(values, stratumValues, numStrata));
3519566063dSJacob Faibussowitsch   PetscCall(PetscSortRemoveDupsInt(&numStrata, values));
352b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
353b9907514SLisandro Dalcin     PetscInt   *tmpV;
354b9907514SLisandro Dalcin     PetscInt   *tmpS;
355b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
356b9907514SLisandro Dalcin     IS         *tmpP, is;
357b9907514SLisandro Dalcin     PetscBool  *tmpB;
358b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
359b9907514SLisandro Dalcin 
3609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpV));
3619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpS));
3629f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(numStrata, &tmpH));
3639f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(numStrata, &tmpP));
3649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpB));
365b9907514SLisandro Dalcin     label->numStrata     = numStrata;
366b9907514SLisandro Dalcin     label->stratumValues = tmpV;
367b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
368b9907514SLisandro Dalcin     label->ht            = tmpH;
369b9907514SLisandro Dalcin     label->points        = tmpP;
370b9907514SLisandro Dalcin     label->validIS       = tmpB;
371b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3729566063dSJacob Faibussowitsch       PetscCall(PetscHSetICreate(&ht));
3739566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
3749566063dSJacob Faibussowitsch       PetscCall(PetscHMapISet(hmap, values[v], v));
375b9907514SLisandro Dalcin       tmpV[v] = values[v];
376b9907514SLisandro Dalcin       tmpS[v] = 0;
377b9907514SLisandro Dalcin       tmpH[v] = ht;
378b9907514SLisandro Dalcin       tmpP[v] = is;
379b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
380b9907514SLisandro Dalcin     }
3819566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
382b9907514SLisandro Dalcin   } else {
38348a46eb9SPierre Jolivet     for (v = 0; v < numStrata; ++v) PetscCall(DMLabelAddStratum(label, values[v]));
384b9907514SLisandro Dalcin   }
3859566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
3863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
387b9907514SLisandro Dalcin }
388b9907514SLisandro Dalcin 
389b9907514SLisandro Dalcin /*@
39020f4b53cSBarry Smith   DMLabelAddStrataIS - Adds new stratum values in a `DMLabel`
391b9907514SLisandro Dalcin 
39220f4b53cSBarry Smith   Not Collective
3935b5e7992SMatthew G. Knepley 
394d8d19677SJose E. Roman   Input Parameters:
39520f4b53cSBarry Smith + label   - The `DMLabel`
396b9907514SLisandro Dalcin - valueIS - Index set with stratum values
397b9907514SLisandro Dalcin 
398b9907514SLisandro Dalcin   Level: beginner
399b9907514SLisandro Dalcin 
40020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
401b9907514SLisandro Dalcin @*/
402d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
403d71ae5a4SJacob Faibussowitsch {
404b9907514SLisandro Dalcin   PetscInt        numStrata;
405b9907514SLisandro Dalcin   const PetscInt *stratumValues;
406b9907514SLisandro Dalcin 
407b9907514SLisandro Dalcin   PetscFunctionBegin;
408b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
409b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
4109f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
4119566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(valueIS, &numStrata));
4129566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valueIS, &stratumValues));
4139566063dSJacob Faibussowitsch   PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
4143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
415c58f1c22SToby Isaac }
416c58f1c22SToby Isaac 
4179f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelView_Concrete_Ascii(DMLabel label, PetscViewer viewer)
418d71ae5a4SJacob Faibussowitsch {
419c58f1c22SToby Isaac   PetscInt    v;
420c58f1c22SToby Isaac   PetscMPIInt rank;
421c58f1c22SToby Isaac 
422c58f1c22SToby Isaac   PetscFunctionBegin;
4239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
4249566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
425c58f1c22SToby Isaac   if (label) {
426d67d17b1SMatthew G. Knepley     const char *name;
427d67d17b1SMatthew G. Knepley 
4289566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
4299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
43063a3b9bcSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", label->pStart, label->pEnd));
431c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
432c58f1c22SToby Isaac       const PetscInt  value = label->stratumValues[v];
433ad8374ffSToby Isaac       const PetscInt *points;
434c58f1c22SToby Isaac       PetscInt        p;
435c58f1c22SToby Isaac 
4369566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
43748a46eb9SPierre Jolivet       for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, points[p], value));
4389566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
439c58f1c22SToby Isaac     }
440c58f1c22SToby Isaac   }
4419566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4429566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
4433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
444c58f1c22SToby Isaac }
445c58f1c22SToby Isaac 
44666976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelView_Concrete(DMLabel label, PetscViewer viewer)
4479f6c5813SMatthew G. Knepley {
4489f6c5813SMatthew G. Knepley   PetscBool iascii;
4499f6c5813SMatthew G. Knepley 
4509f6c5813SMatthew G. Knepley   PetscFunctionBegin;
4519f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4529f6c5813SMatthew G. Knepley   if (iascii) PetscCall(DMLabelView_Concrete_Ascii(label, viewer));
4533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4549f6c5813SMatthew G. Knepley }
4559f6c5813SMatthew G. Knepley 
456ffeef943SBarry Smith /*@
457c58f1c22SToby Isaac   DMLabelView - View the label
458c58f1c22SToby Isaac 
45920f4b53cSBarry Smith   Collective
4605b5e7992SMatthew G. Knepley 
461c58f1c22SToby Isaac   Input Parameters:
46220f4b53cSBarry Smith + label  - The `DMLabel`
46320f4b53cSBarry Smith - viewer - The `PetscViewer`
464c58f1c22SToby Isaac 
465c58f1c22SToby Isaac   Level: intermediate
466c58f1c22SToby Isaac 
46720f4b53cSBarry Smith .seealso: `DMLabel`, `PetscViewer`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
468c58f1c22SToby Isaac @*/
469d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
470d71ae5a4SJacob Faibussowitsch {
471c58f1c22SToby Isaac   PetscFunctionBegin;
472d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4739566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
474c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4759f6c5813SMatthew G. Knepley   PetscCall(DMLabelMakeAllValid_Private(label));
4769f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, view, viewer);
4773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
478c58f1c22SToby Isaac }
479c58f1c22SToby Isaac 
48084f0b6dfSMatthew G. Knepley /*@
48120f4b53cSBarry Smith   DMLabelReset - Destroys internal data structures in a `DMLabel`
482d67d17b1SMatthew G. Knepley 
48320f4b53cSBarry Smith   Not Collective
4845b5e7992SMatthew G. Knepley 
485d67d17b1SMatthew G. Knepley   Input Parameter:
48620f4b53cSBarry Smith . label - The `DMLabel`
487d67d17b1SMatthew G. Knepley 
488d67d17b1SMatthew G. Knepley   Level: beginner
489d67d17b1SMatthew G. Knepley 
49020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`, `DMLabelCreate()`
491d67d17b1SMatthew G. Knepley @*/
492d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelReset(DMLabel label)
493d71ae5a4SJacob Faibussowitsch {
494d67d17b1SMatthew G. Knepley   PetscInt v;
495d67d17b1SMatthew G. Knepley 
496d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
497d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
498d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
4999f6c5813SMatthew G. Knepley     if (label->ht[v]) PetscCall(PetscHSetIDestroy(&label->ht[v]));
5009566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
501d67d17b1SMatthew G. Knepley   }
502b9907514SLisandro Dalcin   label->numStrata = 0;
5039566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
5049566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
5059566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
5069566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
5079566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
5089566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
509b9907514SLisandro Dalcin   label->pStart = -1;
510b9907514SLisandro Dalcin   label->pEnd   = -1;
5119566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
5123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
513d67d17b1SMatthew G. Knepley }
514d67d17b1SMatthew G. Knepley 
515d67d17b1SMatthew G. Knepley /*@
51620f4b53cSBarry Smith   DMLabelDestroy - Destroys a `DMLabel`
51784f0b6dfSMatthew G. Knepley 
51820f4b53cSBarry Smith   Collective
5195b5e7992SMatthew G. Knepley 
52084f0b6dfSMatthew G. Knepley   Input Parameter:
52120f4b53cSBarry Smith . label - The `DMLabel`
52284f0b6dfSMatthew G. Knepley 
52384f0b6dfSMatthew G. Knepley   Level: beginner
52484f0b6dfSMatthew G. Knepley 
52520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelReset()`, `DMLabelCreate()`
52684f0b6dfSMatthew G. Knepley @*/
527d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
528d71ae5a4SJacob Faibussowitsch {
529c58f1c22SToby Isaac   PetscFunctionBegin;
5303ba16761SJacob Faibussowitsch   if (!*label) PetscFunctionReturn(PETSC_SUCCESS);
531f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 1);
532f4f49eeaSPierre Jolivet   if (--((PetscObject)*label)->refct > 0) {
5339371c9d4SSatish Balay     *label = NULL;
5343ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5359371c9d4SSatish Balay   }
5369566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5379566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5389566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
5393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
540c58f1c22SToby Isaac }
541c58f1c22SToby Isaac 
54266976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDuplicate_Concrete(DMLabel label, DMLabel *labelnew)
5439f6c5813SMatthew G. Knepley {
5449f6c5813SMatthew G. Knepley   PetscFunctionBegin;
5459f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
5469f6c5813SMatthew G. Knepley     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
547f4f49eeaSPierre Jolivet     PetscCall(PetscObjectReference((PetscObject)label->points[v]));
5489f6c5813SMatthew G. Knepley     (*labelnew)->points[v] = label->points[v];
5499f6c5813SMatthew G. Knepley   }
5509f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5519f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
5523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5539f6c5813SMatthew G. Knepley }
5549f6c5813SMatthew G. Knepley 
55584f0b6dfSMatthew G. Knepley /*@
55620f4b53cSBarry Smith   DMLabelDuplicate - Duplicates a `DMLabel`
55784f0b6dfSMatthew G. Knepley 
55820f4b53cSBarry Smith   Collective
5595b5e7992SMatthew G. Knepley 
56084f0b6dfSMatthew G. Knepley   Input Parameter:
56120f4b53cSBarry Smith . label - The `DMLabel`
56284f0b6dfSMatthew G. Knepley 
56384f0b6dfSMatthew G. Knepley   Output Parameter:
56420f4b53cSBarry Smith . labelnew - new label
56584f0b6dfSMatthew G. Knepley 
56684f0b6dfSMatthew G. Knepley   Level: intermediate
56784f0b6dfSMatthew G. Knepley 
56820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
56984f0b6dfSMatthew G. Knepley @*/
570d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
571d71ae5a4SJacob Faibussowitsch {
572d67d17b1SMatthew G. Knepley   const char *name;
573c58f1c22SToby Isaac 
574c58f1c22SToby Isaac   PetscFunctionBegin;
575d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5769566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5779566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
5789566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
579c58f1c22SToby Isaac 
580c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5815aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5828dcf10e8SMatthew G. Knepley   (*labelnew)->readonly     = label->readonly;
5839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5859f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->ht));
5869f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->points));
5879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
5889f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
589c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
590c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
591b9907514SLisandro Dalcin     (*labelnew)->validIS[v]       = PETSC_TRUE;
592c58f1c22SToby Isaac   }
593c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
594c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
595c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
5969f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, duplicate, labelnew);
5973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
598c58f1c22SToby Isaac }
599c58f1c22SToby Isaac 
600609dae6eSVaclav Hapla /*@C
60120f4b53cSBarry Smith   DMLabelCompare - Compare two `DMLabel` objects
602609dae6eSVaclav Hapla 
60320f4b53cSBarry Smith   Collective; No Fortran Support
604609dae6eSVaclav Hapla 
605609dae6eSVaclav Hapla   Input Parameters:
606f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
60720f4b53cSBarry Smith . l0   - First `DMLabel`
60820f4b53cSBarry Smith - l1   - Second `DMLabel`
609609dae6eSVaclav Hapla 
610a4e35b19SJacob Faibussowitsch   Output Parameters:
6115efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
6125efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
613609dae6eSVaclav Hapla 
614609dae6eSVaclav Hapla   Level: intermediate
615609dae6eSVaclav Hapla 
616609dae6eSVaclav Hapla   Notes:
6175efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
61820f4b53cSBarry Smith   If it is passed as `NULL` and difference is found, an error is thrown on all processes.
61920f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
620609dae6eSVaclav Hapla 
6215efe38ccSVaclav Hapla   The output message is set independently on each rank.
62220f4b53cSBarry Smith   It is set to `NULL` if no difference was found on the current rank. It must be freed by user.
62320f4b53cSBarry Smith   If message is passed as `NULL` and difference is found, the difference description is printed to stderr in synchronized manner.
62420f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
625609dae6eSVaclav Hapla 
626609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
627609dae6eSVaclav Hapla 
62820f4b53cSBarry Smith   The communicator needs to be specified because currently `DMLabel` can live on `PETSC_COMM_SELF` even if the underlying `DM` is parallel.
6295efe38ccSVaclav Hapla 
630a3b724e8SBarry Smith   Developer Note:
631a3b724e8SBarry Smith   Fortran stub cannot be generated automatically because `message` must be freed with `PetscFree()`
632a3b724e8SBarry Smith 
63320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
634609dae6eSVaclav Hapla @*/
635d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
636d71ae5a4SJacob Faibussowitsch {
637609dae6eSVaclav Hapla   const char *name0, *name1;
638609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6395efe38ccSVaclav Hapla   PetscBool   eq;
6405efe38ccSVaclav Hapla   PetscMPIInt rank;
641609dae6eSVaclav Hapla 
642609dae6eSVaclav Hapla   PetscFunctionBegin;
6435efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6445efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6454f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 4);
6464f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 5);
6479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6499566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
650609dae6eSVaclav Hapla   {
651609dae6eSVaclav Hapla     PetscInt v0, v1;
652609dae6eSVaclav Hapla 
6539566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6549566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6555efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
65648a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Default value of DMLabel l0 \"%s\" = %" PetscInt_FMT " != %" PetscInt_FMT " = Default value of DMLabel l1 \"%s\"", name0, v0, v1, name1));
657462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6585efe38ccSVaclav Hapla     if (!eq) goto finish;
659609dae6eSVaclav Hapla   }
660609dae6eSVaclav Hapla   {
661609dae6eSVaclav Hapla     IS is0, is1;
662609dae6eSVaclav Hapla 
6639566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6649566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6659566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6669566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6679566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
66848a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
669462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6705efe38ccSVaclav Hapla     if (!eq) goto finish;
671609dae6eSVaclav Hapla   }
672609dae6eSVaclav Hapla   {
673609dae6eSVaclav Hapla     PetscInt i, nValues;
674609dae6eSVaclav Hapla 
6759566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
676609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
677609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
678609dae6eSVaclav Hapla       PetscInt       n;
679609dae6eSVaclav Hapla       IS             is0, is1;
680609dae6eSVaclav Hapla 
6819566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
682609dae6eSVaclav Hapla       if (!n) continue;
6839566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6849566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6859566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6869566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6879566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6885efe38ccSVaclav Hapla       if (!eq) {
68963a3b9bcSJacob Faibussowitsch         PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum #%" PetscInt_FMT " with value %" PetscInt_FMT " contains different points in DMLabel l0 \"%s\" and DMLabel l1 \"%s\"", i, v, name0, name1));
6905efe38ccSVaclav Hapla         break;
691609dae6eSVaclav Hapla       }
692609dae6eSVaclav Hapla     }
693462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
694609dae6eSVaclav Hapla   }
695609dae6eSVaclav Hapla finish:
6965efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
697609dae6eSVaclav Hapla   if (message) {
698609dae6eSVaclav Hapla     *message = NULL;
69948a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
7005efe38ccSVaclav Hapla   } else {
70148a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
7029566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
7035efe38ccSVaclav Hapla   }
7045efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
7055efe38ccSVaclav Hapla   if (equal) *equal = eq;
70663a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
7073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
708609dae6eSVaclav Hapla }
709609dae6eSVaclav Hapla 
710c6a43d28SMatthew G. Knepley /*@
711c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
712c6a43d28SMatthew G. Knepley 
71320f4b53cSBarry Smith   Not Collective
7145b5e7992SMatthew G. Knepley 
715c6a43d28SMatthew G. Knepley   Input Parameter:
71620f4b53cSBarry Smith . label - The `DMLabel`
717c6a43d28SMatthew G. Knepley 
718c6a43d28SMatthew G. Knepley   Level: intermediate
719c6a43d28SMatthew G. Knepley 
72020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
721c6a43d28SMatthew G. Knepley @*/
722d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
723d71ae5a4SJacob Faibussowitsch {
7241690c2aeSBarry Smith   PetscInt pStart = PETSC_INT_MAX, pEnd = -1, v;
725c6a43d28SMatthew G. Knepley 
726c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
727c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7289566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
729c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
730c6a43d28SMatthew G. Knepley     const PetscInt *points;
731c6a43d28SMatthew G. Knepley     PetscInt        i;
732c6a43d28SMatthew G. Knepley 
7339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
734c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
735c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
736c6a43d28SMatthew G. Knepley 
737c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
738c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
739c6a43d28SMatthew G. Knepley     }
7409566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
741c6a43d28SMatthew G. Knepley   }
7421690c2aeSBarry Smith   label->pStart = pStart == PETSC_INT_MAX ? -1 : pStart;
743c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7449566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
7453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
746c6a43d28SMatthew G. Knepley }
747c6a43d28SMatthew G. Knepley 
748c6a43d28SMatthew G. Knepley /*@
749c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
750c6a43d28SMatthew G. Knepley 
75120f4b53cSBarry Smith   Not Collective
7525b5e7992SMatthew G. Knepley 
753c6a43d28SMatthew G. Knepley   Input Parameters:
75420f4b53cSBarry Smith + label  - The `DMLabel`
755c6a43d28SMatthew G. Knepley . pStart - The smallest point
756c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
757c6a43d28SMatthew G. Knepley 
758c6a43d28SMatthew G. Knepley   Level: intermediate
759c6a43d28SMatthew G. Knepley 
76020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
761c6a43d28SMatthew G. Knepley @*/
762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
763d71ae5a4SJacob Faibussowitsch {
764c58f1c22SToby Isaac   PetscInt v;
765c58f1c22SToby Isaac 
766c58f1c22SToby Isaac   PetscFunctionBegin;
767d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7689566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7699566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
770c58f1c22SToby Isaac   label->pStart = pStart;
771c58f1c22SToby Isaac   label->pEnd   = pEnd;
772c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7739566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
774c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
7759f6c5813SMatthew G. Knepley     IS              pointIS;
776ad8374ffSToby Isaac     const PetscInt *points;
777c58f1c22SToby Isaac     PetscInt        i;
778c58f1c22SToby Isaac 
7799f6c5813SMatthew G. Knepley     PetscUseTypeMethod(label, getstratumis, v, &pointIS);
7809f6c5813SMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
781c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
782ad8374ffSToby Isaac       const PetscInt point = points[i];
783c58f1c22SToby Isaac 
7849f6c5813SMatthew G. Knepley       PetscCheck(!(point < pStart) && !(point >= pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " in stratum %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->stratumValues[v], pStart, pEnd);
7859566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
786c58f1c22SToby Isaac     }
7879566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
7889f6c5813SMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
789c58f1c22SToby Isaac   }
7903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
791c58f1c22SToby Isaac }
792c58f1c22SToby Isaac 
793c6a43d28SMatthew G. Knepley /*@
794c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
795c6a43d28SMatthew G. Knepley 
79620f4b53cSBarry Smith   Not Collective
7975b5e7992SMatthew G. Knepley 
798c6a43d28SMatthew G. Knepley   Input Parameter:
79920f4b53cSBarry Smith . label - the `DMLabel`
800c6a43d28SMatthew G. Knepley 
801c6a43d28SMatthew G. Knepley   Level: intermediate
802c6a43d28SMatthew G. Knepley 
80320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
804c6a43d28SMatthew G. Knepley @*/
805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
806d71ae5a4SJacob Faibussowitsch {
807c58f1c22SToby Isaac   PetscFunctionBegin;
808d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
809c58f1c22SToby Isaac   label->pStart = -1;
810c58f1c22SToby Isaac   label->pEnd   = -1;
8119566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
8123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
813c58f1c22SToby Isaac }
814c58f1c22SToby Isaac 
815c58f1c22SToby Isaac /*@
816c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
817c6a43d28SMatthew G. Knepley 
81820f4b53cSBarry Smith   Not Collective
8195b5e7992SMatthew G. Knepley 
820c6a43d28SMatthew G. Knepley   Input Parameter:
82120f4b53cSBarry Smith . label - the `DMLabel`
822c6a43d28SMatthew G. Knepley 
823c6a43d28SMatthew G. Knepley   Output Parameters:
824c6a43d28SMatthew G. Knepley + pStart - The smallest point
825c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
826c6a43d28SMatthew G. Knepley 
827c6a43d28SMatthew G. Knepley   Level: intermediate
828c6a43d28SMatthew G. Knepley 
82920f4b53cSBarry Smith   Note:
83020f4b53cSBarry Smith   This will compute an index for the label if one does not exist.
83120f4b53cSBarry Smith 
83220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
833c6a43d28SMatthew G. Knepley @*/
834d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
835d71ae5a4SJacob Faibussowitsch {
836c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
837c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8389566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
839c6a43d28SMatthew G. Knepley   if (pStart) {
8404f572ea9SToby Isaac     PetscAssertPointer(pStart, 2);
841c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
842c6a43d28SMatthew G. Knepley   }
843c6a43d28SMatthew G. Knepley   if (pEnd) {
8444f572ea9SToby Isaac     PetscAssertPointer(pEnd, 3);
845c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
846c6a43d28SMatthew G. Knepley   }
8473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
848c6a43d28SMatthew G. Knepley }
849c6a43d28SMatthew G. Knepley 
850c6a43d28SMatthew G. Knepley /*@
851c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
852c58f1c22SToby Isaac 
85320f4b53cSBarry Smith   Not Collective
8545b5e7992SMatthew G. Knepley 
855c58f1c22SToby Isaac   Input Parameters:
85620f4b53cSBarry Smith + label - the `DMLabel`
857c58f1c22SToby Isaac - value - the value
858c58f1c22SToby Isaac 
859c58f1c22SToby Isaac   Output Parameter:
860c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
861c58f1c22SToby Isaac 
862c58f1c22SToby Isaac   Level: developer
863c58f1c22SToby Isaac 
86420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
865c58f1c22SToby Isaac @*/
866d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
867d71ae5a4SJacob Faibussowitsch {
868c58f1c22SToby Isaac   PetscInt v;
869c58f1c22SToby Isaac 
870c58f1c22SToby Isaac   PetscFunctionBegin;
871d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8724f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
8739566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8740c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
8753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
876c58f1c22SToby Isaac }
877c58f1c22SToby Isaac 
878c58f1c22SToby Isaac /*@
879c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
880c58f1c22SToby Isaac 
88120f4b53cSBarry Smith   Not Collective
8825b5e7992SMatthew G. Knepley 
883c58f1c22SToby Isaac   Input Parameters:
88420f4b53cSBarry Smith + label - the `DMLabel`
885c58f1c22SToby Isaac - point - the point
886c58f1c22SToby Isaac 
887c58f1c22SToby Isaac   Output Parameter:
888c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
889c58f1c22SToby Isaac 
890c58f1c22SToby Isaac   Level: developer
891c58f1c22SToby Isaac 
89220f4b53cSBarry Smith   Note:
89320f4b53cSBarry Smith   The user must call `DMLabelCreateIndex()` before this function.
89420f4b53cSBarry Smith 
89520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
896c58f1c22SToby Isaac @*/
897d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
898d71ae5a4SJacob Faibussowitsch {
899c58f1c22SToby Isaac   PetscFunctionBeginHot;
900d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9014f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
9029566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
90376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
90428b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
90563a3b9bcSJacob Faibussowitsch     PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
90676bd3646SJed Brown   }
907c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
9083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
909c58f1c22SToby Isaac }
910c58f1c22SToby Isaac 
911c58f1c22SToby Isaac /*@
912c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
913c58f1c22SToby Isaac 
91420f4b53cSBarry Smith   Not Collective
9155b5e7992SMatthew G. Knepley 
916c58f1c22SToby Isaac   Input Parameters:
91720f4b53cSBarry Smith + label - the `DMLabel`
918c58f1c22SToby Isaac . value - the stratum value
919c58f1c22SToby Isaac - point - the point
920c58f1c22SToby Isaac 
921c58f1c22SToby Isaac   Output Parameter:
922c58f1c22SToby Isaac . contains - true if the stratum contains the point
923c58f1c22SToby Isaac 
924c58f1c22SToby Isaac   Level: intermediate
925c58f1c22SToby Isaac 
92620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
927c58f1c22SToby Isaac @*/
928d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
929d71ae5a4SJacob Faibussowitsch {
9300c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
931d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9324f572ea9SToby Isaac   PetscAssertPointer(contains, 4);
933cffad2c9SToby Isaac   if (value == label->defaultValue) {
934cffad2c9SToby Isaac     PetscInt pointVal;
9350c3c4a36SLisandro Dalcin 
936cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
937cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
938cffad2c9SToby Isaac   } else {
939cffad2c9SToby Isaac     PetscInt v;
940cffad2c9SToby Isaac 
941cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
942cffad2c9SToby Isaac     if (v >= 0) {
9439f6c5813SMatthew G. Knepley       if (label->validIS[v] || label->readonly) {
9449f6c5813SMatthew G. Knepley         IS       is;
945c58f1c22SToby Isaac         PetscInt i;
946c58f1c22SToby Isaac 
9479f6c5813SMatthew G. Knepley         PetscUseTypeMethod(label, getstratumis, v, &is);
9482b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(is, point, &i));
9499f6c5813SMatthew G. Knepley         PetscCall(ISDestroy(&is));
950cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
951c58f1c22SToby Isaac       } else {
952cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
953cffad2c9SToby Isaac       }
954cffad2c9SToby Isaac     } else { // value is not present
955cffad2c9SToby Isaac       *contains = PETSC_FALSE;
956cffad2c9SToby Isaac     }
957c58f1c22SToby Isaac   }
9583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
959c58f1c22SToby Isaac }
960c58f1c22SToby Isaac 
96184f0b6dfSMatthew G. Knepley /*@
96220f4b53cSBarry Smith   DMLabelGetDefaultValue - Get the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9635aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9645aa44df4SToby Isaac 
96520f4b53cSBarry Smith   Not Collective
9665b5e7992SMatthew G. Knepley 
96760225df5SJacob Faibussowitsch   Input Parameter:
96820f4b53cSBarry Smith . label - a `DMLabel` object
9695aa44df4SToby Isaac 
97060225df5SJacob Faibussowitsch   Output Parameter:
9715aa44df4SToby Isaac . defaultValue - the default value
9725aa44df4SToby Isaac 
9735aa44df4SToby Isaac   Level: beginner
9745aa44df4SToby Isaac 
97520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
97684f0b6dfSMatthew G. Knepley @*/
977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
978d71ae5a4SJacob Faibussowitsch {
9795aa44df4SToby Isaac   PetscFunctionBegin;
980d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9815aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9835aa44df4SToby Isaac }
9845aa44df4SToby Isaac 
98584f0b6dfSMatthew G. Knepley /*@
98620f4b53cSBarry Smith   DMLabelSetDefaultValue - Set the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9875aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9885aa44df4SToby Isaac 
98920f4b53cSBarry Smith   Not Collective
9905b5e7992SMatthew G. Knepley 
99160225df5SJacob Faibussowitsch   Input Parameter:
99220f4b53cSBarry Smith . label - a `DMLabel` object
9935aa44df4SToby Isaac 
99460225df5SJacob Faibussowitsch   Output Parameter:
9955aa44df4SToby Isaac . defaultValue - the default value
9965aa44df4SToby Isaac 
9975aa44df4SToby Isaac   Level: beginner
9985aa44df4SToby Isaac 
99920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
100084f0b6dfSMatthew G. Knepley @*/
1001d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1002d71ae5a4SJacob Faibussowitsch {
10035aa44df4SToby Isaac   PetscFunctionBegin;
1004d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10055aa44df4SToby Isaac   label->defaultValue = defaultValue;
10063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10075aa44df4SToby Isaac }
10085aa44df4SToby Isaac 
1009c58f1c22SToby Isaac /*@
101020f4b53cSBarry Smith   DMLabelGetValue - Return the value a label assigns to a point, or the label's default value (which is initially -1, and can be changed with
101120f4b53cSBarry Smith   `DMLabelSetDefaultValue()`)
1012c58f1c22SToby Isaac 
101320f4b53cSBarry Smith   Not Collective
10145b5e7992SMatthew G. Knepley 
1015c58f1c22SToby Isaac   Input Parameters:
101620f4b53cSBarry Smith + label - the `DMLabel`
1017c58f1c22SToby Isaac - point - the point
1018c58f1c22SToby Isaac 
1019c58f1c22SToby Isaac   Output Parameter:
10208e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
1021c58f1c22SToby Isaac 
1022c58f1c22SToby Isaac   Level: intermediate
1023c58f1c22SToby Isaac 
102420f4b53cSBarry Smith   Note:
102520f4b53cSBarry Smith   A label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.
102620f4b53cSBarry Smith   Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
102720f4b53cSBarry Smith 
102820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1029c58f1c22SToby Isaac @*/
1030d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1031d71ae5a4SJacob Faibussowitsch {
1032c58f1c22SToby Isaac   PetscInt v;
1033c58f1c22SToby Isaac 
10340c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
1035d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10364f572ea9SToby Isaac   PetscAssertPointer(value, 3);
10375aa44df4SToby Isaac   *value = label->defaultValue;
1038c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
10399f6c5813SMatthew G. Knepley     if (label->validIS[v] || label->readonly) {
10409f6c5813SMatthew G. Knepley       IS       is;
1041c58f1c22SToby Isaac       PetscInt i;
1042c58f1c22SToby Isaac 
10439f6c5813SMatthew G. Knepley       PetscUseTypeMethod(label, getstratumis, v, &is);
10442b4d18a0SMatthew G. Knepley       PetscCall(ISLocate(label->points[v], point, &i));
10459f6c5813SMatthew G. Knepley       PetscCall(ISDestroy(&is));
1046c58f1c22SToby Isaac       if (i >= 0) {
1047c58f1c22SToby Isaac         *value = label->stratumValues[v];
1048c58f1c22SToby Isaac         break;
1049c58f1c22SToby Isaac       }
1050c58f1c22SToby Isaac     } else {
1051c58f1c22SToby Isaac       PetscBool has;
1052c58f1c22SToby Isaac 
10539566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1054c58f1c22SToby Isaac       if (has) {
1055c58f1c22SToby Isaac         *value = label->stratumValues[v];
1056c58f1c22SToby Isaac         break;
1057c58f1c22SToby Isaac       }
1058c58f1c22SToby Isaac     }
1059c58f1c22SToby Isaac   }
10603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1061c58f1c22SToby Isaac }
1062c58f1c22SToby Isaac 
1063c58f1c22SToby Isaac /*@
106420f4b53cSBarry Smith   DMLabelSetValue - Set the value a label assigns to a point.  If the value is the same as the label's default value (which is initially -1, and can
106520f4b53cSBarry Smith   be changed with `DMLabelSetDefaultValue()` to something different), then this function will do nothing.
1066c58f1c22SToby Isaac 
106720f4b53cSBarry Smith   Not Collective
10685b5e7992SMatthew G. Knepley 
1069c58f1c22SToby Isaac   Input Parameters:
107020f4b53cSBarry Smith + label - the `DMLabel`
1071c58f1c22SToby Isaac . point - the point
1072c58f1c22SToby Isaac - value - The point value
1073c58f1c22SToby Isaac 
1074c58f1c22SToby Isaac   Level: intermediate
1075c58f1c22SToby Isaac 
107620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1077c58f1c22SToby Isaac @*/
1078d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1079d71ae5a4SJacob Faibussowitsch {
1080c58f1c22SToby Isaac   PetscInt v;
1081c58f1c22SToby Isaac 
1082c58f1c22SToby Isaac   PetscFunctionBegin;
1083d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10840c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10853ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
10869f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
10879566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1088c58f1c22SToby Isaac   /* Set key */
10899566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10909566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
10913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1092c58f1c22SToby Isaac }
1093c58f1c22SToby Isaac 
1094c58f1c22SToby Isaac /*@
1095c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1096c58f1c22SToby Isaac 
109720f4b53cSBarry Smith   Not Collective
10985b5e7992SMatthew G. Knepley 
1099c58f1c22SToby Isaac   Input Parameters:
110020f4b53cSBarry Smith + label - the `DMLabel`
1101c58f1c22SToby Isaac . point - the point
1102c58f1c22SToby Isaac - value - The point value
1103c58f1c22SToby Isaac 
1104c58f1c22SToby Isaac   Level: intermediate
1105c58f1c22SToby Isaac 
110620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1107c58f1c22SToby Isaac @*/
1108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1109d71ae5a4SJacob Faibussowitsch {
1110ad8374ffSToby Isaac   PetscInt v;
1111c58f1c22SToby Isaac 
1112c58f1c22SToby Isaac   PetscFunctionBegin;
1113d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11149f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1115c58f1c22SToby Isaac   /* Find label value */
11169566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
11173ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
11180c3c4a36SLisandro Dalcin 
1119eeed21e7SToby Isaac   if (label->bt) {
112063a3b9bcSJacob Faibussowitsch     PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
11219566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1122eeed21e7SToby Isaac   }
11230c3c4a36SLisandro Dalcin 
11240c3c4a36SLisandro Dalcin   /* Delete key */
11259566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11269566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
11273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1128c58f1c22SToby Isaac }
1129c58f1c22SToby Isaac 
1130c58f1c22SToby Isaac /*@
113120f4b53cSBarry Smith   DMLabelInsertIS - Set all points in the `IS` to a value
1132c58f1c22SToby Isaac 
113320f4b53cSBarry Smith   Not Collective
11345b5e7992SMatthew G. Knepley 
1135c58f1c22SToby Isaac   Input Parameters:
113620f4b53cSBarry Smith + label - the `DMLabel`
11372fe279fdSBarry Smith . is    - the point `IS`
1138c58f1c22SToby Isaac - value - The point value
1139c58f1c22SToby Isaac 
1140c58f1c22SToby Isaac   Level: intermediate
1141c58f1c22SToby Isaac 
114220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1143c58f1c22SToby Isaac @*/
1144d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1145d71ae5a4SJacob Faibussowitsch {
11460c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1147c58f1c22SToby Isaac   const PetscInt *points;
1148c58f1c22SToby Isaac 
1149c58f1c22SToby Isaac   PetscFunctionBegin;
1150d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1151c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11520c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11533ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11549f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11559566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11560c3c4a36SLisandro Dalcin   /* Set keys */
11579566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11589566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11599566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11609566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11619566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
11623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1163c58f1c22SToby Isaac }
1164c58f1c22SToby Isaac 
116584f0b6dfSMatthew G. Knepley /*@
116620f4b53cSBarry Smith   DMLabelGetNumValues - Get the number of values that the `DMLabel` takes
116784f0b6dfSMatthew G. Knepley 
116820f4b53cSBarry Smith   Not Collective
11695b5e7992SMatthew G. Knepley 
117084f0b6dfSMatthew G. Knepley   Input Parameter:
117120f4b53cSBarry Smith . label - the `DMLabel`
117284f0b6dfSMatthew G. Knepley 
117301d2d390SJose E. Roman   Output Parameter:
117484f0b6dfSMatthew G. Knepley . numValues - the number of values
117584f0b6dfSMatthew G. Knepley 
117684f0b6dfSMatthew G. Knepley   Level: intermediate
117784f0b6dfSMatthew G. Knepley 
117820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
117984f0b6dfSMatthew G. Knepley @*/
1180d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1181d71ae5a4SJacob Faibussowitsch {
1182c58f1c22SToby Isaac   PetscFunctionBegin;
1183d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11844f572ea9SToby Isaac   PetscAssertPointer(numValues, 2);
1185c58f1c22SToby Isaac   *numValues = label->numStrata;
11863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1187c58f1c22SToby Isaac }
1188c58f1c22SToby Isaac 
118984f0b6dfSMatthew G. Knepley /*@
119020f4b53cSBarry Smith   DMLabelGetValueIS - Get an `IS` of all values that the `DMlabel` takes
119184f0b6dfSMatthew G. Knepley 
119220f4b53cSBarry Smith   Not Collective
11935b5e7992SMatthew G. Knepley 
119484f0b6dfSMatthew G. Knepley   Input Parameter:
119520f4b53cSBarry Smith . label - the `DMLabel`
119684f0b6dfSMatthew G. Knepley 
119701d2d390SJose E. Roman   Output Parameter:
119860225df5SJacob Faibussowitsch . values - the value `IS`
119984f0b6dfSMatthew G. Knepley 
120084f0b6dfSMatthew G. Knepley   Level: intermediate
120184f0b6dfSMatthew G. Knepley 
12021d04cbbeSVaclav Hapla   Notes:
120320f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
120420f4b53cSBarry Smith   Strata which are allocated but empty [`DMLabelGetStratumSize()` yields 0] are counted.
120520f4b53cSBarry Smith   If you need to count only nonempty strata, use `DMLabelGetNonEmptyStratumValuesIS()`.
12061d04cbbeSVaclav Hapla 
120720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
120884f0b6dfSMatthew G. Knepley @*/
1209d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1210d71ae5a4SJacob Faibussowitsch {
1211c58f1c22SToby Isaac   PetscFunctionBegin;
1212d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12134f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12149566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1216c58f1c22SToby Isaac }
1217c58f1c22SToby Isaac 
121884f0b6dfSMatthew G. Knepley /*@
12198696263dSMatthew G. Knepley   DMLabelGetValueBounds - Return the smallest and largest value in the label
12208696263dSMatthew G. Knepley 
12218696263dSMatthew G. Knepley   Not Collective
12228696263dSMatthew G. Knepley 
12238696263dSMatthew G. Knepley   Input Parameter:
12248696263dSMatthew G. Knepley . label - the `DMLabel`
12258696263dSMatthew G. Knepley 
12268696263dSMatthew G. Knepley   Output Parameters:
12278696263dSMatthew G. Knepley + minValue - The smallest value
12288696263dSMatthew G. Knepley - maxValue - The largest value
12298696263dSMatthew G. Knepley 
12308696263dSMatthew G. Knepley   Level: intermediate
12318696263dSMatthew G. Knepley 
12328696263dSMatthew G. Knepley .seealso: `DMLabel`, `DM`, `DMLabelGetBounds()`, `DMLabelGetValue()`, `DMLabelSetValue()`
12338696263dSMatthew G. Knepley @*/
12348696263dSMatthew G. Knepley PetscErrorCode DMLabelGetValueBounds(DMLabel label, PetscInt *minValue, PetscInt *maxValue)
12358696263dSMatthew G. Knepley {
12361690c2aeSBarry Smith   PetscInt min = PETSC_INT_MAX, max = PETSC_INT_MIN;
12378696263dSMatthew G. Knepley 
12388696263dSMatthew G. Knepley   PetscFunctionBegin;
12398696263dSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12408696263dSMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
12418696263dSMatthew G. Knepley     min = PetscMin(min, label->stratumValues[v]);
12428696263dSMatthew G. Knepley     max = PetscMax(max, label->stratumValues[v]);
12438696263dSMatthew G. Knepley   }
12448696263dSMatthew G. Knepley   if (minValue) {
12458696263dSMatthew G. Knepley     PetscAssertPointer(minValue, 2);
12468696263dSMatthew G. Knepley     *minValue = min;
12478696263dSMatthew G. Knepley   }
12488696263dSMatthew G. Knepley   if (maxValue) {
12498696263dSMatthew G. Knepley     PetscAssertPointer(maxValue, 3);
12508696263dSMatthew G. Knepley     *maxValue = max;
12518696263dSMatthew G. Knepley   }
12528696263dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
12538696263dSMatthew G. Knepley }
12548696263dSMatthew G. Knepley 
12558696263dSMatthew G. Knepley /*@
125620f4b53cSBarry Smith   DMLabelGetNonEmptyStratumValuesIS - Get an `IS` of all values that the `DMlabel` takes
12571d04cbbeSVaclav Hapla 
125820f4b53cSBarry Smith   Not Collective
12591d04cbbeSVaclav Hapla 
12601d04cbbeSVaclav Hapla   Input Parameter:
126120f4b53cSBarry Smith . label - the `DMLabel`
12621d04cbbeSVaclav Hapla 
1263d5b43468SJose E. Roman   Output Parameter:
126460225df5SJacob Faibussowitsch . values - the value `IS`
12651d04cbbeSVaclav Hapla 
12661d04cbbeSVaclav Hapla   Level: intermediate
12671d04cbbeSVaclav Hapla 
12681d04cbbeSVaclav Hapla   Notes:
126920f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
127020f4b53cSBarry Smith   This is similar to `DMLabelGetValueIS()` but counts only nonempty strata.
12711d04cbbeSVaclav Hapla 
127220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
12731d04cbbeSVaclav Hapla @*/
1274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1275d71ae5a4SJacob Faibussowitsch {
12761d04cbbeSVaclav Hapla   PetscInt  i, j;
12771d04cbbeSVaclav Hapla   PetscInt *valuesArr;
12781d04cbbeSVaclav Hapla 
12791d04cbbeSVaclav Hapla   PetscFunctionBegin;
12801d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12814f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
12831d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
12841d04cbbeSVaclav Hapla     PetscInt n;
12851d04cbbeSVaclav Hapla 
12869566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
12871d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
12881d04cbbeSVaclav Hapla   }
12891d04cbbeSVaclav Hapla   if (j == label->numStrata) {
12909566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12911d04cbbeSVaclav Hapla   } else {
12929566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
12931d04cbbeSVaclav Hapla   }
12949566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
12953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12961d04cbbeSVaclav Hapla }
12971d04cbbeSVaclav Hapla 
12981d04cbbeSVaclav Hapla /*@
129920f4b53cSBarry Smith   DMLabelGetValueIndex - Get the index of a given value in the list of values for the `DMlabel`, or -1 if it is not present
1300d123abd9SMatthew G. Knepley 
130120f4b53cSBarry Smith   Not Collective
1302d123abd9SMatthew G. Knepley 
1303d123abd9SMatthew G. Knepley   Input Parameters:
130420f4b53cSBarry Smith + label - the `DMLabel`
130597bb3fdcSJose E. Roman - value - the value
1306d123abd9SMatthew G. Knepley 
130701d2d390SJose E. Roman   Output Parameter:
1308d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1309d123abd9SMatthew G. Knepley 
1310d123abd9SMatthew G. Knepley   Level: intermediate
1311d123abd9SMatthew G. Knepley 
131220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1313d123abd9SMatthew G. Knepley @*/
1314d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1315d71ae5a4SJacob Faibussowitsch {
1316d123abd9SMatthew G. Knepley   PetscInt v;
1317d123abd9SMatthew G. Knepley 
1318d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1319d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13204f572ea9SToby Isaac   PetscAssertPointer(index, 3);
1321d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
13229371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
13239371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1324d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1325d123abd9SMatthew G. Knepley   else *index = v;
13263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1327d123abd9SMatthew G. Knepley }
1328d123abd9SMatthew G. Knepley 
1329d123abd9SMatthew G. Knepley /*@
133084f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
133184f0b6dfSMatthew G. Knepley 
133220f4b53cSBarry Smith   Not Collective
13335b5e7992SMatthew G. Knepley 
133484f0b6dfSMatthew G. Knepley   Input Parameters:
133520f4b53cSBarry Smith + label - the `DMLabel`
133684f0b6dfSMatthew G. Knepley - value - the stratum value
133784f0b6dfSMatthew G. Knepley 
133801d2d390SJose E. Roman   Output Parameter:
133984f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
134084f0b6dfSMatthew G. Knepley 
134184f0b6dfSMatthew G. Knepley   Level: intermediate
134284f0b6dfSMatthew G. Knepley 
134320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
134484f0b6dfSMatthew G. Knepley @*/
1345d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1346d71ae5a4SJacob Faibussowitsch {
1347fada774cSMatthew G. Knepley   PetscInt v;
1348fada774cSMatthew G. Knepley 
1349fada774cSMatthew G. Knepley   PetscFunctionBegin;
1350d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13514f572ea9SToby Isaac   PetscAssertPointer(exists, 3);
13529566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13530c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
13543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1355fada774cSMatthew G. Knepley }
1356fada774cSMatthew G. Knepley 
135784f0b6dfSMatthew G. Knepley /*@
135884f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
135984f0b6dfSMatthew G. Knepley 
136020f4b53cSBarry Smith   Not Collective
13615b5e7992SMatthew G. Knepley 
136284f0b6dfSMatthew G. Knepley   Input Parameters:
136320f4b53cSBarry Smith + label - the `DMLabel`
136484f0b6dfSMatthew G. Knepley - value - the stratum value
136584f0b6dfSMatthew G. Knepley 
136601d2d390SJose E. Roman   Output Parameter:
136784f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
136884f0b6dfSMatthew G. Knepley 
136984f0b6dfSMatthew G. Knepley   Level: intermediate
137084f0b6dfSMatthew G. Knepley 
137120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
137284f0b6dfSMatthew G. Knepley @*/
1373d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1374d71ae5a4SJacob Faibussowitsch {
1375c58f1c22SToby Isaac   PetscInt v;
1376c58f1c22SToby Isaac 
1377c58f1c22SToby Isaac   PetscFunctionBegin;
1378d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13794f572ea9SToby Isaac   PetscAssertPointer(size, 3);
13809566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13819566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
13823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1383c58f1c22SToby Isaac }
1384c58f1c22SToby Isaac 
138584f0b6dfSMatthew G. Knepley /*@
138684f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
138784f0b6dfSMatthew G. Knepley 
138820f4b53cSBarry Smith   Not Collective
13895b5e7992SMatthew G. Knepley 
139084f0b6dfSMatthew G. Knepley   Input Parameters:
139120f4b53cSBarry Smith + label - the `DMLabel`
139284f0b6dfSMatthew G. Knepley - value - the stratum value
139384f0b6dfSMatthew G. Knepley 
139401d2d390SJose E. Roman   Output Parameters:
139584f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
139684f0b6dfSMatthew G. Knepley - end   - the largest point in the stratum
139784f0b6dfSMatthew G. Knepley 
139884f0b6dfSMatthew G. Knepley   Level: intermediate
139984f0b6dfSMatthew G. Knepley 
140020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
140184f0b6dfSMatthew G. Knepley @*/
1402d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1403d71ae5a4SJacob Faibussowitsch {
14049f6c5813SMatthew G. Knepley   IS       is;
14050c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1406c58f1c22SToby Isaac 
1407c58f1c22SToby Isaac   PetscFunctionBegin;
1408d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14099371c9d4SSatish Balay   if (start) {
14104f572ea9SToby Isaac     PetscAssertPointer(start, 3);
14119371c9d4SSatish Balay     *start = -1;
14129371c9d4SSatish Balay   }
14139371c9d4SSatish Balay   if (end) {
14144f572ea9SToby Isaac     PetscAssertPointer(end, 4);
14159371c9d4SSatish Balay     *end = -1;
14169371c9d4SSatish Balay   }
14179566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14183ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14199566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14203ba16761SJacob Faibussowitsch   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
14219f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &is);
14229f6c5813SMatthew G. Knepley   PetscCall(ISGetMinMax(is, &min, &max));
14239f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&is));
1424d6cb179aSToby Isaac   if (start) *start = min;
1425d6cb179aSToby Isaac   if (end) *end = max + 1;
14263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1427c58f1c22SToby Isaac }
1428c58f1c22SToby Isaac 
142966976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
14309f6c5813SMatthew G. Knepley {
14319f6c5813SMatthew G. Knepley   PetscFunctionBegin;
14329f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
14339f6c5813SMatthew G. Knepley   *pointIS = label->points[v];
14343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14359f6c5813SMatthew G. Knepley }
14369f6c5813SMatthew G. Knepley 
143784f0b6dfSMatthew G. Knepley /*@
143820f4b53cSBarry Smith   DMLabelGetStratumIS - Get an `IS` with the stratum points
143984f0b6dfSMatthew G. Knepley 
144020f4b53cSBarry Smith   Not Collective
14415b5e7992SMatthew G. Knepley 
144284f0b6dfSMatthew G. Knepley   Input Parameters:
144320f4b53cSBarry Smith + label - the `DMLabel`
144484f0b6dfSMatthew G. Knepley - value - the stratum value
144584f0b6dfSMatthew G. Knepley 
144601d2d390SJose E. Roman   Output Parameter:
144784f0b6dfSMatthew G. Knepley . points - The stratum points
144884f0b6dfSMatthew G. Knepley 
144984f0b6dfSMatthew G. Knepley   Level: intermediate
145084f0b6dfSMatthew G. Knepley 
1451593ce467SVaclav Hapla   Notes:
145220f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
145320f4b53cSBarry Smith   Returns `NULL` if the stratum is empty.
1454593ce467SVaclav Hapla 
145520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
145684f0b6dfSMatthew G. Knepley @*/
1457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1458d71ae5a4SJacob Faibussowitsch {
1459c58f1c22SToby Isaac   PetscInt v;
1460c58f1c22SToby Isaac 
1461c58f1c22SToby Isaac   PetscFunctionBegin;
1462d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14634f572ea9SToby Isaac   PetscAssertPointer(points, 3);
1464c58f1c22SToby Isaac   *points = NULL;
14659566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14663ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14679566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14689f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, points);
14693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1470c58f1c22SToby Isaac }
1471c58f1c22SToby Isaac 
147284f0b6dfSMatthew G. Knepley /*@
147320f4b53cSBarry Smith   DMLabelSetStratumIS - Set the stratum points using an `IS`
147484f0b6dfSMatthew G. Knepley 
147520f4b53cSBarry Smith   Not Collective
14765b5e7992SMatthew G. Knepley 
147784f0b6dfSMatthew G. Knepley   Input Parameters:
147820f4b53cSBarry Smith + label - the `DMLabel`
147984f0b6dfSMatthew G. Knepley . value - the stratum value
148060225df5SJacob Faibussowitsch - is    - The stratum points
148184f0b6dfSMatthew G. Knepley 
148284f0b6dfSMatthew G. Knepley   Level: intermediate
148384f0b6dfSMatthew G. Knepley 
148420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
148584f0b6dfSMatthew G. Knepley @*/
1486d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1487d71ae5a4SJacob Faibussowitsch {
14880c3c4a36SLisandro Dalcin   PetscInt v;
14894de306b1SToby Isaac 
14904de306b1SToby Isaac   PetscFunctionBegin;
1491d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1492d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
14939f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
14949566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
14953ba16761SJacob Faibussowitsch   if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
14969566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
1497f4f49eeaSPierre Jolivet   PetscCall(ISGetLocalSize(is, &label->stratumSizes[v]));
14989566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
1499f4f49eeaSPierre Jolivet   PetscCall(ISDestroy(&label->points[v]));
15000c3c4a36SLisandro Dalcin   label->points[v]  = is;
15010c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
15029566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
15034de306b1SToby Isaac   if (label->bt) {
15044de306b1SToby Isaac     const PetscInt *points;
15054de306b1SToby Isaac     PetscInt        p;
15064de306b1SToby Isaac 
15079566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
15084de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
15094de306b1SToby Isaac       const PetscInt point = points[p];
15104de306b1SToby Isaac 
151163a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
15129566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
15134de306b1SToby Isaac     }
15144de306b1SToby Isaac   }
15153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15164de306b1SToby Isaac }
15174de306b1SToby Isaac 
151884f0b6dfSMatthew G. Knepley /*@
151984f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
15204de306b1SToby Isaac 
152120f4b53cSBarry Smith   Not Collective
15225b5e7992SMatthew G. Knepley 
152384f0b6dfSMatthew G. Knepley   Input Parameters:
152420f4b53cSBarry Smith + label - the `DMLabel`
152584f0b6dfSMatthew G. Knepley - value - the stratum value
152684f0b6dfSMatthew G. Knepley 
152784f0b6dfSMatthew G. Knepley   Level: intermediate
152884f0b6dfSMatthew G. Knepley 
152920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
153084f0b6dfSMatthew G. Knepley @*/
1531d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1532d71ae5a4SJacob Faibussowitsch {
1533c58f1c22SToby Isaac   PetscInt v;
1534c58f1c22SToby Isaac 
1535c58f1c22SToby Isaac   PetscFunctionBegin;
1536d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15379f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15389566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15393ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15404de306b1SToby Isaac   if (label->validIS[v]) {
15414de306b1SToby Isaac     if (label->bt) {
1542c58f1c22SToby Isaac       PetscInt        i;
1543ad8374ffSToby Isaac       const PetscInt *points;
1544c58f1c22SToby Isaac 
15459566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1546c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1547ad8374ffSToby Isaac         const PetscInt point = points[i];
1548c58f1c22SToby Isaac 
154963a3b9bcSJacob Faibussowitsch         PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
15509566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1551c58f1c22SToby Isaac       }
15529566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1553c58f1c22SToby Isaac     }
1554c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
15559566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
15569566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
15579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
15589566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1559c58f1c22SToby Isaac   } else {
15609566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1561c58f1c22SToby Isaac   }
15623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1563c58f1c22SToby Isaac }
1564c58f1c22SToby Isaac 
156584f0b6dfSMatthew G. Knepley /*@
1566412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1567412e9a14SMatthew G. Knepley 
156820f4b53cSBarry Smith   Not Collective
1569412e9a14SMatthew G. Knepley 
1570412e9a14SMatthew G. Knepley   Input Parameters:
157120f4b53cSBarry Smith + label  - The `DMLabel`
1572412e9a14SMatthew G. Knepley . value  - The label value for all points
1573412e9a14SMatthew G. Knepley . pStart - The first point
1574412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1575412e9a14SMatthew G. Knepley 
1576412e9a14SMatthew G. Knepley   Level: intermediate
1577412e9a14SMatthew G. Knepley 
157820f4b53cSBarry Smith   Note:
157920f4b53cSBarry Smith   The marks points are [`pStart`, `pEnd`), and only the bounds are stored.
158020f4b53cSBarry Smith 
158120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1582412e9a14SMatthew G. Knepley @*/
1583d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1584d71ae5a4SJacob Faibussowitsch {
1585412e9a14SMatthew G. Knepley   IS pIS;
1586412e9a14SMatthew G. Knepley 
1587412e9a14SMatthew G. Knepley   PetscFunctionBegin;
15889566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
15899566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
15909566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
15913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1592412e9a14SMatthew G. Knepley }
1593412e9a14SMatthew G. Knepley 
1594412e9a14SMatthew G. Knepley /*@
1595d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1596d123abd9SMatthew G. Knepley 
159720f4b53cSBarry Smith   Not Collective
1598d123abd9SMatthew G. Knepley 
1599d123abd9SMatthew G. Knepley   Input Parameters:
160020f4b53cSBarry Smith + label - The `DMLabel`
1601d123abd9SMatthew G. Knepley . value - The label value
1602d123abd9SMatthew G. Knepley - p     - A point with this value
1603d123abd9SMatthew G. Knepley 
1604d123abd9SMatthew G. Knepley   Output Parameter:
1605d123abd9SMatthew G. Knepley . index - The index of this point in the stratum, or -1 if the point is not in the stratum or the stratum does not exist
1606d123abd9SMatthew G. Knepley 
1607d123abd9SMatthew G. Knepley   Level: intermediate
1608d123abd9SMatthew G. Knepley 
160920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1610d123abd9SMatthew G. Knepley @*/
1611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1612d71ae5a4SJacob Faibussowitsch {
16139f6c5813SMatthew G. Knepley   IS              pointIS;
1614d123abd9SMatthew G. Knepley   const PetscInt *indices;
1615d123abd9SMatthew G. Knepley   PetscInt        v;
1616d123abd9SMatthew G. Knepley 
1617d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1618d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16194f572ea9SToby Isaac   PetscAssertPointer(index, 4);
1620d123abd9SMatthew G. Knepley   *index = -1;
16219566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
16223ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
16239566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
16249f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &pointIS);
16259f6c5813SMatthew G. Knepley   PetscCall(ISGetIndices(pointIS, &indices));
16269566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
16279f6c5813SMatthew G. Knepley   PetscCall(ISRestoreIndices(pointIS, &indices));
16289f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&pointIS));
16293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1630d123abd9SMatthew G. Knepley }
1631d123abd9SMatthew G. Knepley 
1632d123abd9SMatthew G. Knepley /*@
163320f4b53cSBarry Smith   DMLabelFilter - Remove all points outside of [`start`, `end`)
163484f0b6dfSMatthew G. Knepley 
163520f4b53cSBarry Smith   Not Collective
16365b5e7992SMatthew G. Knepley 
163784f0b6dfSMatthew G. Knepley   Input Parameters:
163820f4b53cSBarry Smith + label - the `DMLabel`
163922cd2cdaSVaclav Hapla . start - the first point kept
164022cd2cdaSVaclav Hapla - end   - one more than the last point kept
164184f0b6dfSMatthew G. Knepley 
164284f0b6dfSMatthew G. Knepley   Level: intermediate
164384f0b6dfSMatthew G. Knepley 
164420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
164584f0b6dfSMatthew G. Knepley @*/
1646d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1647d71ae5a4SJacob Faibussowitsch {
1648c58f1c22SToby Isaac   PetscInt v;
1649c58f1c22SToby Isaac 
1650c58f1c22SToby Isaac   PetscFunctionBegin;
1651d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16529f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16539566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
16549566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16559f6c5813SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
16569f6c5813SMatthew G. Knepley     PetscCall(ISGeneralFilter(label->points[v], start, end));
16579f6c5813SMatthew G. Knepley     PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
16589f6c5813SMatthew G. Knepley   }
16599566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
16603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1661c58f1c22SToby Isaac }
1662c58f1c22SToby Isaac 
166384f0b6dfSMatthew G. Knepley /*@
166484f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
166584f0b6dfSMatthew G. Knepley 
166620f4b53cSBarry Smith   Not Collective
16675b5e7992SMatthew G. Knepley 
166884f0b6dfSMatthew G. Knepley   Input Parameters:
166920f4b53cSBarry Smith + label       - the `DMLabel`
167084f0b6dfSMatthew G. Knepley - permutation - the point permutation
167184f0b6dfSMatthew G. Knepley 
167284f0b6dfSMatthew G. Knepley   Output Parameter:
167360225df5SJacob Faibussowitsch . labelNew - the new label containing the permuted points
167484f0b6dfSMatthew G. Knepley 
167584f0b6dfSMatthew G. Knepley   Level: intermediate
167684f0b6dfSMatthew G. Knepley 
167720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
167884f0b6dfSMatthew G. Knepley @*/
1679d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1680d71ae5a4SJacob Faibussowitsch {
1681c58f1c22SToby Isaac   const PetscInt *perm;
1682c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1683c58f1c22SToby Isaac 
1684c58f1c22SToby Isaac   PetscFunctionBegin;
1685d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1686d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
16879f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16889566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16899566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
16909566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
16919566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
16929566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1693c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1694c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1695ad8374ffSToby Isaac     const PetscInt *points;
1696ad8374ffSToby Isaac     PetscInt       *pointsNew;
1697c58f1c22SToby Isaac 
16989566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
16999f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(size, &pointsNew));
1700c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1701ad8374ffSToby Isaac       const PetscInt point = points[q];
1702c58f1c22SToby Isaac 
170363a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < 0) && !(point >= numPoints), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ") for the remapping", point, numPoints);
1704ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1705c58f1c22SToby Isaac     }
17069566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
17079566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
170857508eceSPierre Jolivet     PetscCall(ISDestroy(&(*labelNew)->points[v]));
1709fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
17109566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
17119566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1712fa8e8ae5SToby Isaac     } else {
17139566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1714fa8e8ae5SToby Isaac     }
17159566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1716c58f1c22SToby Isaac   }
17179566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1718c58f1c22SToby Isaac   if (label->bt) {
17199566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
17209566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1721c58f1c22SToby Isaac   }
17223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1723c58f1c22SToby Isaac }
1724c58f1c22SToby Isaac 
1725*5552b385SBrandon /*@
1726*5552b385SBrandon   DMLabelPermuteValues - Permute the values in a label
1727*5552b385SBrandon 
1728*5552b385SBrandon   Not collective
1729*5552b385SBrandon 
1730*5552b385SBrandon   Input Parameters:
1731*5552b385SBrandon + label       - the `DMLabel`
1732*5552b385SBrandon - permutation - the value permutation, permutation[old value] = new value
1733*5552b385SBrandon 
1734*5552b385SBrandon   Output Parameter:
1735*5552b385SBrandon . label - the `DMLabel` now with permuted values
1736*5552b385SBrandon 
1737*5552b385SBrandon   Note:
1738*5552b385SBrandon   The modification is done in-place
1739*5552b385SBrandon 
1740*5552b385SBrandon   Level: intermediate
1741*5552b385SBrandon 
1742*5552b385SBrandon .seealso: `DMLabelRewriteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1743*5552b385SBrandon @*/
1744*5552b385SBrandon PetscErrorCode DMLabelPermuteValues(DMLabel label, IS permutation)
1745*5552b385SBrandon {
1746*5552b385SBrandon   PetscInt Nv, Np;
1747*5552b385SBrandon 
1748*5552b385SBrandon   PetscFunctionBegin;
1749*5552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1750*5552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
1751*5552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
1752*5552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
1753*5552b385SBrandon   PetscCheck(Np == Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " != %" PetscInt_FMT " number of label values", Np, Nv);
1754*5552b385SBrandon   if (PetscDefined(USE_DEBUG)) {
1755*5552b385SBrandon     PetscBool flg;
1756*5552b385SBrandon     PetscCall(ISGetInfo(permutation, IS_PERMUTATION, IS_LOCAL, PETSC_TRUE, &flg));
1757*5552b385SBrandon     PetscCheck(flg, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "IS is not a permutation");
1758*5552b385SBrandon   }
1759*5552b385SBrandon   PetscCall(DMLabelRewriteValues(label, permutation));
1760*5552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
1761*5552b385SBrandon }
1762*5552b385SBrandon 
1763*5552b385SBrandon /*@
1764*5552b385SBrandon   DMLabelRewriteValues - Permute the values in a label, but some may be omitted
1765*5552b385SBrandon 
1766*5552b385SBrandon   Not collective
1767*5552b385SBrandon 
1768*5552b385SBrandon   Input Parameters:
1769*5552b385SBrandon + label       - the `DMLabel`
1770*5552b385SBrandon - permutation - the value permutation, permutation[old value] = new value, but some maybe omitted
1771*5552b385SBrandon 
1772*5552b385SBrandon   Output Parameter:
1773*5552b385SBrandon . label - the `DMLabel` now with permuted values
1774*5552b385SBrandon 
1775*5552b385SBrandon   Note:
1776*5552b385SBrandon   The modification is done in-place
1777*5552b385SBrandon 
1778*5552b385SBrandon   Level: intermediate
1779*5552b385SBrandon 
1780*5552b385SBrandon .seealso: `DMLabelPermuteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1781*5552b385SBrandon @*/
1782*5552b385SBrandon PetscErrorCode DMLabelRewriteValues(DMLabel label, IS permutation)
1783*5552b385SBrandon {
1784*5552b385SBrandon   const PetscInt *perm;
1785*5552b385SBrandon   PetscInt        Nv, Np;
1786*5552b385SBrandon 
1787*5552b385SBrandon   PetscFunctionBegin;
1788*5552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1789*5552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
1790*5552b385SBrandon   PetscCall(DMLabelMakeAllValid_Private(label));
1791*5552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
1792*5552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
1793*5552b385SBrandon   PetscCheck(Np >= Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " < %" PetscInt_FMT " number of label values", Np, Nv);
1794*5552b385SBrandon   PetscCall(ISGetIndices(permutation, &perm));
1795*5552b385SBrandon   for (PetscInt v = 0; v < Nv; ++v) label->stratumValues[v] = perm[label->stratumValues[v]];
1796*5552b385SBrandon   PetscCall(ISRestoreIndices(permutation, &perm));
1797*5552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
1798*5552b385SBrandon }
1799*5552b385SBrandon 
180066976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1801d71ae5a4SJacob Faibussowitsch {
180226c55118SMichael Lange   MPI_Comm     comm;
1803eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
180426c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
180526c55118SMichael Lange   PetscSection rootSection;
180626c55118SMichael Lange   PetscSF      labelSF;
180726c55118SMichael Lange 
180826c55118SMichael Lange   PetscFunctionBegin;
18099566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
18109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
181126c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
181226c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
18139566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
18149566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
18159566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
181626c55118SMichael Lange   if (label) {
181726c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1818ad8374ffSToby Isaac       const PetscInt *points;
1819ad8374ffSToby Isaac 
18209566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
182148a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
18229566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
182326c55118SMichael Lange     }
182426c55118SMichael Lange   }
18259566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
182626c55118SMichael Lange   /* Create a point-wise array of stratum values */
18279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
18289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
18299566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
183026c55118SMichael Lange   if (label) {
183126c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1832ad8374ffSToby Isaac       const PetscInt *points;
1833ad8374ffSToby Isaac 
18349566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
183526c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1836ad8374ffSToby Isaac         const PetscInt p = points[l];
18379566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
183826c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
183926c55118SMichael Lange       }
18409566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
184126c55118SMichael Lange     }
184226c55118SMichael Lange   }
184326c55118SMichael Lange   /* Build SF that maps label points to remote processes */
18449566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
18459566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
18469566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
18479566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
184826c55118SMichael Lange   /* Send the strata for each point over the derived SF */
18499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
18509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
18519566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
18529566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
185326c55118SMichael Lange   /* Clean up */
18549566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18559566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
18569566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18579566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
18583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185926c55118SMichael Lange }
186026c55118SMichael Lange 
186184f0b6dfSMatthew G. Knepley /*@
186220f4b53cSBarry Smith   DMLabelDistribute - Create a new label pushed forward over the `PetscSF`
186384f0b6dfSMatthew G. Knepley 
186420f4b53cSBarry Smith   Collective
18655b5e7992SMatthew G. Knepley 
186684f0b6dfSMatthew G. Knepley   Input Parameters:
186720f4b53cSBarry Smith + label - the `DMLabel`
186884f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
186984f0b6dfSMatthew G. Knepley 
187084f0b6dfSMatthew G. Knepley   Output Parameter:
187160225df5SJacob Faibussowitsch . labelNew - the new redistributed label
187284f0b6dfSMatthew G. Knepley 
187384f0b6dfSMatthew G. Knepley   Level: intermediate
187484f0b6dfSMatthew G. Knepley 
187520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
187684f0b6dfSMatthew G. Knepley @*/
1877d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1878d71ae5a4SJacob Faibussowitsch {
1879c58f1c22SToby Isaac   MPI_Comm     comm;
188026c55118SMichael Lange   PetscSection leafSection;
188126c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
188226c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1883ad8374ffSToby Isaac   PetscInt   **points;
1884d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1885c58f1c22SToby Isaac   char        *name;
1886835f2295SStefano Zampini   PetscMPIInt  nameSize;
1887e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1888c58f1c22SToby Isaac   size_t       len = 0;
188926c55118SMichael Lange   PetscMPIInt  rank;
1890c58f1c22SToby Isaac 
1891c58f1c22SToby Isaac   PetscFunctionBegin;
1892d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1893f018e600SMatthew G. Knepley   if (label) {
1894f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
18959f6c5813SMatthew G. Knepley     PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
18969566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1897f018e600SMatthew G. Knepley   }
18989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
18999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1900c58f1c22SToby Isaac   /* Bcast name */
1901dd400576SPatrick Sanan   if (rank == 0) {
19029566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
19039566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1904d67d17b1SMatthew G. Knepley   }
1905835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
1906835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
19079566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
19089566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
1909835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
19109566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
19119566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
191277d236dfSMichael Lange   /* Bcast defaultValue */
1913dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
19149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
191526c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
19169566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
19175cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
19189566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
19199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
19209566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
19219566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
19229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1923ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
19249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
19255cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
19265cbdf6fcSMichael Lange   offset = 0;
19279566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
19289566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
192948a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
19305cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1931231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
19329371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
19339371c9d4SSatish Balay         leafStrata[p] = s;
19349371c9d4SSatish Balay         break;
19359371c9d4SSatish Balay       }
19365cbdf6fcSMichael Lange     }
19375cbdf6fcSMichael Lange   }
1938c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
19399566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
19409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1941c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1944ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1945c58f1c22SToby Isaac   }
19469566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
19479f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
19489f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1949c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
19509566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
1951f4f49eeaSPierre Jolivet     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &points[s]));
1952c58f1c22SToby Isaac   }
1953c58f1c22SToby Isaac   /* Insert points into new strata */
19549566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
19559566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1956c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1959c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1960c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1961ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1962c58f1c22SToby Isaac     }
1963c58f1c22SToby Isaac   }
1964ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1965f4f49eeaSPierre Jolivet     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &points[s][0], PETSC_OWN_POINTER, &((*labelNew)->points[s])));
19669566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1967ad8374ffSToby Isaac   }
19689566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
19699566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
19709566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
19719566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
19729566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
19733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1974c58f1c22SToby Isaac }
1975c58f1c22SToby Isaac 
19767937d9ceSMichael Lange /*@
19777937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
19787937d9ceSMichael Lange 
197920f4b53cSBarry Smith   Collective
19805b5e7992SMatthew G. Knepley 
19817937d9ceSMichael Lange   Input Parameters:
198220f4b53cSBarry Smith + label - the `DMLabel`
198320f4b53cSBarry Smith - sf    - the `PetscSF` communication map
19847937d9ceSMichael Lange 
19852fe279fdSBarry Smith   Output Parameter:
198620f4b53cSBarry Smith . labelNew - the new `DMLabel` with localised leaf values
19877937d9ceSMichael Lange 
19887937d9ceSMichael Lange   Level: developer
19897937d9ceSMichael Lange 
199020f4b53cSBarry Smith   Note:
199120f4b53cSBarry Smith   This is the inverse operation to `DMLabelDistribute()`.
19927937d9ceSMichael Lange 
199320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
19947937d9ceSMichael Lange @*/
1995d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
1996d71ae5a4SJacob Faibussowitsch {
19977937d9ceSMichael Lange   MPI_Comm        comm;
19987937d9ceSMichael Lange   PetscSection    rootSection;
19997937d9ceSMichael Lange   PetscSF         sfLabel;
20007937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
20017937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
20027937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
20037937d9ceSMichael Lange   PetscInt       *rootStrata;
2004d67d17b1SMatthew G. Knepley   const char     *lname;
20057937d9ceSMichael Lange   char           *name;
2006835f2295SStefano Zampini   PetscMPIInt     nameSize;
20077937d9ceSMichael Lange   size_t          len = 0;
20089852e123SBarry Smith   PetscMPIInt     rank, size;
20097937d9ceSMichael Lange 
20107937d9ceSMichael Lange   PetscFunctionBegin;
2011d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2012d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
20139f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
20149566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
20159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
20169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
20177937d9ceSMichael Lange   /* Bcast name */
2018dd400576SPatrick Sanan   if (rank == 0) {
20199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
20209566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
2021d67d17b1SMatthew G. Knepley   }
2022835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
2023835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
20249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
20259566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
2026835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
20279566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
20289566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
20297937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
20307937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
20317937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
20329566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
20339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
2034dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
20357937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
20368212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
20378212dd46SStefano Zampini 
20388212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
20398212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
20407937d9ceSMichael Lange   }
20419566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
20429566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
20437937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
20449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
20456497c311SBarry Smith   PetscCall(PetscSFGatherBegin(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20466497c311SBarry Smith   PetscCall(PetscSFGatherEnd(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20479566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
20489566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
20497937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
20509566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
20517937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
20527937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
20537937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
20549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
20559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
20569566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
20577937d9ceSMichael Lange     }
20587937d9ceSMichael Lange     idx += rootDegree[p];
20597937d9ceSMichael Lange   }
20609566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
20619566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
20629566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
20639566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
20643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20657937d9ceSMichael Lange }
20667937d9ceSMichael Lange 
2067d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
2068d71ae5a4SJacob Faibussowitsch {
2069d42890abSMatthew G. Knepley   const PetscInt *degree;
2070d42890abSMatthew G. Knepley   const PetscInt *points;
2071d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2072d42890abSMatthew G. Knepley 
2073d42890abSMatthew G. Knepley   PetscFunctionBegin;
2074d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2075d42890abSMatthew G. Knepley   /* Add in leaves */
2076d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2077d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2078d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
2079d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
2080d42890abSMatthew G. Knepley   }
2081d42890abSMatthew G. Knepley   /* Add in shared roots */
2082d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2083d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2084d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2085d42890abSMatthew G. Knepley     if (degree[r]) {
2086d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
2087d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
2088d42890abSMatthew G. Knepley     }
2089d42890abSMatthew G. Knepley   }
20903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2091d42890abSMatthew G. Knepley }
2092d42890abSMatthew G. Knepley 
2093d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2094d71ae5a4SJacob Faibussowitsch {
2095d42890abSMatthew G. Knepley   const PetscInt *degree;
2096d42890abSMatthew G. Knepley   const PetscInt *points;
2097d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2098d42890abSMatthew G. Knepley 
2099d42890abSMatthew G. Knepley   PetscFunctionBegin;
2100d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2101d42890abSMatthew G. Knepley   /* Read out leaves */
2102d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2103d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2104d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
2105d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
2106d42890abSMatthew G. Knepley 
2107d42890abSMatthew G. Knepley     if (cval != defVal) {
2108d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
2109d42890abSMatthew G. Knepley       if (val == defVal) {
2110d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
211148a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
2112d42890abSMatthew G. Knepley       }
2113d42890abSMatthew G. Knepley     }
2114d42890abSMatthew G. Knepley   }
2115d42890abSMatthew G. Knepley   /* Read out shared roots */
2116d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2117d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2118d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2119d42890abSMatthew G. Knepley     if (degree[r]) {
2120d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
2121d42890abSMatthew G. Knepley 
2122d42890abSMatthew G. Knepley       if (cval != defVal) {
2123d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
2124d42890abSMatthew G. Knepley         if (val == defVal) {
2125d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
212648a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2127d42890abSMatthew G. Knepley         }
2128d42890abSMatthew G. Knepley       }
2129d42890abSMatthew G. Knepley     }
2130d42890abSMatthew G. Knepley   }
21313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2132d42890abSMatthew G. Knepley }
2133d42890abSMatthew G. Knepley 
2134d42890abSMatthew G. Knepley /*@
2135d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
2136d42890abSMatthew G. Knepley 
213720f4b53cSBarry Smith   Collective
2138d42890abSMatthew G. Knepley 
2139d42890abSMatthew G. Knepley   Input Parameters:
214020f4b53cSBarry Smith + label - The `DMLabel` to propagate across processes
214120f4b53cSBarry Smith - sf    - The `PetscSF` describing parallel layout of the label points
2142d42890abSMatthew G. Knepley 
2143d42890abSMatthew G. Knepley   Level: intermediate
2144d42890abSMatthew G. Knepley 
214520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2146d42890abSMatthew G. Knepley @*/
2147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2148d71ae5a4SJacob Faibussowitsch {
2149d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
2150d42890abSMatthew G. Knepley   PetscMPIInt size;
2151d42890abSMatthew G. Knepley 
2152d42890abSMatthew G. Knepley   PetscFunctionBegin;
21539f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2154d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2155d42890abSMatthew G. Knepley   if (size > 1) {
2156d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
2157d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2158d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2159d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2160d42890abSMatthew G. Knepley   }
21613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2162d42890abSMatthew G. Knepley }
2163d42890abSMatthew G. Knepley 
2164d42890abSMatthew G. Knepley /*@
2165d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
2166d42890abSMatthew G. Knepley 
216720f4b53cSBarry Smith   Collective
2168d42890abSMatthew G. Knepley 
2169d42890abSMatthew G. Knepley   Input Parameters:
217020f4b53cSBarry Smith + label   - The `DMLabel` to propagate across processes
217160225df5SJacob Faibussowitsch - pointSF - The `PetscSF` describing parallel layout of the label points
2172d42890abSMatthew G. Knepley 
2173d42890abSMatthew G. Knepley   Level: intermediate
2174d42890abSMatthew G. Knepley 
217520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2176d42890abSMatthew G. Knepley @*/
2177d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2178d71ae5a4SJacob Faibussowitsch {
2179d42890abSMatthew G. Knepley   PetscFunctionBegin;
21809f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2181d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
2182d42890abSMatthew G. Knepley   label->propArray = NULL;
21833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2184d42890abSMatthew G. Knepley }
2185d42890abSMatthew G. Knepley 
2186d42890abSMatthew G. Knepley /*@C
2187d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2188d42890abSMatthew G. Knepley 
218920f4b53cSBarry Smith   Collective
2190d42890abSMatthew G. Knepley 
2191d42890abSMatthew G. Knepley   Input Parameters:
219220f4b53cSBarry Smith + label     - The `DMLabel` to propagate across processes
2193a4e35b19SJacob Faibussowitsch . pointSF   - The `PetscSF` describing parallel layout of the label points
219420f4b53cSBarry Smith . markPoint - An optional callback that is called when a point is marked, or `NULL`
219520f4b53cSBarry Smith - ctx       - An optional user context for the callback, or `NULL`
2196d42890abSMatthew G. Knepley 
219720f4b53cSBarry Smith   Calling sequence of `markPoint`:
219820f4b53cSBarry Smith + label - The `DMLabel`
2199d42890abSMatthew G. Knepley . p     - The point being marked
2200a4e35b19SJacob Faibussowitsch . val   - The label value for `p`
2201d42890abSMatthew G. Knepley - ctx   - An optional user context
2202d42890abSMatthew G. Knepley 
2203d42890abSMatthew G. Knepley   Level: intermediate
2204d42890abSMatthew G. Knepley 
220520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2206d42890abSMatthew G. Knepley @*/
2207a4e35b19SJacob Faibussowitsch PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel label, PetscInt p, PetscInt val, void *ctx), void *ctx)
2208d71ae5a4SJacob Faibussowitsch {
2209c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2210d42890abSMatthew G. Knepley   PetscMPIInt size;
2211d42890abSMatthew G. Knepley 
2212d42890abSMatthew G. Knepley   PetscFunctionBegin;
22139f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2214d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2215c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2216c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2217d42890abSMatthew G. Knepley     /* Communicate marked edges
2218d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2219d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2220d42890abSMatthew G. Knepley 
2221d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2222d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2223d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2224d42890abSMatthew G. Knepley 
2225d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2226d42890abSMatthew G. Knepley        values will have 1+0=1 and old values will have 1+1=2. Loop over these, resetting the values to 1, and adding any new
2227d42890abSMatthew G. Knepley        edge to the queue.
2228d42890abSMatthew G. Knepley     */
2229d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2230d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2231d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2232d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2233d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2234d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2235d42890abSMatthew G. Knepley   }
22363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2237d42890abSMatthew G. Knepley }
2238d42890abSMatthew G. Knepley 
223984f0b6dfSMatthew G. Knepley /*@
224020f4b53cSBarry Smith   DMLabelConvertToSection - Make a `PetscSection`/`IS` pair that encodes the label
224184f0b6dfSMatthew G. Knepley 
224220f4b53cSBarry Smith   Not Collective
22435b5e7992SMatthew G. Knepley 
224484f0b6dfSMatthew G. Knepley   Input Parameter:
224520f4b53cSBarry Smith . label - the `DMLabel`
224684f0b6dfSMatthew G. Knepley 
224784f0b6dfSMatthew G. Knepley   Output Parameters:
224884f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
224920f4b53cSBarry Smith - is      - An `IS` containing all the label points
225084f0b6dfSMatthew G. Knepley 
225184f0b6dfSMatthew G. Knepley   Level: developer
225284f0b6dfSMatthew G. Knepley 
225320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
225484f0b6dfSMatthew G. Knepley @*/
2255d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2256d71ae5a4SJacob Faibussowitsch {
2257c58f1c22SToby Isaac   IS              vIS;
2258c58f1c22SToby Isaac   const PetscInt *values;
2259c58f1c22SToby Isaac   PetscInt       *points;
2260c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2261c58f1c22SToby Isaac 
2262c58f1c22SToby Isaac   PetscFunctionBegin;
2263d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
22649566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
22659566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
22669566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
22679371c9d4SSatish Balay   if (nV) {
22689371c9d4SSatish Balay     vS = values[0];
22699371c9d4SSatish Balay     vE = values[0] + 1;
22709371c9d4SSatish Balay   }
2271c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2272c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2273c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2274c58f1c22SToby Isaac   }
22759566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
22769566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2277c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2278c58f1c22SToby Isaac     PetscInt n;
2279c58f1c22SToby Isaac 
22809566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
22819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2282c58f1c22SToby Isaac   }
22839566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
22849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
22859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2286c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2287c58f1c22SToby Isaac     IS              is;
2288c58f1c22SToby Isaac     const PetscInt *spoints;
2289c58f1c22SToby Isaac     PetscInt        dof, off, p;
2290c58f1c22SToby Isaac 
22919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
22929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
22939566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
22949566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2295c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
22969566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
22979566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2298c58f1c22SToby Isaac   }
22999566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
23009566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
23019566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
23023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2303c58f1c22SToby Isaac }
2304c58f1c22SToby Isaac 
23059f6c5813SMatthew G. Knepley /*@C
23069f6c5813SMatthew G. Knepley   DMLabelRegister - Adds a new label component implementation
23079f6c5813SMatthew G. Knepley 
23089f6c5813SMatthew G. Knepley   Not Collective
23099f6c5813SMatthew G. Knepley 
23109f6c5813SMatthew G. Knepley   Input Parameters:
23119f6c5813SMatthew G. Knepley + name        - The name of a new user-defined creation routine
23129f6c5813SMatthew G. Knepley - create_func - The creation routine itself
23139f6c5813SMatthew G. Knepley 
23149f6c5813SMatthew G. Knepley   Notes:
23159f6c5813SMatthew G. Knepley   `DMLabelRegister()` may be called multiple times to add several user-defined labels
23169f6c5813SMatthew G. Knepley 
231760225df5SJacob Faibussowitsch   Example Usage:
23189f6c5813SMatthew G. Knepley .vb
23199f6c5813SMatthew G. Knepley   DMLabelRegister("my_label", MyLabelCreate);
23209f6c5813SMatthew G. Knepley .ve
23219f6c5813SMatthew G. Knepley 
23229f6c5813SMatthew G. Knepley   Then, your label type can be chosen with the procedural interface via
23239f6c5813SMatthew G. Knepley .vb
23249f6c5813SMatthew G. Knepley   DMLabelCreate(MPI_Comm, DMLabel *);
23259f6c5813SMatthew G. Knepley   DMLabelSetType(DMLabel, "my_label");
23269f6c5813SMatthew G. Knepley .ve
23279f6c5813SMatthew G. Knepley   or at runtime via the option
23289f6c5813SMatthew G. Knepley .vb
23299f6c5813SMatthew G. Knepley   -dm_label_type my_label
23309f6c5813SMatthew G. Knepley .ve
23319f6c5813SMatthew G. Knepley 
23329f6c5813SMatthew G. Knepley   Level: advanced
23339f6c5813SMatthew G. Knepley 
233460225df5SJacob Faibussowitsch .seealso: `DMLabel`, `DM`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
23359f6c5813SMatthew G. Knepley @*/
23369f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
23379f6c5813SMatthew G. Knepley {
23389f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23399f6c5813SMatthew G. Knepley   PetscCall(DMInitializePackage());
23409f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
23413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23429f6c5813SMatthew G. Knepley }
23439f6c5813SMatthew G. Knepley 
23449f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
23459f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
23469f6c5813SMatthew G. Knepley 
23479f6c5813SMatthew G. Knepley /*@C
23489f6c5813SMatthew G. Knepley   DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
23499f6c5813SMatthew G. Knepley 
23509f6c5813SMatthew G. Knepley   Not Collective
23519f6c5813SMatthew G. Knepley 
23529f6c5813SMatthew G. Knepley   Level: advanced
23539f6c5813SMatthew G. Knepley 
235420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMRegisterAll()`, `DMLabelRegisterDestroy()`
23559f6c5813SMatthew G. Knepley @*/
23569f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterAll(void)
23579f6c5813SMatthew G. Knepley {
23589f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23593ba16761SJacob Faibussowitsch   if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
23609f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_TRUE;
23619f6c5813SMatthew G. Knepley 
23629f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
23639f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
23643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23659f6c5813SMatthew G. Knepley }
23669f6c5813SMatthew G. Knepley 
23679f6c5813SMatthew G. Knepley /*@C
23689f6c5813SMatthew G. Knepley   DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
23699f6c5813SMatthew G. Knepley 
23709f6c5813SMatthew G. Knepley   Level: developer
23719f6c5813SMatthew G. Knepley 
237220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscInitialize()`
23739f6c5813SMatthew G. Knepley @*/
23749f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterDestroy(void)
23759f6c5813SMatthew G. Knepley {
23769f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23779f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListDestroy(&DMLabelList));
23789f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_FALSE;
23793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23809f6c5813SMatthew G. Knepley }
23819f6c5813SMatthew G. Knepley 
2382cc4c1da9SBarry Smith /*@
23839f6c5813SMatthew G. Knepley   DMLabelSetType - Sets the particular implementation for a label.
23849f6c5813SMatthew G. Knepley 
238520f4b53cSBarry Smith   Collective
23869f6c5813SMatthew G. Knepley 
23879f6c5813SMatthew G. Knepley   Input Parameters:
23889f6c5813SMatthew G. Knepley + label  - The label
23899f6c5813SMatthew G. Knepley - method - The name of the label type
23909f6c5813SMatthew G. Knepley 
23919f6c5813SMatthew G. Knepley   Options Database Key:
239220f4b53cSBarry Smith . -dm_label_type <type> - Sets the label type; use -help for a list of available types or see `DMLabelType`
23939f6c5813SMatthew G. Knepley 
23949f6c5813SMatthew G. Knepley   Level: intermediate
23959f6c5813SMatthew G. Knepley 
239620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetType()`, `DMLabelCreate()`
23979f6c5813SMatthew G. Knepley @*/
23989f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
23999f6c5813SMatthew G. Knepley {
24009f6c5813SMatthew G. Knepley   PetscErrorCode (*r)(DMLabel);
24019f6c5813SMatthew G. Knepley   PetscBool match;
24029f6c5813SMatthew G. Knepley 
24039f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24049f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24059f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
24063ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
24079f6c5813SMatthew G. Knepley 
24089f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24099f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
24109f6c5813SMatthew G. Knepley   PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
24119f6c5813SMatthew G. Knepley 
24129f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, destroy);
24139f6c5813SMatthew G. Knepley   PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
24149f6c5813SMatthew G. Knepley   PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
24159f6c5813SMatthew G. Knepley   PetscCall((*r)(label));
24163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24179f6c5813SMatthew G. Knepley }
24189f6c5813SMatthew G. Knepley 
2419cc4c1da9SBarry Smith /*@
24209f6c5813SMatthew G. Knepley   DMLabelGetType - Gets the type name (as a string) from the label.
24219f6c5813SMatthew G. Knepley 
24229f6c5813SMatthew G. Knepley   Not Collective
24239f6c5813SMatthew G. Knepley 
24249f6c5813SMatthew G. Knepley   Input Parameter:
242520f4b53cSBarry Smith . label - The `DMLabel`
24269f6c5813SMatthew G. Knepley 
24279f6c5813SMatthew G. Knepley   Output Parameter:
242820f4b53cSBarry Smith . type - The `DMLabel` type name
24299f6c5813SMatthew G. Knepley 
24309f6c5813SMatthew G. Knepley   Level: intermediate
24319f6c5813SMatthew G. Knepley 
243220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetType()`, `DMLabelCreate()`
24339f6c5813SMatthew G. Knepley @*/
24349f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
24359f6c5813SMatthew G. Knepley {
24369f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24379f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24384f572ea9SToby Isaac   PetscAssertPointer(type, 2);
24399f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24409f6c5813SMatthew G. Knepley   *type = ((PetscObject)label)->type_name;
24413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24429f6c5813SMatthew G. Knepley }
24439f6c5813SMatthew G. Knepley 
24449f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
24459f6c5813SMatthew G. Knepley {
24469f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24479f6c5813SMatthew G. Knepley   label->ops->view         = DMLabelView_Concrete;
24489f6c5813SMatthew G. Knepley   label->ops->setup        = NULL;
24499f6c5813SMatthew G. Knepley   label->ops->duplicate    = DMLabelDuplicate_Concrete;
24509f6c5813SMatthew G. Knepley   label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
24513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24529f6c5813SMatthew G. Knepley }
24539f6c5813SMatthew G. Knepley 
24549f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
24559f6c5813SMatthew G. Knepley {
24569f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24579f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24589f6c5813SMatthew G. Knepley   PetscCall(DMLabelInitialize_Concrete(label));
24593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24609f6c5813SMatthew G. Knepley }
24619f6c5813SMatthew G. Knepley 
246284f0b6dfSMatthew G. Knepley /*@
2463c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
246420f4b53cSBarry Smith   the local section and an `PetscSF` describing the section point overlap.
2465c58f1c22SToby Isaac 
246620f4b53cSBarry Smith   Collective
24675b5e7992SMatthew G. Knepley 
2468c58f1c22SToby Isaac   Input Parameters:
246920f4b53cSBarry Smith + s                  - The `PetscSection` for the local field layout
247020f4b53cSBarry Smith . sf                 - The `PetscSF` describing parallel layout of the section points
247120f4b53cSBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
2472c58f1c22SToby Isaac . label              - The label specifying the points
2473c58f1c22SToby Isaac - labelValue         - The label stratum specifying the points
2474c58f1c22SToby Isaac 
2475c58f1c22SToby Isaac   Output Parameter:
247620f4b53cSBarry Smith . gsection - The `PetscSection` for the global field layout
2477c58f1c22SToby Isaac 
2478c58f1c22SToby Isaac   Level: developer
2479c58f1c22SToby Isaac 
248020f4b53cSBarry Smith   Note:
248120f4b53cSBarry Smith   This gives negative sizes and offsets to points not owned by this process
248220f4b53cSBarry Smith 
248320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionCreate()`
2484c58f1c22SToby Isaac @*/
2485d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2486d71ae5a4SJacob Faibussowitsch {
2487c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2488c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2489c58f1c22SToby Isaac 
2490c58f1c22SToby Isaac   PetscFunctionBegin;
2491d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2492d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2493d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
24949566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
24959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
24969566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
24979566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2498c58f1c22SToby Isaac   if (nroots >= 0) {
249963a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
25009566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2501c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25029566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2503c58f1c22SToby Isaac     } else {
2504c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2505c58f1c22SToby Isaac     }
2506c58f1c22SToby Isaac   }
2507c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2508c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2509c58f1c22SToby Isaac     PetscInt value;
2510c58f1c22SToby Isaac 
25119566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2512c58f1c22SToby Isaac     if (value != labelValue) continue;
25139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
25149566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
25159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
25169566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2517c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2518c58f1c22SToby Isaac   }
25199566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2520c58f1c22SToby Isaac   if (nroots >= 0) {
25219566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25229566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2523c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25249371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25259371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
25269371c9d4SSatish Balay       }
2527c58f1c22SToby Isaac     }
2528c58f1c22SToby Isaac   }
252935cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
2530c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2531c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2532c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2533c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2534c58f1c22SToby Isaac   }
25359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2536c58f1c22SToby Isaac   globalOff -= off;
2537c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2538c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2539c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2540c58f1c22SToby Isaac   }
2541c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2542c58f1c22SToby Isaac   if (nroots >= 0) {
25439566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25449566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2545c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25469371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25479371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
25489371c9d4SSatish Balay       }
2549c58f1c22SToby Isaac     }
2550c58f1c22SToby Isaac   }
25519566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
25529566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
25533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2554c58f1c22SToby Isaac }
2555c58f1c22SToby Isaac 
25569371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
25575fdea053SToby Isaac   DMLabel              label;
25585fdea053SToby Isaac   PetscCopyMode       *modes;
25595fdea053SToby Isaac   PetscInt            *sizes;
25605fdea053SToby Isaac   const PetscInt    ***perms;
25615fdea053SToby Isaac   const PetscScalar ***rots;
25625fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
25635fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
25645fdea053SToby Isaac } PetscSectionSym_Label;
25655fdea053SToby Isaac 
2566d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2567d71ae5a4SJacob Faibussowitsch {
25685fdea053SToby Isaac   PetscInt               i, j;
25695fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
25705fdea053SToby Isaac 
25715fdea053SToby Isaac   PetscFunctionBegin;
25725fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
25735fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
25745fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
25759566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
25769566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
25775fdea053SToby Isaac       }
25785fdea053SToby Isaac       if (sl->perms[i]) {
25795fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
25805fdea053SToby Isaac 
25819566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
25825fdea053SToby Isaac       }
25835fdea053SToby Isaac       if (sl->rots[i]) {
25845fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
25855fdea053SToby Isaac 
25869566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
25875fdea053SToby Isaac       }
25885fdea053SToby Isaac     }
25895fdea053SToby Isaac   }
25909566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
25919566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
25925fdea053SToby Isaac   sl->numStrata = 0;
25933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25945fdea053SToby Isaac }
25955fdea053SToby Isaac 
2596d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2597d71ae5a4SJacob Faibussowitsch {
25985fdea053SToby Isaac   PetscFunctionBegin;
25999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
26009566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
26013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26025fdea053SToby Isaac }
26035fdea053SToby Isaac 
2604d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2605d71ae5a4SJacob Faibussowitsch {
26065fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
26075fdea053SToby Isaac   PetscBool              isAscii;
26085fdea053SToby Isaac   DMLabel                label = sl->label;
2609d67d17b1SMatthew G. Knepley   const char            *name;
26105fdea053SToby Isaac 
26115fdea053SToby Isaac   PetscFunctionBegin;
26129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
26135fdea053SToby Isaac   if (isAscii) {
26145fdea053SToby Isaac     PetscInt          i, j, k;
26155fdea053SToby Isaac     PetscViewerFormat format;
26165fdea053SToby Isaac 
26179566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
26185fdea053SToby Isaac     if (label) {
26199566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
26205fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26219566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
26229566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
26239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26245fdea053SToby Isaac       } else {
26259566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
26269566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
26275fdea053SToby Isaac       }
26285fdea053SToby Isaac     } else {
26299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
26305fdea053SToby Isaac     }
26319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
26325fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
26335fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
26345fdea053SToby Isaac 
26355fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
263663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
26375fdea053SToby Isaac       } else {
263863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
26399566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
264063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
26415fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26429566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
26435fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
26445fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
264563a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
26465fdea053SToby Isaac             } else {
26475fdea053SToby Isaac               PetscInt tab;
26485fdea053SToby Isaac 
264963a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
26509566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
26519566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
26525fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
26539566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
26549566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
265563a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
26569566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26579566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26585fdea053SToby Isaac               }
26595fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
26609566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
26619566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
26625fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
266363a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g+i*%+g", (double)PetscRealPart(sl->rots[i][j][k]), (double)PetscImaginaryPart(sl->rots[i][j][k])));
26645fdea053SToby Isaac #else
266563a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
26665fdea053SToby Isaac #endif
26679566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26689566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26695fdea053SToby Isaac               }
26709566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
26715fdea053SToby Isaac             }
26725fdea053SToby Isaac           }
26739566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
26745fdea053SToby Isaac         }
26759566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26765fdea053SToby Isaac       }
26775fdea053SToby Isaac     }
26789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
26795fdea053SToby Isaac   }
26803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26815fdea053SToby Isaac }
26825fdea053SToby Isaac 
26835fdea053SToby Isaac /*@
26845fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
26855fdea053SToby Isaac 
268620f4b53cSBarry Smith   Logically
26875fdea053SToby Isaac 
268860225df5SJacob Faibussowitsch   Input Parameters:
26895fdea053SToby Isaac + sym   - the section symmetries
269020f4b53cSBarry Smith - label - the `DMLabel` describing the types of points
26915fdea053SToby Isaac 
26925fdea053SToby Isaac   Level: developer:
26935fdea053SToby Isaac 
269420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
26955fdea053SToby Isaac @*/
2696d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2697d71ae5a4SJacob Faibussowitsch {
26985fdea053SToby Isaac   PetscSectionSym_Label *sl;
26995fdea053SToby Isaac 
27005fdea053SToby Isaac   PetscFunctionBegin;
27015fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
27025fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
27039566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
27045fdea053SToby Isaac   if (label) {
27055fdea053SToby Isaac     sl->label = label;
27069566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
27079566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
27089566063dSJacob Faibussowitsch     PetscCall(PetscMalloc5(sl->numStrata + 1, &sl->modes, sl->numStrata + 1, &sl->sizes, sl->numStrata + 1, &sl->perms, sl->numStrata + 1, &sl->rots, sl->numStrata + 1, &sl->minMaxOrients));
27099566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
27109566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
27119566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
27129566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
27139566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
27145fdea053SToby Isaac   }
27153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27165fdea053SToby Isaac }
27175fdea053SToby Isaac 
27185fdea053SToby Isaac /*@C
2719b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2720b004864fSMatthew G. Knepley 
272120f4b53cSBarry Smith   Logically Collective
2722b004864fSMatthew G. Knepley 
2723b004864fSMatthew G. Knepley   Input Parameters:
2724b004864fSMatthew G. Knepley + sym     - the section symmetries
2725b004864fSMatthew G. Knepley - stratum - the stratum value in the label that we are assigning symmetries for
2726b004864fSMatthew G. Knepley 
2727b004864fSMatthew G. Knepley   Output Parameters:
272820f4b53cSBarry Smith + size      - the number of dofs for points in the `stratum` of the label
272920f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
273020f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a ppoint in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
273120f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
273220f4b53cSBarry Smith - rots      - `NULL` if there are no rotations, or (`maxOrient` - `minOrient`) sets of rotations, one for each orientation.  A `NULL` set of orientations is the identity
2733b004864fSMatthew G. Knepley 
2734b004864fSMatthew G. Knepley   Level: developer
2735b004864fSMatthew G. Knepley 
273620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2737b004864fSMatthew G. Knepley @*/
2738d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2739d71ae5a4SJacob Faibussowitsch {
2740b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2741b004864fSMatthew G. Knepley   const char            *name;
2742b004864fSMatthew G. Knepley   PetscInt               i;
2743b004864fSMatthew G. Knepley 
2744b004864fSMatthew G. Knepley   PetscFunctionBegin;
2745b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2746b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2747b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2748b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2749b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2750b004864fSMatthew G. Knepley 
2751b004864fSMatthew G. Knepley     if (stratum == value) break;
2752b004864fSMatthew G. Knepley   }
27539566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2754b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
27559371c9d4SSatish Balay   if (size) {
27564f572ea9SToby Isaac     PetscAssertPointer(size, 3);
27579371c9d4SSatish Balay     *size = sl->sizes[i];
27589371c9d4SSatish Balay   }
27599371c9d4SSatish Balay   if (minOrient) {
27604f572ea9SToby Isaac     PetscAssertPointer(minOrient, 4);
27619371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
27629371c9d4SSatish Balay   }
27639371c9d4SSatish Balay   if (maxOrient) {
27644f572ea9SToby Isaac     PetscAssertPointer(maxOrient, 5);
27659371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
27669371c9d4SSatish Balay   }
27679371c9d4SSatish Balay   if (perms) {
27684f572ea9SToby Isaac     PetscAssertPointer(perms, 6);
27698e3a54c0SPierre Jolivet     *perms = PetscSafePointerPlusOffset(sl->perms[i], sl->minMaxOrients[i][0]);
27709371c9d4SSatish Balay   }
27719371c9d4SSatish Balay   if (rots) {
27724f572ea9SToby Isaac     PetscAssertPointer(rots, 7);
27738e3a54c0SPierre Jolivet     *rots = PetscSafePointerPlusOffset(sl->rots[i], sl->minMaxOrients[i][0]);
27749371c9d4SSatish Balay   }
27753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2776b004864fSMatthew G. Knepley }
2777b004864fSMatthew G. Knepley 
2778b004864fSMatthew G. Knepley /*@C
27795fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
27805fdea053SToby Isaac 
278120f4b53cSBarry Smith   Logically
27825fdea053SToby Isaac 
27835fdea053SToby Isaac   Input Parameters:
27845b5e7992SMatthew G. Knepley + sym       - the section symmetries
27855fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
278620f4b53cSBarry Smith . size      - the number of dofs for points in the `stratum` of the label
278720f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
278820f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a point in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
278920f4b53cSBarry Smith . mode      - how `sym` should copy the `perms` and `rots` arrays
279020f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
279120f4b53cSBarry Smith - rots      - `NULL` if there are no rotations, or (`maxOrient` - `minOrient`) sets of rotations, one for each orientation.  A `NULL` set of orientations is the identity
27925fdea053SToby Isaac 
27935fdea053SToby Isaac   Level: developer
27945fdea053SToby Isaac 
279520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
27965fdea053SToby Isaac @*/
2797d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2798d71ae5a4SJacob Faibussowitsch {
27995fdea053SToby Isaac   PetscSectionSym_Label *sl;
2800d67d17b1SMatthew G. Knepley   const char            *name;
2801d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
28025fdea053SToby Isaac 
28035fdea053SToby Isaac   PetscFunctionBegin;
28045fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
28055fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2806b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
28075fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
28085fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
28095fdea053SToby Isaac 
28105fdea053SToby Isaac     if (stratum == value) break;
28115fdea053SToby Isaac   }
28129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
281363a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
28145fdea053SToby Isaac   sl->sizes[i]            = size;
28155fdea053SToby Isaac   sl->modes[i]            = mode;
28165fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
28175fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
28185fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
28195fdea053SToby Isaac     if (perms) {
28205fdea053SToby Isaac       PetscInt **ownPerms;
28215fdea053SToby Isaac 
28229566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
28235fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28245fdea053SToby Isaac         if (perms[j]) {
28259566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2826ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
28275fdea053SToby Isaac         }
28285fdea053SToby Isaac       }
28295fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
28305fdea053SToby Isaac     }
28315fdea053SToby Isaac     if (rots) {
28325fdea053SToby Isaac       PetscScalar **ownRots;
28335fdea053SToby Isaac 
28349566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
28355fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28365fdea053SToby Isaac         if (rots[j]) {
28379566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2838ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
28395fdea053SToby Isaac         }
28405fdea053SToby Isaac       }
28415fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
28425fdea053SToby Isaac     }
28435fdea053SToby Isaac   } else {
28448e3a54c0SPierre Jolivet     sl->perms[i] = PetscSafePointerPlusOffset(perms, -minOrient);
28458e3a54c0SPierre Jolivet     sl->rots[i]  = PetscSafePointerPlusOffset(rots, -minOrient);
28465fdea053SToby Isaac   }
28473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28485fdea053SToby Isaac }
28495fdea053SToby Isaac 
2850d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2851d71ae5a4SJacob Faibussowitsch {
28525fdea053SToby Isaac   PetscInt               i, j, numStrata;
28535fdea053SToby Isaac   PetscSectionSym_Label *sl;
28545fdea053SToby Isaac   DMLabel                label;
28555fdea053SToby Isaac 
28565fdea053SToby Isaac   PetscFunctionBegin;
28575fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
28585fdea053SToby Isaac   numStrata = sl->numStrata;
28595fdea053SToby Isaac   label     = sl->label;
28605fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
28615fdea053SToby Isaac     PetscInt point = points[2 * i];
28625fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
28635fdea053SToby Isaac 
28645fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
28655fdea053SToby Isaac       if (label->validIS[j]) {
28665fdea053SToby Isaac         PetscInt k;
28675fdea053SToby Isaac 
28682b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(label->points[j], point, &k));
28695fdea053SToby Isaac         if (k >= 0) break;
28705fdea053SToby Isaac       } else {
28715fdea053SToby Isaac         PetscBool has;
28725fdea053SToby Isaac 
28739566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
28745fdea053SToby Isaac         if (has) break;
28755fdea053SToby Isaac       }
28765fdea053SToby Isaac     }
28779371c9d4SSatish Balay     PetscCheck(!(sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) || !(ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "point %" PetscInt_FMT " orientation %" PetscInt_FMT " not in range [%" PetscInt_FMT ", %" PetscInt_FMT ") for stratum %" PetscInt_FMT, point, ornt, sl->minMaxOrients[j][0], sl->minMaxOrients[j][1],
28789371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2879ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2880ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
28815fdea053SToby Isaac   }
28823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28835fdea053SToby Isaac }
28845fdea053SToby Isaac 
2885d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2886d71ae5a4SJacob Faibussowitsch {
2887b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2888b004864fSMatthew G. Knepley   IS                     valIS;
2889b004864fSMatthew G. Knepley   const PetscInt        *values;
2890b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2891b004864fSMatthew G. Knepley 
2892b004864fSMatthew G. Knepley   PetscFunctionBegin;
28939566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
28949566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
28959566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2896b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2897b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2898b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2899b004864fSMatthew G. Knepley     const PetscInt    **perms;
2900b004864fSMatthew G. Knepley     const PetscScalar **rots;
2901b004864fSMatthew G. Knepley 
29029566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
29039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2904b004864fSMatthew G. Knepley   }
29059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
29063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2907b004864fSMatthew G. Knepley }
2908b004864fSMatthew G. Knepley 
2909d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2910d71ae5a4SJacob Faibussowitsch {
2911b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2912b004864fSMatthew G. Knepley   DMLabel                dlabel;
2913b004864fSMatthew G. Knepley 
2914b004864fSMatthew G. Knepley   PetscFunctionBegin;
29159566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
29169566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
29179566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
29189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
29193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2920b004864fSMatthew G. Knepley }
2921b004864fSMatthew G. Knepley 
2922d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2923d71ae5a4SJacob Faibussowitsch {
29245fdea053SToby Isaac   PetscSectionSym_Label *sl;
29255fdea053SToby Isaac 
29265fdea053SToby Isaac   PetscFunctionBegin;
29274dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
29285fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2929b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2930b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
29315fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
29325fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
29335fdea053SToby Isaac   sym->data            = (void *)sl;
29343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29355fdea053SToby Isaac }
29365fdea053SToby Isaac 
29375fdea053SToby Isaac /*@
29385fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
29395fdea053SToby Isaac 
29405fdea053SToby Isaac   Collective
29415fdea053SToby Isaac 
29425fdea053SToby Isaac   Input Parameters:
29435fdea053SToby Isaac + comm  - the MPI communicator for the new symmetry
29445fdea053SToby Isaac - label - the label defining the strata
29455fdea053SToby Isaac 
29462fe279fdSBarry Smith   Output Parameter:
29475fdea053SToby Isaac . sym - the section symmetries
29485fdea053SToby Isaac 
29495fdea053SToby Isaac   Level: developer
29505fdea053SToby Isaac 
295120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
29525fdea053SToby Isaac @*/
2953d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2954d71ae5a4SJacob Faibussowitsch {
29555fdea053SToby Isaac   PetscFunctionBegin;
29569566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
29579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
29589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
29599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
29603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29615fdea053SToby Isaac }
2962