xref: /petsc/src/dm/label/dmlabel.c (revision 9f196a0264fbaf0568fead3a30c861c7ae4cf663)
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   }
115f622de60SMatthew G. Knepley   PetscCall(ISSetInfo(is, IS_SORTED, IS_LOCAL, PETSC_TRUE, PETSC_TRUE));
1169566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)is, "indices"));
117277ea44aSLisandro Dalcin   label->points[v]  = is;
118ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
1199566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
1203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121c58f1c22SToby Isaac }
122c58f1c22SToby Isaac 
123c58f1c22SToby Isaac /*
124c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
125c58f1c22SToby Isaac 
12620f4b53cSBarry Smith   Not Collective
1275b5e7992SMatthew G. Knepley 
128c58f1c22SToby Isaac   Input parameter:
12920f4b53cSBarry Smith . label - The `DMLabel`
130c58f1c22SToby Isaac 
131c58f1c22SToby Isaac   Output parameter:
13220f4b53cSBarry Smith . label - The `DMLabel` with all strata in sorted list format
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Level: developer
135c58f1c22SToby Isaac 
13620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
137c58f1c22SToby Isaac */
138d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
139d71ae5a4SJacob Faibussowitsch {
140c58f1c22SToby Isaac   PetscInt v;
141c58f1c22SToby Isaac 
142c58f1c22SToby Isaac   PetscFunctionBegin;
14348a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeValid_Private(label, v));
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145c58f1c22SToby Isaac }
146c58f1c22SToby Isaac 
147c58f1c22SToby Isaac /*
148c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
149c58f1c22SToby Isaac 
15020f4b53cSBarry Smith   Not Collective
1515b5e7992SMatthew G. Knepley 
152c58f1c22SToby Isaac   Input parameter:
15320f4b53cSBarry Smith + label - The `DMLabel`
154c58f1c22SToby Isaac - v - The stratum value
155c58f1c22SToby Isaac 
156c58f1c22SToby Isaac   Output parameter:
15720f4b53cSBarry Smith . label - The `DMLabel` with stratum in hash format
158c58f1c22SToby Isaac 
159c58f1c22SToby Isaac   Level: developer
160c58f1c22SToby Isaac 
16120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
162c58f1c22SToby Isaac */
163d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
164d71ae5a4SJacob Faibussowitsch {
165c58f1c22SToby Isaac   PetscInt        p;
166ad8374ffSToby Isaac   const PetscInt *points;
167c58f1c22SToby Isaac 
168c58f1c22SToby Isaac   PetscFunctionBegin;
1694d86920dSPierre Jolivet   if ((PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) || label->readonly) PetscFunctionReturn(PETSC_SUCCESS);
1701dca8a05SBarry 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);
171ad8374ffSToby Isaac   if (label->points[v]) {
1729566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
17348a46eb9SPierre Jolivet     for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
1749566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
175f4f49eeaSPierre Jolivet     PetscCall(ISDestroy(&label->points[v]));
176ad8374ffSToby Isaac   }
177ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
1783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
179c58f1c22SToby Isaac }
180c58f1c22SToby Isaac 
181d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelMakeAllInvalid_Internal(DMLabel label)
182d71ae5a4SJacob Faibussowitsch {
183695799ffSMatthew G. Knepley   PetscInt v;
184695799ffSMatthew G. Knepley 
185695799ffSMatthew G. Knepley   PetscFunctionBegin;
18648a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeInvalid_Private(label, v));
1873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
188695799ffSMatthew G. Knepley }
189695799ffSMatthew G. Knepley 
190b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
191b9907514SLisandro Dalcin   #define DMLABEL_LOOKUP_THRESHOLD 16
192b9907514SLisandro Dalcin #endif
193b9907514SLisandro Dalcin 
1949f6c5813SMatthew G. Knepley PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
195d71ae5a4SJacob Faibussowitsch {
1960c3c4a36SLisandro Dalcin   PetscInt v;
1970e79e033SBarry Smith 
1980c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1990e79e033SBarry Smith   *index = -1;
2009f6c5813SMatthew G. Knepley   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD || label->readonly) {
201b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
2029371c9d4SSatish Balay       if (label->stratumValues[v] == value) {
2039371c9d4SSatish Balay         *index = v;
2049371c9d4SSatish Balay         break;
2059371c9d4SSatish Balay       }
206b9907514SLisandro Dalcin   } else {
2079566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(label->hmap, value, index));
2080e79e033SBarry Smith   }
2099f6c5813SMatthew G. Knepley   if (PetscDefined(USE_DEBUG) && !label->readonly) { /* Check strata hash map consistency */
21090e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
2119566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(label->hmap, &len));
21208401ef6SPierre Jolivet     PetscCheck(len == label->numStrata, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
21390e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
2149566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(label->hmap, value, &loc));
21590e9b2aeSLisandro Dalcin     } else {
21690e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
2179371c9d4SSatish Balay         if (label->stratumValues[v] == value) {
2189371c9d4SSatish Balay           loc = v;
2199371c9d4SSatish Balay           break;
2209371c9d4SSatish Balay         }
22190e9b2aeSLisandro Dalcin     }
22208401ef6SPierre Jolivet     PetscCheck(loc == *index, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
22390e9b2aeSLisandro Dalcin   }
2243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2250c3c4a36SLisandro Dalcin }
2260c3c4a36SLisandro Dalcin 
227d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
228d71ae5a4SJacob Faibussowitsch {
229b9907514SLisandro Dalcin   PetscInt    v;
230b9907514SLisandro Dalcin   PetscInt   *tmpV;
231b9907514SLisandro Dalcin   PetscInt   *tmpS;
232b9907514SLisandro Dalcin   PetscHSetI *tmpH, ht;
233b9907514SLisandro Dalcin   IS         *tmpP, is;
234c58f1c22SToby Isaac   PetscBool  *tmpB;
235b9907514SLisandro Dalcin   PetscHMapI  hmap = label->hmap;
236c58f1c22SToby Isaac 
237c58f1c22SToby Isaac   PetscFunctionBegin;
238b9907514SLisandro Dalcin   v    = label->numStrata;
239b9907514SLisandro Dalcin   tmpV = label->stratumValues;
240b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
241b9907514SLisandro Dalcin   tmpH = label->ht;
242b9907514SLisandro Dalcin   tmpP = label->points;
243b9907514SLisandro Dalcin   tmpB = label->validIS;
2448e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2458e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2468e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2478e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2488e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2498e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpV), &tmpV));
2519566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpS), &tmpS));
2529f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc((v + 1) * sizeof(*tmpH), &tmpH));
2539f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc((v + 1) * sizeof(*tmpP), &tmpP));
2549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpB), &tmpB));
2559566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpV, oldV, v));
2569566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpS, oldS, v));
2579566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpH, oldH, v));
2589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpP, oldP, v));
2599566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpB, oldB, v));
2609566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldV));
2619566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldS));
2629566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldH));
2639566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldP));
2649566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldB));
2658e1f8cf0SLisandro Dalcin   }
266b9907514SLisandro Dalcin   label->numStrata     = v + 1;
267c58f1c22SToby Isaac   label->stratumValues = tmpV;
268c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
269c58f1c22SToby Isaac   label->ht            = tmpH;
270c58f1c22SToby Isaac   label->points        = tmpP;
271ad8374ffSToby Isaac   label->validIS       = tmpB;
2729566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
2739566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
2749566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(hmap, value, v));
275b9907514SLisandro Dalcin   tmpV[v] = value;
276b9907514SLisandro Dalcin   tmpS[v] = 0;
277b9907514SLisandro Dalcin   tmpH[v] = ht;
278b9907514SLisandro Dalcin   tmpP[v] = is;
279b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
2809566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
2810c3c4a36SLisandro Dalcin   *index = v;
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2830c3c4a36SLisandro Dalcin }
2840c3c4a36SLisandro Dalcin 
285d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
286d71ae5a4SJacob Faibussowitsch {
287b9907514SLisandro Dalcin   PetscFunctionBegin;
2889566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, index));
2899566063dSJacob Faibussowitsch   if (*index < 0) PetscCall(DMLabelNewStratum(label, value, index));
2903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
291b9907514SLisandro Dalcin }
292b9907514SLisandro Dalcin 
2939f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
294d71ae5a4SJacob Faibussowitsch {
2959e63cc69SVaclav Hapla   PetscFunctionBegin;
2969e63cc69SVaclav Hapla   *size = 0;
2973ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
2989f6c5813SMatthew G. Knepley   if (label->readonly || label->validIS[v]) {
2999e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
3009e63cc69SVaclav Hapla   } else {
3019566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(label->ht[v], size));
3029e63cc69SVaclav Hapla   }
3033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3049e63cc69SVaclav Hapla }
3059e63cc69SVaclav Hapla 
306b9907514SLisandro Dalcin /*@
30720f4b53cSBarry Smith   DMLabelAddStratum - Adds a new stratum value in a `DMLabel`
308b9907514SLisandro Dalcin 
309d8d19677SJose E. Roman   Input Parameters:
31020f4b53cSBarry Smith + label - The `DMLabel`
311b9907514SLisandro Dalcin - value - The stratum value
312b9907514SLisandro Dalcin 
313b9907514SLisandro Dalcin   Level: beginner
314b9907514SLisandro Dalcin 
31520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
316b9907514SLisandro Dalcin @*/
317d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
318d71ae5a4SJacob Faibussowitsch {
3190c3c4a36SLisandro Dalcin   PetscInt v;
3200c3c4a36SLisandro Dalcin 
3210c3c4a36SLisandro Dalcin   PetscFunctionBegin;
322d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
3239f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
3249566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
3253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326b9907514SLisandro Dalcin }
327b9907514SLisandro Dalcin 
328b9907514SLisandro Dalcin /*@
32920f4b53cSBarry Smith   DMLabelAddStrata - Adds new stratum values in a `DMLabel`
330b9907514SLisandro Dalcin 
33120f4b53cSBarry Smith   Not Collective
3325b5e7992SMatthew G. Knepley 
333d8d19677SJose E. Roman   Input Parameters:
33420f4b53cSBarry Smith + label         - The `DMLabel`
335b9907514SLisandro Dalcin . numStrata     - The number of stratum values
336b9907514SLisandro Dalcin - stratumValues - The stratum values
337b9907514SLisandro Dalcin 
338b9907514SLisandro Dalcin   Level: beginner
339b9907514SLisandro Dalcin 
34020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
341b9907514SLisandro Dalcin @*/
342d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
343d71ae5a4SJacob Faibussowitsch {
344b9907514SLisandro Dalcin   PetscInt *values, v;
345b9907514SLisandro Dalcin 
346b9907514SLisandro Dalcin   PetscFunctionBegin;
347b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
3484f572ea9SToby Isaac   if (numStrata) PetscAssertPointer(stratumValues, 3);
3499f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
3509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numStrata, &values));
3519566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(values, stratumValues, numStrata));
3529566063dSJacob Faibussowitsch   PetscCall(PetscSortRemoveDupsInt(&numStrata, values));
353b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
354b9907514SLisandro Dalcin     PetscInt   *tmpV;
355b9907514SLisandro Dalcin     PetscInt   *tmpS;
356b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
357b9907514SLisandro Dalcin     IS         *tmpP, is;
358b9907514SLisandro Dalcin     PetscBool  *tmpB;
359b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
360b9907514SLisandro Dalcin 
3619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpV));
3629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpS));
3639f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(numStrata, &tmpH));
3649f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(numStrata, &tmpP));
3659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpB));
366b9907514SLisandro Dalcin     label->numStrata     = numStrata;
367b9907514SLisandro Dalcin     label->stratumValues = tmpV;
368b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
369b9907514SLisandro Dalcin     label->ht            = tmpH;
370b9907514SLisandro Dalcin     label->points        = tmpP;
371b9907514SLisandro Dalcin     label->validIS       = tmpB;
372b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3739566063dSJacob Faibussowitsch       PetscCall(PetscHSetICreate(&ht));
3749566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
3759566063dSJacob Faibussowitsch       PetscCall(PetscHMapISet(hmap, values[v], v));
376b9907514SLisandro Dalcin       tmpV[v] = values[v];
377b9907514SLisandro Dalcin       tmpS[v] = 0;
378b9907514SLisandro Dalcin       tmpH[v] = ht;
379b9907514SLisandro Dalcin       tmpP[v] = is;
380b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
381b9907514SLisandro Dalcin     }
3829566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
383b9907514SLisandro Dalcin   } else {
38448a46eb9SPierre Jolivet     for (v = 0; v < numStrata; ++v) PetscCall(DMLabelAddStratum(label, values[v]));
385b9907514SLisandro Dalcin   }
3869566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
3873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388b9907514SLisandro Dalcin }
389b9907514SLisandro Dalcin 
390b9907514SLisandro Dalcin /*@
39120f4b53cSBarry Smith   DMLabelAddStrataIS - Adds new stratum values in a `DMLabel`
392b9907514SLisandro Dalcin 
39320f4b53cSBarry Smith   Not Collective
3945b5e7992SMatthew G. Knepley 
395d8d19677SJose E. Roman   Input Parameters:
39620f4b53cSBarry Smith + label   - The `DMLabel`
397b9907514SLisandro Dalcin - valueIS - Index set with stratum values
398b9907514SLisandro Dalcin 
399b9907514SLisandro Dalcin   Level: beginner
400b9907514SLisandro Dalcin 
40120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
402b9907514SLisandro Dalcin @*/
403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
404d71ae5a4SJacob Faibussowitsch {
405b9907514SLisandro Dalcin   PetscInt        numStrata;
406b9907514SLisandro Dalcin   const PetscInt *stratumValues;
407b9907514SLisandro Dalcin 
408b9907514SLisandro Dalcin   PetscFunctionBegin;
409b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
410b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
4119f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
4129566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(valueIS, &numStrata));
4139566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valueIS, &stratumValues));
4149566063dSJacob Faibussowitsch   PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
4153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
416c58f1c22SToby Isaac }
417c58f1c22SToby Isaac 
4189f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelView_Concrete_Ascii(DMLabel label, PetscViewer viewer)
419d71ae5a4SJacob Faibussowitsch {
420c58f1c22SToby Isaac   PetscInt    v;
421c58f1c22SToby Isaac   PetscMPIInt rank;
422c58f1c22SToby Isaac 
423c58f1c22SToby Isaac   PetscFunctionBegin;
4249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
4259566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
426c58f1c22SToby Isaac   if (label) {
427d67d17b1SMatthew G. Knepley     const char *name;
428d67d17b1SMatthew G. Knepley 
4299566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
4309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
43163a3b9bcSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", label->pStart, label->pEnd));
432c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
433c58f1c22SToby Isaac       const PetscInt  value = label->stratumValues[v];
434ad8374ffSToby Isaac       const PetscInt *points;
435c58f1c22SToby Isaac       PetscInt        p;
436c58f1c22SToby Isaac 
4379566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
43848a46eb9SPierre Jolivet       for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, points[p], value));
4399566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
440c58f1c22SToby Isaac     }
441c58f1c22SToby Isaac   }
4429566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4439566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445c58f1c22SToby Isaac }
446c58f1c22SToby Isaac 
44766976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelView_Concrete(DMLabel label, PetscViewer viewer)
4489f6c5813SMatthew G. Knepley {
449*9f196a02SMartin Diehl   PetscBool isascii;
4509f6c5813SMatthew G. Knepley 
4519f6c5813SMatthew G. Knepley   PetscFunctionBegin;
452*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
453*9f196a02SMartin Diehl   if (isascii) PetscCall(DMLabelView_Concrete_Ascii(label, viewer));
4543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4559f6c5813SMatthew G. Knepley }
4569f6c5813SMatthew G. Knepley 
457ffeef943SBarry Smith /*@
458c58f1c22SToby Isaac   DMLabelView - View the label
459c58f1c22SToby Isaac 
46020f4b53cSBarry Smith   Collective
4615b5e7992SMatthew G. Knepley 
462c58f1c22SToby Isaac   Input Parameters:
46320f4b53cSBarry Smith + label  - The `DMLabel`
46420f4b53cSBarry Smith - viewer - The `PetscViewer`
465c58f1c22SToby Isaac 
466c58f1c22SToby Isaac   Level: intermediate
467c58f1c22SToby Isaac 
46820f4b53cSBarry Smith .seealso: `DMLabel`, `PetscViewer`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
469c58f1c22SToby Isaac @*/
470d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
471d71ae5a4SJacob Faibussowitsch {
472c58f1c22SToby Isaac   PetscFunctionBegin;
473d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4749566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
475c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4769f6c5813SMatthew G. Knepley   PetscCall(DMLabelMakeAllValid_Private(label));
4779f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, view, viewer);
4783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
479c58f1c22SToby Isaac }
480c58f1c22SToby Isaac 
48184f0b6dfSMatthew G. Knepley /*@
48220f4b53cSBarry Smith   DMLabelReset - Destroys internal data structures in a `DMLabel`
483d67d17b1SMatthew G. Knepley 
48420f4b53cSBarry Smith   Not Collective
4855b5e7992SMatthew G. Knepley 
486d67d17b1SMatthew G. Knepley   Input Parameter:
48720f4b53cSBarry Smith . label - The `DMLabel`
488d67d17b1SMatthew G. Knepley 
489d67d17b1SMatthew G. Knepley   Level: beginner
490d67d17b1SMatthew G. Knepley 
49120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`, `DMLabelCreate()`
492d67d17b1SMatthew G. Knepley @*/
493d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelReset(DMLabel label)
494d71ae5a4SJacob Faibussowitsch {
495d67d17b1SMatthew G. Knepley   PetscInt v;
496d67d17b1SMatthew G. Knepley 
497d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
498d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
499d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
5009f6c5813SMatthew G. Knepley     if (label->ht[v]) PetscCall(PetscHSetIDestroy(&label->ht[v]));
5019566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
502d67d17b1SMatthew G. Knepley   }
503b9907514SLisandro Dalcin   label->numStrata = 0;
5049566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
5059566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
5069566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
5079566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
5089566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
5099566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
510b9907514SLisandro Dalcin   label->pStart = -1;
511b9907514SLisandro Dalcin   label->pEnd   = -1;
5129566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
5133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
514d67d17b1SMatthew G. Knepley }
515d67d17b1SMatthew G. Knepley 
516d67d17b1SMatthew G. Knepley /*@
51720f4b53cSBarry Smith   DMLabelDestroy - Destroys a `DMLabel`
51884f0b6dfSMatthew G. Knepley 
51920f4b53cSBarry Smith   Collective
5205b5e7992SMatthew G. Knepley 
52184f0b6dfSMatthew G. Knepley   Input Parameter:
52220f4b53cSBarry Smith . label - The `DMLabel`
52384f0b6dfSMatthew G. Knepley 
52484f0b6dfSMatthew G. Knepley   Level: beginner
52584f0b6dfSMatthew G. Knepley 
52620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelReset()`, `DMLabelCreate()`
52784f0b6dfSMatthew G. Knepley @*/
528d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
529d71ae5a4SJacob Faibussowitsch {
530c58f1c22SToby Isaac   PetscFunctionBegin;
5313ba16761SJacob Faibussowitsch   if (!*label) PetscFunctionReturn(PETSC_SUCCESS);
532f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 1);
533f4f49eeaSPierre Jolivet   if (--((PetscObject)*label)->refct > 0) {
5349371c9d4SSatish Balay     *label = NULL;
5353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5369371c9d4SSatish Balay   }
5379566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5389566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5399566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
5403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
541c58f1c22SToby Isaac }
542c58f1c22SToby Isaac 
54366976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDuplicate_Concrete(DMLabel label, DMLabel *labelnew)
5449f6c5813SMatthew G. Knepley {
5459f6c5813SMatthew G. Knepley   PetscFunctionBegin;
5469f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
5479f6c5813SMatthew G. Knepley     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
548f4f49eeaSPierre Jolivet     PetscCall(PetscObjectReference((PetscObject)label->points[v]));
5499f6c5813SMatthew G. Knepley     (*labelnew)->points[v] = label->points[v];
5509f6c5813SMatthew G. Knepley   }
5519f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5529f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
5533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5549f6c5813SMatthew G. Knepley }
5559f6c5813SMatthew G. Knepley 
55684f0b6dfSMatthew G. Knepley /*@
55720f4b53cSBarry Smith   DMLabelDuplicate - Duplicates a `DMLabel`
55884f0b6dfSMatthew G. Knepley 
55920f4b53cSBarry Smith   Collective
5605b5e7992SMatthew G. Knepley 
56184f0b6dfSMatthew G. Knepley   Input Parameter:
56220f4b53cSBarry Smith . label - The `DMLabel`
56384f0b6dfSMatthew G. Knepley 
56484f0b6dfSMatthew G. Knepley   Output Parameter:
56520f4b53cSBarry Smith . labelnew - new label
56684f0b6dfSMatthew G. Knepley 
56784f0b6dfSMatthew G. Knepley   Level: intermediate
56884f0b6dfSMatthew G. Knepley 
56920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
57084f0b6dfSMatthew G. Knepley @*/
571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
572d71ae5a4SJacob Faibussowitsch {
573d67d17b1SMatthew G. Knepley   const char *name;
574c58f1c22SToby Isaac 
575c58f1c22SToby Isaac   PetscFunctionBegin;
576d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5779566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
5799566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
580c58f1c22SToby Isaac 
581c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5825aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5838dcf10e8SMatthew G. Knepley   (*labelnew)->readonly     = label->readonly;
5849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5869f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->ht));
5879f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->points));
5889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
5899f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
590c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
591c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
592b9907514SLisandro Dalcin     (*labelnew)->validIS[v]       = PETSC_TRUE;
593c58f1c22SToby Isaac   }
594c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
595c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
596c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
5979f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, duplicate, labelnew);
5983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
599c58f1c22SToby Isaac }
600c58f1c22SToby Isaac 
601609dae6eSVaclav Hapla /*@C
60220f4b53cSBarry Smith   DMLabelCompare - Compare two `DMLabel` objects
603609dae6eSVaclav Hapla 
60420f4b53cSBarry Smith   Collective; No Fortran Support
605609dae6eSVaclav Hapla 
606609dae6eSVaclav Hapla   Input Parameters:
607f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
60820f4b53cSBarry Smith . l0   - First `DMLabel`
60920f4b53cSBarry Smith - l1   - Second `DMLabel`
610609dae6eSVaclav Hapla 
611a4e35b19SJacob Faibussowitsch   Output Parameters:
6125efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
6135efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
614609dae6eSVaclav Hapla 
615609dae6eSVaclav Hapla   Level: intermediate
616609dae6eSVaclav Hapla 
617609dae6eSVaclav Hapla   Notes:
6185efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
61920f4b53cSBarry Smith   If it is passed as `NULL` and difference is found, an error is thrown on all processes.
62020f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
621609dae6eSVaclav Hapla 
6225efe38ccSVaclav Hapla   The output message is set independently on each rank.
62320f4b53cSBarry Smith   It is set to `NULL` if no difference was found on the current rank. It must be freed by user.
62420f4b53cSBarry Smith   If message is passed as `NULL` and difference is found, the difference description is printed to stderr in synchronized manner.
62520f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
626609dae6eSVaclav Hapla 
627609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
628609dae6eSVaclav Hapla 
62920f4b53cSBarry Smith   The communicator needs to be specified because currently `DMLabel` can live on `PETSC_COMM_SELF` even if the underlying `DM` is parallel.
6305efe38ccSVaclav Hapla 
631a3b724e8SBarry Smith   Developer Note:
632a3b724e8SBarry Smith   Fortran stub cannot be generated automatically because `message` must be freed with `PetscFree()`
633a3b724e8SBarry Smith 
63420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
635609dae6eSVaclav Hapla @*/
636d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
637d71ae5a4SJacob Faibussowitsch {
638609dae6eSVaclav Hapla   const char *name0, *name1;
639609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6405efe38ccSVaclav Hapla   PetscBool   eq;
6415efe38ccSVaclav Hapla   PetscMPIInt rank;
642609dae6eSVaclav Hapla 
643609dae6eSVaclav Hapla   PetscFunctionBegin;
6445efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6455efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6464f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 4);
6474f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 5);
6489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6499566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
651609dae6eSVaclav Hapla   {
652609dae6eSVaclav Hapla     PetscInt v0, v1;
653609dae6eSVaclav Hapla 
6549566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6559566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6565efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
65748a46eb9SPierre 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));
658462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6595efe38ccSVaclav Hapla     if (!eq) goto finish;
660609dae6eSVaclav Hapla   }
661609dae6eSVaclav Hapla   {
662609dae6eSVaclav Hapla     IS is0, is1;
663609dae6eSVaclav Hapla 
6649566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6659566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6669566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6679566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6689566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
66948a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
670462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6715efe38ccSVaclav Hapla     if (!eq) goto finish;
672609dae6eSVaclav Hapla   }
673609dae6eSVaclav Hapla   {
674609dae6eSVaclav Hapla     PetscInt i, nValues;
675609dae6eSVaclav Hapla 
6769566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
677609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
678609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
679609dae6eSVaclav Hapla       PetscInt       n;
680609dae6eSVaclav Hapla       IS             is0, is1;
681609dae6eSVaclav Hapla 
6829566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
683609dae6eSVaclav Hapla       if (!n) continue;
6849566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6859566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6869566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6879566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6889566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6895efe38ccSVaclav Hapla       if (!eq) {
69063a3b9bcSJacob 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));
6915efe38ccSVaclav Hapla         break;
692609dae6eSVaclav Hapla       }
693609dae6eSVaclav Hapla     }
694462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
695609dae6eSVaclav Hapla   }
696609dae6eSVaclav Hapla finish:
6975efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
698609dae6eSVaclav Hapla   if (message) {
699609dae6eSVaclav Hapla     *message = NULL;
70048a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
7015efe38ccSVaclav Hapla   } else {
70248a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
7039566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
7045efe38ccSVaclav Hapla   }
7055efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
7065efe38ccSVaclav Hapla   if (equal) *equal = eq;
70763a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
7083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
709609dae6eSVaclav Hapla }
710609dae6eSVaclav Hapla 
711c6a43d28SMatthew G. Knepley /*@
712c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
713c6a43d28SMatthew G. Knepley 
71420f4b53cSBarry Smith   Not Collective
7155b5e7992SMatthew G. Knepley 
716c6a43d28SMatthew G. Knepley   Input Parameter:
71720f4b53cSBarry Smith . label - The `DMLabel`
718c6a43d28SMatthew G. Knepley 
719c6a43d28SMatthew G. Knepley   Level: intermediate
720c6a43d28SMatthew G. Knepley 
72120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
722c6a43d28SMatthew G. Knepley @*/
723d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
724d71ae5a4SJacob Faibussowitsch {
7251690c2aeSBarry Smith   PetscInt pStart = PETSC_INT_MAX, pEnd = -1, v;
726c6a43d28SMatthew G. Knepley 
727c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
728c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7299566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
730c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
731c6a43d28SMatthew G. Knepley     const PetscInt *points;
732c6a43d28SMatthew G. Knepley     PetscInt        i;
733c6a43d28SMatthew G. Knepley 
7349566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
735c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
736c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
737c6a43d28SMatthew G. Knepley 
738c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
739c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
740c6a43d28SMatthew G. Knepley     }
7419566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
742c6a43d28SMatthew G. Knepley   }
7431690c2aeSBarry Smith   label->pStart = pStart == PETSC_INT_MAX ? -1 : pStart;
744c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7459566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
7463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
747c6a43d28SMatthew G. Knepley }
748c6a43d28SMatthew G. Knepley 
749c6a43d28SMatthew G. Knepley /*@
750c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
751c6a43d28SMatthew G. Knepley 
75220f4b53cSBarry Smith   Not Collective
7535b5e7992SMatthew G. Knepley 
754c6a43d28SMatthew G. Knepley   Input Parameters:
75520f4b53cSBarry Smith + label  - The `DMLabel`
756c6a43d28SMatthew G. Knepley . pStart - The smallest point
757c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
758c6a43d28SMatthew G. Knepley 
759c6a43d28SMatthew G. Knepley   Level: intermediate
760c6a43d28SMatthew G. Knepley 
76120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
762c6a43d28SMatthew G. Knepley @*/
763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
764d71ae5a4SJacob Faibussowitsch {
765c58f1c22SToby Isaac   PetscInt v;
766c58f1c22SToby Isaac 
767c58f1c22SToby Isaac   PetscFunctionBegin;
768d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7699566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7709566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
771c58f1c22SToby Isaac   label->pStart = pStart;
772c58f1c22SToby Isaac   label->pEnd   = pEnd;
773c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7749566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
775c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
7769f6c5813SMatthew G. Knepley     IS              pointIS;
777ad8374ffSToby Isaac     const PetscInt *points;
778c58f1c22SToby Isaac     PetscInt        i;
779c58f1c22SToby Isaac 
7809f6c5813SMatthew G. Knepley     PetscUseTypeMethod(label, getstratumis, v, &pointIS);
7819f6c5813SMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
782c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
783ad8374ffSToby Isaac       const PetscInt point = points[i];
784c58f1c22SToby Isaac 
7859f6c5813SMatthew 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);
7869566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
787c58f1c22SToby Isaac     }
7889566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
7899f6c5813SMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
790c58f1c22SToby Isaac   }
7913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
792c58f1c22SToby Isaac }
793c58f1c22SToby Isaac 
794c6a43d28SMatthew G. Knepley /*@
795c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
796c6a43d28SMatthew G. Knepley 
79720f4b53cSBarry Smith   Not Collective
7985b5e7992SMatthew G. Knepley 
799c6a43d28SMatthew G. Knepley   Input Parameter:
80020f4b53cSBarry Smith . label - the `DMLabel`
801c6a43d28SMatthew G. Knepley 
802c6a43d28SMatthew G. Knepley   Level: intermediate
803c6a43d28SMatthew G. Knepley 
80420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
805c6a43d28SMatthew G. Knepley @*/
806d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
807d71ae5a4SJacob Faibussowitsch {
808c58f1c22SToby Isaac   PetscFunctionBegin;
809d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
810c58f1c22SToby Isaac   label->pStart = -1;
811c58f1c22SToby Isaac   label->pEnd   = -1;
8129566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
8133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
814c58f1c22SToby Isaac }
815c58f1c22SToby Isaac 
816c58f1c22SToby Isaac /*@
817c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
818c6a43d28SMatthew G. Knepley 
81920f4b53cSBarry Smith   Not Collective
8205b5e7992SMatthew G. Knepley 
821c6a43d28SMatthew G. Knepley   Input Parameter:
82220f4b53cSBarry Smith . label - the `DMLabel`
823c6a43d28SMatthew G. Knepley 
824c6a43d28SMatthew G. Knepley   Output Parameters:
825c6a43d28SMatthew G. Knepley + pStart - The smallest point
826c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
827c6a43d28SMatthew G. Knepley 
828c6a43d28SMatthew G. Knepley   Level: intermediate
829c6a43d28SMatthew G. Knepley 
83020f4b53cSBarry Smith   Note:
83120f4b53cSBarry Smith   This will compute an index for the label if one does not exist.
83220f4b53cSBarry Smith 
83320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
834c6a43d28SMatthew G. Knepley @*/
835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
836d71ae5a4SJacob Faibussowitsch {
837c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
838c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8399566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
840c6a43d28SMatthew G. Knepley   if (pStart) {
8414f572ea9SToby Isaac     PetscAssertPointer(pStart, 2);
842c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
843c6a43d28SMatthew G. Knepley   }
844c6a43d28SMatthew G. Knepley   if (pEnd) {
8454f572ea9SToby Isaac     PetscAssertPointer(pEnd, 3);
846c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
847c6a43d28SMatthew G. Knepley   }
8483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
849c6a43d28SMatthew G. Knepley }
850c6a43d28SMatthew G. Knepley 
851c6a43d28SMatthew G. Knepley /*@
852c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
853c58f1c22SToby Isaac 
85420f4b53cSBarry Smith   Not Collective
8555b5e7992SMatthew G. Knepley 
856c58f1c22SToby Isaac   Input Parameters:
85720f4b53cSBarry Smith + label - the `DMLabel`
858c58f1c22SToby Isaac - value - the value
859c58f1c22SToby Isaac 
860c58f1c22SToby Isaac   Output Parameter:
861c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
862c58f1c22SToby Isaac 
863c58f1c22SToby Isaac   Level: developer
864c58f1c22SToby Isaac 
86520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
866c58f1c22SToby Isaac @*/
867d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
868d71ae5a4SJacob Faibussowitsch {
869c58f1c22SToby Isaac   PetscInt v;
870c58f1c22SToby Isaac 
871c58f1c22SToby Isaac   PetscFunctionBegin;
872d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8734f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
8749566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8750c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
8763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
877c58f1c22SToby Isaac }
878c58f1c22SToby Isaac 
879c58f1c22SToby Isaac /*@
880c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
881c58f1c22SToby Isaac 
88220f4b53cSBarry Smith   Not Collective
8835b5e7992SMatthew G. Knepley 
884c58f1c22SToby Isaac   Input Parameters:
88520f4b53cSBarry Smith + label - the `DMLabel`
886c58f1c22SToby Isaac - point - the point
887c58f1c22SToby Isaac 
888c58f1c22SToby Isaac   Output Parameter:
889c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
890c58f1c22SToby Isaac 
891c58f1c22SToby Isaac   Level: developer
892c58f1c22SToby Isaac 
89320f4b53cSBarry Smith   Note:
89420f4b53cSBarry Smith   The user must call `DMLabelCreateIndex()` before this function.
89520f4b53cSBarry Smith 
89620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
897c58f1c22SToby Isaac @*/
898d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
899d71ae5a4SJacob Faibussowitsch {
900c58f1c22SToby Isaac   PetscFunctionBeginHot;
901d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9024f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
9039566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
90476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
90528b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
90663a3b9bcSJacob 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);
90776bd3646SJed Brown   }
908c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
9093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
910c58f1c22SToby Isaac }
911c58f1c22SToby Isaac 
912c58f1c22SToby Isaac /*@
913c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
914c58f1c22SToby Isaac 
91520f4b53cSBarry Smith   Not Collective
9165b5e7992SMatthew G. Knepley 
917c58f1c22SToby Isaac   Input Parameters:
91820f4b53cSBarry Smith + label - the `DMLabel`
919c58f1c22SToby Isaac . value - the stratum value
920c58f1c22SToby Isaac - point - the point
921c58f1c22SToby Isaac 
922c58f1c22SToby Isaac   Output Parameter:
923c58f1c22SToby Isaac . contains - true if the stratum contains the point
924c58f1c22SToby Isaac 
925c58f1c22SToby Isaac   Level: intermediate
926c58f1c22SToby Isaac 
92720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
928c58f1c22SToby Isaac @*/
929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
930d71ae5a4SJacob Faibussowitsch {
9310c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
932d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9334f572ea9SToby Isaac   PetscAssertPointer(contains, 4);
934cffad2c9SToby Isaac   if (value == label->defaultValue) {
935cffad2c9SToby Isaac     PetscInt pointVal;
9360c3c4a36SLisandro Dalcin 
937cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
938cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
939cffad2c9SToby Isaac   } else {
940cffad2c9SToby Isaac     PetscInt v;
941cffad2c9SToby Isaac 
942cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
943cffad2c9SToby Isaac     if (v >= 0) {
9449f6c5813SMatthew G. Knepley       if (label->validIS[v] || label->readonly) {
9459f6c5813SMatthew G. Knepley         IS       is;
946c58f1c22SToby Isaac         PetscInt i;
947c58f1c22SToby Isaac 
9489f6c5813SMatthew G. Knepley         PetscUseTypeMethod(label, getstratumis, v, &is);
9492b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(is, point, &i));
9509f6c5813SMatthew G. Knepley         PetscCall(ISDestroy(&is));
951cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
952c58f1c22SToby Isaac       } else {
953cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
954cffad2c9SToby Isaac       }
955cffad2c9SToby Isaac     } else { // value is not present
956cffad2c9SToby Isaac       *contains = PETSC_FALSE;
957cffad2c9SToby Isaac     }
958c58f1c22SToby Isaac   }
9593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
960c58f1c22SToby Isaac }
961c58f1c22SToby Isaac 
96284f0b6dfSMatthew G. Knepley /*@
96320f4b53cSBarry Smith   DMLabelGetDefaultValue - Get the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9645aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9655aa44df4SToby Isaac 
96620f4b53cSBarry Smith   Not Collective
9675b5e7992SMatthew G. Knepley 
96860225df5SJacob Faibussowitsch   Input Parameter:
96920f4b53cSBarry Smith . label - a `DMLabel` object
9705aa44df4SToby Isaac 
97160225df5SJacob Faibussowitsch   Output Parameter:
9725aa44df4SToby Isaac . defaultValue - the default value
9735aa44df4SToby Isaac 
9745aa44df4SToby Isaac   Level: beginner
9755aa44df4SToby Isaac 
97620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
97784f0b6dfSMatthew G. Knepley @*/
978d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
979d71ae5a4SJacob Faibussowitsch {
9805aa44df4SToby Isaac   PetscFunctionBegin;
981d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9825aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9845aa44df4SToby Isaac }
9855aa44df4SToby Isaac 
98684f0b6dfSMatthew G. Knepley /*@
98720f4b53cSBarry Smith   DMLabelSetDefaultValue - Set the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9885aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9895aa44df4SToby Isaac 
99020f4b53cSBarry Smith   Not Collective
9915b5e7992SMatthew G. Knepley 
99260225df5SJacob Faibussowitsch   Input Parameter:
99320f4b53cSBarry Smith . label - a `DMLabel` object
9945aa44df4SToby Isaac 
99560225df5SJacob Faibussowitsch   Output Parameter:
9965aa44df4SToby Isaac . defaultValue - the default value
9975aa44df4SToby Isaac 
9985aa44df4SToby Isaac   Level: beginner
9995aa44df4SToby Isaac 
100020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
100184f0b6dfSMatthew G. Knepley @*/
1002d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1003d71ae5a4SJacob Faibussowitsch {
10045aa44df4SToby Isaac   PetscFunctionBegin;
1005d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10065aa44df4SToby Isaac   label->defaultValue = defaultValue;
10073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10085aa44df4SToby Isaac }
10095aa44df4SToby Isaac 
1010c58f1c22SToby Isaac /*@
101120f4b53cSBarry 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
101220f4b53cSBarry Smith   `DMLabelSetDefaultValue()`)
1013c58f1c22SToby Isaac 
101420f4b53cSBarry Smith   Not Collective
10155b5e7992SMatthew G. Knepley 
1016c58f1c22SToby Isaac   Input Parameters:
101720f4b53cSBarry Smith + label - the `DMLabel`
1018c58f1c22SToby Isaac - point - the point
1019c58f1c22SToby Isaac 
1020c58f1c22SToby Isaac   Output Parameter:
10218e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
1022c58f1c22SToby Isaac 
1023c58f1c22SToby Isaac   Level: intermediate
1024c58f1c22SToby Isaac 
102520f4b53cSBarry Smith   Note:
102620f4b53cSBarry Smith   A label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.
102720f4b53cSBarry Smith   Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
102820f4b53cSBarry Smith 
102920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1030c58f1c22SToby Isaac @*/
1031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1032d71ae5a4SJacob Faibussowitsch {
1033c58f1c22SToby Isaac   PetscInt v;
1034c58f1c22SToby Isaac 
10350c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
1036d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10374f572ea9SToby Isaac   PetscAssertPointer(value, 3);
10385aa44df4SToby Isaac   *value = label->defaultValue;
1039c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
10409f6c5813SMatthew G. Knepley     if (label->validIS[v] || label->readonly) {
10419f6c5813SMatthew G. Knepley       IS       is;
1042c58f1c22SToby Isaac       PetscInt i;
1043c58f1c22SToby Isaac 
10449f6c5813SMatthew G. Knepley       PetscUseTypeMethod(label, getstratumis, v, &is);
10452b4d18a0SMatthew G. Knepley       PetscCall(ISLocate(label->points[v], point, &i));
10469f6c5813SMatthew G. Knepley       PetscCall(ISDestroy(&is));
1047c58f1c22SToby Isaac       if (i >= 0) {
1048c58f1c22SToby Isaac         *value = label->stratumValues[v];
1049c58f1c22SToby Isaac         break;
1050c58f1c22SToby Isaac       }
1051c58f1c22SToby Isaac     } else {
1052c58f1c22SToby Isaac       PetscBool has;
1053c58f1c22SToby Isaac 
10549566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1055c58f1c22SToby Isaac       if (has) {
1056c58f1c22SToby Isaac         *value = label->stratumValues[v];
1057c58f1c22SToby Isaac         break;
1058c58f1c22SToby Isaac       }
1059c58f1c22SToby Isaac     }
1060c58f1c22SToby Isaac   }
10613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1062c58f1c22SToby Isaac }
1063c58f1c22SToby Isaac 
1064c58f1c22SToby Isaac /*@
106520f4b53cSBarry 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
106620f4b53cSBarry Smith   be changed with `DMLabelSetDefaultValue()` to something different), then this function will do nothing.
1067c58f1c22SToby Isaac 
106820f4b53cSBarry Smith   Not Collective
10695b5e7992SMatthew G. Knepley 
1070c58f1c22SToby Isaac   Input Parameters:
107120f4b53cSBarry Smith + label - the `DMLabel`
1072c58f1c22SToby Isaac . point - the point
1073c58f1c22SToby Isaac - value - The point value
1074c58f1c22SToby Isaac 
1075c58f1c22SToby Isaac   Level: intermediate
1076c58f1c22SToby Isaac 
107720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1078c58f1c22SToby Isaac @*/
1079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1080d71ae5a4SJacob Faibussowitsch {
1081c58f1c22SToby Isaac   PetscInt v;
1082c58f1c22SToby Isaac 
1083c58f1c22SToby Isaac   PetscFunctionBegin;
1084d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10850c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10863ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
10879f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
10889566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1089c58f1c22SToby Isaac   /* Set key */
10909566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10919566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
10923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1093c58f1c22SToby Isaac }
1094c58f1c22SToby Isaac 
1095c58f1c22SToby Isaac /*@
1096c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1097c58f1c22SToby Isaac 
109820f4b53cSBarry Smith   Not Collective
10995b5e7992SMatthew G. Knepley 
1100c58f1c22SToby Isaac   Input Parameters:
110120f4b53cSBarry Smith + label - the `DMLabel`
1102c58f1c22SToby Isaac . point - the point
1103c58f1c22SToby Isaac - value - The point value
1104c58f1c22SToby Isaac 
1105c58f1c22SToby Isaac   Level: intermediate
1106c58f1c22SToby Isaac 
110720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1108c58f1c22SToby Isaac @*/
1109d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1110d71ae5a4SJacob Faibussowitsch {
1111ad8374ffSToby Isaac   PetscInt v;
1112c58f1c22SToby Isaac 
1113c58f1c22SToby Isaac   PetscFunctionBegin;
1114d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11159f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1116c58f1c22SToby Isaac   /* Find label value */
11179566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
11183ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
11190c3c4a36SLisandro Dalcin 
1120eeed21e7SToby Isaac   if (label->bt) {
112163a3b9bcSJacob 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);
11229566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1123eeed21e7SToby Isaac   }
11240c3c4a36SLisandro Dalcin 
11250c3c4a36SLisandro Dalcin   /* Delete key */
11269566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11279566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
11283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1129c58f1c22SToby Isaac }
1130c58f1c22SToby Isaac 
1131c58f1c22SToby Isaac /*@
113220f4b53cSBarry Smith   DMLabelInsertIS - Set all points in the `IS` to a value
1133c58f1c22SToby Isaac 
113420f4b53cSBarry Smith   Not Collective
11355b5e7992SMatthew G. Knepley 
1136c58f1c22SToby Isaac   Input Parameters:
113720f4b53cSBarry Smith + label - the `DMLabel`
11382fe279fdSBarry Smith . is    - the point `IS`
1139c58f1c22SToby Isaac - value - The point value
1140c58f1c22SToby Isaac 
1141c58f1c22SToby Isaac   Level: intermediate
1142c58f1c22SToby Isaac 
114320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1144c58f1c22SToby Isaac @*/
1145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1146d71ae5a4SJacob Faibussowitsch {
11470c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1148c58f1c22SToby Isaac   const PetscInt *points;
1149c58f1c22SToby Isaac 
1150c58f1c22SToby Isaac   PetscFunctionBegin;
1151d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1152c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11530c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11543ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11559f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11569566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11570c3c4a36SLisandro Dalcin   /* Set keys */
11589566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11599566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11609566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11619566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11629566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
11633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1164c58f1c22SToby Isaac }
1165c58f1c22SToby Isaac 
116684f0b6dfSMatthew G. Knepley /*@
116720f4b53cSBarry Smith   DMLabelGetNumValues - Get the number of values that the `DMLabel` takes
116884f0b6dfSMatthew G. Knepley 
116920f4b53cSBarry Smith   Not Collective
11705b5e7992SMatthew G. Knepley 
117184f0b6dfSMatthew G. Knepley   Input Parameter:
117220f4b53cSBarry Smith . label - the `DMLabel`
117384f0b6dfSMatthew G. Knepley 
117401d2d390SJose E. Roman   Output Parameter:
117584f0b6dfSMatthew G. Knepley . numValues - the number of values
117684f0b6dfSMatthew G. Knepley 
117784f0b6dfSMatthew G. Knepley   Level: intermediate
117884f0b6dfSMatthew G. Knepley 
117920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
118084f0b6dfSMatthew G. Knepley @*/
1181d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1182d71ae5a4SJacob Faibussowitsch {
1183c58f1c22SToby Isaac   PetscFunctionBegin;
1184d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11854f572ea9SToby Isaac   PetscAssertPointer(numValues, 2);
1186c58f1c22SToby Isaac   *numValues = label->numStrata;
11873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1188c58f1c22SToby Isaac }
1189c58f1c22SToby Isaac 
119084f0b6dfSMatthew G. Knepley /*@
119120f4b53cSBarry Smith   DMLabelGetValueIS - Get an `IS` of all values that the `DMlabel` takes
119284f0b6dfSMatthew G. Knepley 
119320f4b53cSBarry Smith   Not Collective
11945b5e7992SMatthew G. Knepley 
119584f0b6dfSMatthew G. Knepley   Input Parameter:
119620f4b53cSBarry Smith . label - the `DMLabel`
119784f0b6dfSMatthew G. Knepley 
119801d2d390SJose E. Roman   Output Parameter:
119960225df5SJacob Faibussowitsch . values - the value `IS`
120084f0b6dfSMatthew G. Knepley 
120184f0b6dfSMatthew G. Knepley   Level: intermediate
120284f0b6dfSMatthew G. Knepley 
12031d04cbbeSVaclav Hapla   Notes:
120420f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
120520f4b53cSBarry Smith   Strata which are allocated but empty [`DMLabelGetStratumSize()` yields 0] are counted.
120620f4b53cSBarry Smith   If you need to count only nonempty strata, use `DMLabelGetNonEmptyStratumValuesIS()`.
12071d04cbbeSVaclav Hapla 
120820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
120984f0b6dfSMatthew G. Knepley @*/
1210d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1211d71ae5a4SJacob Faibussowitsch {
1212c58f1c22SToby Isaac   PetscFunctionBegin;
1213d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12144f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12159566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1217c58f1c22SToby Isaac }
1218c58f1c22SToby Isaac 
121984f0b6dfSMatthew G. Knepley /*@
12208696263dSMatthew G. Knepley   DMLabelGetValueBounds - Return the smallest and largest value in the label
12218696263dSMatthew G. Knepley 
12228696263dSMatthew G. Knepley   Not Collective
12238696263dSMatthew G. Knepley 
12248696263dSMatthew G. Knepley   Input Parameter:
12258696263dSMatthew G. Knepley . label - the `DMLabel`
12268696263dSMatthew G. Knepley 
12278696263dSMatthew G. Knepley   Output Parameters:
12288696263dSMatthew G. Knepley + minValue - The smallest value
12298696263dSMatthew G. Knepley - maxValue - The largest value
12308696263dSMatthew G. Knepley 
12318696263dSMatthew G. Knepley   Level: intermediate
12328696263dSMatthew G. Knepley 
12338696263dSMatthew G. Knepley .seealso: `DMLabel`, `DM`, `DMLabelGetBounds()`, `DMLabelGetValue()`, `DMLabelSetValue()`
12348696263dSMatthew G. Knepley @*/
12358696263dSMatthew G. Knepley PetscErrorCode DMLabelGetValueBounds(DMLabel label, PetscInt *minValue, PetscInt *maxValue)
12368696263dSMatthew G. Knepley {
12371690c2aeSBarry Smith   PetscInt min = PETSC_INT_MAX, max = PETSC_INT_MIN;
12388696263dSMatthew G. Knepley 
12398696263dSMatthew G. Knepley   PetscFunctionBegin;
12408696263dSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12418696263dSMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
12428696263dSMatthew G. Knepley     min = PetscMin(min, label->stratumValues[v]);
12438696263dSMatthew G. Knepley     max = PetscMax(max, label->stratumValues[v]);
12448696263dSMatthew G. Knepley   }
12458696263dSMatthew G. Knepley   if (minValue) {
12468696263dSMatthew G. Knepley     PetscAssertPointer(minValue, 2);
12478696263dSMatthew G. Knepley     *minValue = min;
12488696263dSMatthew G. Knepley   }
12498696263dSMatthew G. Knepley   if (maxValue) {
12508696263dSMatthew G. Knepley     PetscAssertPointer(maxValue, 3);
12518696263dSMatthew G. Knepley     *maxValue = max;
12528696263dSMatthew G. Knepley   }
12538696263dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
12548696263dSMatthew G. Knepley }
12558696263dSMatthew G. Knepley 
12568696263dSMatthew G. Knepley /*@
125720f4b53cSBarry Smith   DMLabelGetNonEmptyStratumValuesIS - Get an `IS` of all values that the `DMlabel` takes
12581d04cbbeSVaclav Hapla 
125920f4b53cSBarry Smith   Not Collective
12601d04cbbeSVaclav Hapla 
12611d04cbbeSVaclav Hapla   Input Parameter:
126220f4b53cSBarry Smith . label - the `DMLabel`
12631d04cbbeSVaclav Hapla 
1264d5b43468SJose E. Roman   Output Parameter:
126560225df5SJacob Faibussowitsch . values - the value `IS`
12661d04cbbeSVaclav Hapla 
12671d04cbbeSVaclav Hapla   Level: intermediate
12681d04cbbeSVaclav Hapla 
12691d04cbbeSVaclav Hapla   Notes:
127020f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
127120f4b53cSBarry Smith   This is similar to `DMLabelGetValueIS()` but counts only nonempty strata.
12721d04cbbeSVaclav Hapla 
127320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
12741d04cbbeSVaclav Hapla @*/
1275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1276d71ae5a4SJacob Faibussowitsch {
12771d04cbbeSVaclav Hapla   PetscInt  i, j;
12781d04cbbeSVaclav Hapla   PetscInt *valuesArr;
12791d04cbbeSVaclav Hapla 
12801d04cbbeSVaclav Hapla   PetscFunctionBegin;
12811d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12824f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
12841d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
12851d04cbbeSVaclav Hapla     PetscInt n;
12861d04cbbeSVaclav Hapla 
12879566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
12881d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
12891d04cbbeSVaclav Hapla   }
12901d04cbbeSVaclav Hapla   if (j == label->numStrata) {
12919566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12921d04cbbeSVaclav Hapla   } else {
12939566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
12941d04cbbeSVaclav Hapla   }
12959566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
12963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12971d04cbbeSVaclav Hapla }
12981d04cbbeSVaclav Hapla 
12991d04cbbeSVaclav Hapla /*@
130020f4b53cSBarry Smith   DMLabelGetValueIndex - Get the index of a given value in the list of values for the `DMlabel`, or -1 if it is not present
1301d123abd9SMatthew G. Knepley 
130220f4b53cSBarry Smith   Not Collective
1303d123abd9SMatthew G. Knepley 
1304d123abd9SMatthew G. Knepley   Input Parameters:
130520f4b53cSBarry Smith + label - the `DMLabel`
130697bb3fdcSJose E. Roman - value - the value
1307d123abd9SMatthew G. Knepley 
130801d2d390SJose E. Roman   Output Parameter:
1309d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1310d123abd9SMatthew G. Knepley 
1311d123abd9SMatthew G. Knepley   Level: intermediate
1312d123abd9SMatthew G. Knepley 
131320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1314d123abd9SMatthew G. Knepley @*/
1315d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1316d71ae5a4SJacob Faibussowitsch {
1317d123abd9SMatthew G. Knepley   PetscInt v;
1318d123abd9SMatthew G. Knepley 
1319d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1320d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13214f572ea9SToby Isaac   PetscAssertPointer(index, 3);
1322d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
13239371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
13249371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1325d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1326d123abd9SMatthew G. Knepley   else *index = v;
13273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1328d123abd9SMatthew G. Knepley }
1329d123abd9SMatthew G. Knepley 
1330d123abd9SMatthew G. Knepley /*@
133184f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
133284f0b6dfSMatthew G. Knepley 
133320f4b53cSBarry Smith   Not Collective
13345b5e7992SMatthew G. Knepley 
133584f0b6dfSMatthew G. Knepley   Input Parameters:
133620f4b53cSBarry Smith + label - the `DMLabel`
133784f0b6dfSMatthew G. Knepley - value - the stratum value
133884f0b6dfSMatthew G. Knepley 
133901d2d390SJose E. Roman   Output Parameter:
134084f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
134184f0b6dfSMatthew G. Knepley 
134284f0b6dfSMatthew G. Knepley   Level: intermediate
134384f0b6dfSMatthew G. Knepley 
134420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
134584f0b6dfSMatthew G. Knepley @*/
1346d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1347d71ae5a4SJacob Faibussowitsch {
1348fada774cSMatthew G. Knepley   PetscInt v;
1349fada774cSMatthew G. Knepley 
1350fada774cSMatthew G. Knepley   PetscFunctionBegin;
1351d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13524f572ea9SToby Isaac   PetscAssertPointer(exists, 3);
13539566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13540c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
13553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1356fada774cSMatthew G. Knepley }
1357fada774cSMatthew G. Knepley 
135884f0b6dfSMatthew G. Knepley /*@
135984f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
136084f0b6dfSMatthew G. Knepley 
136120f4b53cSBarry Smith   Not Collective
13625b5e7992SMatthew G. Knepley 
136384f0b6dfSMatthew G. Knepley   Input Parameters:
136420f4b53cSBarry Smith + label - the `DMLabel`
136584f0b6dfSMatthew G. Knepley - value - the stratum value
136684f0b6dfSMatthew G. Knepley 
136701d2d390SJose E. Roman   Output Parameter:
136884f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
136984f0b6dfSMatthew G. Knepley 
137084f0b6dfSMatthew G. Knepley   Level: intermediate
137184f0b6dfSMatthew G. Knepley 
137220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
137384f0b6dfSMatthew G. Knepley @*/
1374d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1375d71ae5a4SJacob Faibussowitsch {
1376c58f1c22SToby Isaac   PetscInt v;
1377c58f1c22SToby Isaac 
1378c58f1c22SToby Isaac   PetscFunctionBegin;
1379d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13804f572ea9SToby Isaac   PetscAssertPointer(size, 3);
13819566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13829566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
13833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1384c58f1c22SToby Isaac }
1385c58f1c22SToby Isaac 
138684f0b6dfSMatthew G. Knepley /*@
138784f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
138884f0b6dfSMatthew G. Knepley 
138920f4b53cSBarry Smith   Not Collective
13905b5e7992SMatthew G. Knepley 
139184f0b6dfSMatthew G. Knepley   Input Parameters:
139220f4b53cSBarry Smith + label - the `DMLabel`
139384f0b6dfSMatthew G. Knepley - value - the stratum value
139484f0b6dfSMatthew G. Knepley 
139501d2d390SJose E. Roman   Output Parameters:
139684f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
139784f0b6dfSMatthew G. Knepley - end   - the largest point in the stratum
139884f0b6dfSMatthew G. Knepley 
139984f0b6dfSMatthew G. Knepley   Level: intermediate
140084f0b6dfSMatthew G. Knepley 
140120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
140284f0b6dfSMatthew G. Knepley @*/
1403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1404d71ae5a4SJacob Faibussowitsch {
14059f6c5813SMatthew G. Knepley   IS       is;
14060c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1407c58f1c22SToby Isaac 
1408c58f1c22SToby Isaac   PetscFunctionBegin;
1409d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14109371c9d4SSatish Balay   if (start) {
14114f572ea9SToby Isaac     PetscAssertPointer(start, 3);
14129371c9d4SSatish Balay     *start = -1;
14139371c9d4SSatish Balay   }
14149371c9d4SSatish Balay   if (end) {
14154f572ea9SToby Isaac     PetscAssertPointer(end, 4);
14169371c9d4SSatish Balay     *end = -1;
14179371c9d4SSatish Balay   }
14189566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14193ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14209566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14213ba16761SJacob Faibussowitsch   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
14229f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &is);
14239f6c5813SMatthew G. Knepley   PetscCall(ISGetMinMax(is, &min, &max));
14249f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&is));
1425d6cb179aSToby Isaac   if (start) *start = min;
1426d6cb179aSToby Isaac   if (end) *end = max + 1;
14273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1428c58f1c22SToby Isaac }
1429c58f1c22SToby Isaac 
143066976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
14319f6c5813SMatthew G. Knepley {
14329f6c5813SMatthew G. Knepley   PetscFunctionBegin;
14339f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
14349f6c5813SMatthew G. Knepley   *pointIS = label->points[v];
14353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14369f6c5813SMatthew G. Knepley }
14379f6c5813SMatthew G. Knepley 
143884f0b6dfSMatthew G. Knepley /*@
143920f4b53cSBarry Smith   DMLabelGetStratumIS - Get an `IS` with the stratum points
144084f0b6dfSMatthew G. Knepley 
144120f4b53cSBarry Smith   Not Collective
14425b5e7992SMatthew G. Knepley 
144384f0b6dfSMatthew G. Knepley   Input Parameters:
144420f4b53cSBarry Smith + label - the `DMLabel`
144584f0b6dfSMatthew G. Knepley - value - the stratum value
144684f0b6dfSMatthew G. Knepley 
144701d2d390SJose E. Roman   Output Parameter:
144884f0b6dfSMatthew G. Knepley . points - The stratum points
144984f0b6dfSMatthew G. Knepley 
145084f0b6dfSMatthew G. Knepley   Level: intermediate
145184f0b6dfSMatthew G. Knepley 
1452593ce467SVaclav Hapla   Notes:
145320f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
145420f4b53cSBarry Smith   Returns `NULL` if the stratum is empty.
1455593ce467SVaclav Hapla 
145620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
145784f0b6dfSMatthew G. Knepley @*/
1458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1459d71ae5a4SJacob Faibussowitsch {
1460c58f1c22SToby Isaac   PetscInt v;
1461c58f1c22SToby Isaac 
1462c58f1c22SToby Isaac   PetscFunctionBegin;
1463d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14644f572ea9SToby Isaac   PetscAssertPointer(points, 3);
1465c58f1c22SToby Isaac   *points = NULL;
14669566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14673ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14689566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14699f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, points);
14703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1471c58f1c22SToby Isaac }
1472c58f1c22SToby Isaac 
147384f0b6dfSMatthew G. Knepley /*@
147420f4b53cSBarry Smith   DMLabelSetStratumIS - Set the stratum points using an `IS`
147584f0b6dfSMatthew G. Knepley 
147620f4b53cSBarry Smith   Not Collective
14775b5e7992SMatthew G. Knepley 
147884f0b6dfSMatthew G. Knepley   Input Parameters:
147920f4b53cSBarry Smith + label - the `DMLabel`
148084f0b6dfSMatthew G. Knepley . value - the stratum value
148160225df5SJacob Faibussowitsch - is    - The stratum points
148284f0b6dfSMatthew G. Knepley 
148384f0b6dfSMatthew G. Knepley   Level: intermediate
148484f0b6dfSMatthew G. Knepley 
148520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
148684f0b6dfSMatthew G. Knepley @*/
1487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1488d71ae5a4SJacob Faibussowitsch {
14890c3c4a36SLisandro Dalcin   PetscInt v;
14904de306b1SToby Isaac 
14914de306b1SToby Isaac   PetscFunctionBegin;
1492d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1493d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
14949f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
14959566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
14963ba16761SJacob Faibussowitsch   if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
14979566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
1498f4f49eeaSPierre Jolivet   PetscCall(ISGetLocalSize(is, &label->stratumSizes[v]));
14999566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
1500f4f49eeaSPierre Jolivet   PetscCall(ISDestroy(&label->points[v]));
15010c3c4a36SLisandro Dalcin   label->points[v]  = is;
15020c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
15039566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
15044de306b1SToby Isaac   if (label->bt) {
15054de306b1SToby Isaac     const PetscInt *points;
15064de306b1SToby Isaac     PetscInt        p;
15074de306b1SToby Isaac 
15089566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
15094de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
15104de306b1SToby Isaac       const PetscInt point = points[p];
15114de306b1SToby Isaac 
151263a3b9bcSJacob 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);
15139566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
15144de306b1SToby Isaac     }
15154de306b1SToby Isaac   }
15163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15174de306b1SToby Isaac }
15184de306b1SToby Isaac 
151984f0b6dfSMatthew G. Knepley /*@
152084f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
15214de306b1SToby Isaac 
152220f4b53cSBarry Smith   Not Collective
15235b5e7992SMatthew G. Knepley 
152484f0b6dfSMatthew G. Knepley   Input Parameters:
152520f4b53cSBarry Smith + label - the `DMLabel`
152684f0b6dfSMatthew G. Knepley - value - the stratum value
152784f0b6dfSMatthew G. Knepley 
152884f0b6dfSMatthew G. Knepley   Level: intermediate
152984f0b6dfSMatthew G. Knepley 
153020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
153184f0b6dfSMatthew G. Knepley @*/
1532d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1533d71ae5a4SJacob Faibussowitsch {
1534c58f1c22SToby Isaac   PetscInt v;
1535c58f1c22SToby Isaac 
1536c58f1c22SToby Isaac   PetscFunctionBegin;
1537d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15389f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15399566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15403ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15414de306b1SToby Isaac   if (label->validIS[v]) {
15424de306b1SToby Isaac     if (label->bt) {
1543c58f1c22SToby Isaac       PetscInt        i;
1544ad8374ffSToby Isaac       const PetscInt *points;
1545c58f1c22SToby Isaac 
15469566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1547c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1548ad8374ffSToby Isaac         const PetscInt point = points[i];
1549c58f1c22SToby Isaac 
155063a3b9bcSJacob 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);
15519566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1552c58f1c22SToby Isaac       }
15539566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1554c58f1c22SToby Isaac     }
1555c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
15569566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
15579566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
15589566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
15599566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1560c58f1c22SToby Isaac   } else {
15619566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1562c58f1c22SToby Isaac   }
15633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1564c58f1c22SToby Isaac }
1565c58f1c22SToby Isaac 
156684f0b6dfSMatthew G. Knepley /*@
1567412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1568412e9a14SMatthew G. Knepley 
156920f4b53cSBarry Smith   Not Collective
1570412e9a14SMatthew G. Knepley 
1571412e9a14SMatthew G. Knepley   Input Parameters:
157220f4b53cSBarry Smith + label  - The `DMLabel`
1573412e9a14SMatthew G. Knepley . value  - The label value for all points
1574412e9a14SMatthew G. Knepley . pStart - The first point
1575412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1576412e9a14SMatthew G. Knepley 
1577412e9a14SMatthew G. Knepley   Level: intermediate
1578412e9a14SMatthew G. Knepley 
157920f4b53cSBarry Smith   Note:
158020f4b53cSBarry Smith   The marks points are [`pStart`, `pEnd`), and only the bounds are stored.
158120f4b53cSBarry Smith 
158220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1583412e9a14SMatthew G. Knepley @*/
1584d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1585d71ae5a4SJacob Faibussowitsch {
1586412e9a14SMatthew G. Knepley   IS pIS;
1587412e9a14SMatthew G. Knepley 
1588412e9a14SMatthew G. Knepley   PetscFunctionBegin;
15899566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
15909566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
15919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
15923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1593412e9a14SMatthew G. Knepley }
1594412e9a14SMatthew G. Knepley 
1595412e9a14SMatthew G. Knepley /*@
1596d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1597d123abd9SMatthew G. Knepley 
159820f4b53cSBarry Smith   Not Collective
1599d123abd9SMatthew G. Knepley 
1600d123abd9SMatthew G. Knepley   Input Parameters:
160120f4b53cSBarry Smith + label - The `DMLabel`
1602d123abd9SMatthew G. Knepley . value - The label value
1603d123abd9SMatthew G. Knepley - p     - A point with this value
1604d123abd9SMatthew G. Knepley 
1605d123abd9SMatthew G. Knepley   Output Parameter:
1606d123abd9SMatthew 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
1607d123abd9SMatthew G. Knepley 
1608d123abd9SMatthew G. Knepley   Level: intermediate
1609d123abd9SMatthew G. Knepley 
161020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1611d123abd9SMatthew G. Knepley @*/
1612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1613d71ae5a4SJacob Faibussowitsch {
16149f6c5813SMatthew G. Knepley   IS       pointIS;
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);
1625f622de60SMatthew G. Knepley   PetscCall(ISLocate(pointIS, p, index));
16269f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&pointIS));
16273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1628d123abd9SMatthew G. Knepley }
1629d123abd9SMatthew G. Knepley 
1630d123abd9SMatthew G. Knepley /*@
163120f4b53cSBarry Smith   DMLabelFilter - Remove all points outside of [`start`, `end`)
163284f0b6dfSMatthew G. Knepley 
163320f4b53cSBarry Smith   Not Collective
16345b5e7992SMatthew G. Knepley 
163584f0b6dfSMatthew G. Knepley   Input Parameters:
163620f4b53cSBarry Smith + label - the `DMLabel`
163722cd2cdaSVaclav Hapla . start - the first point kept
163822cd2cdaSVaclav Hapla - end   - one more than the last point kept
163984f0b6dfSMatthew G. Knepley 
164084f0b6dfSMatthew G. Knepley   Level: intermediate
164184f0b6dfSMatthew G. Knepley 
164220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
164384f0b6dfSMatthew G. Knepley @*/
1644d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1645d71ae5a4SJacob Faibussowitsch {
1646c58f1c22SToby Isaac   PetscInt v;
1647c58f1c22SToby Isaac 
1648c58f1c22SToby Isaac   PetscFunctionBegin;
1649d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16509f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16519566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
16529566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16539f6c5813SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
16549f6c5813SMatthew G. Knepley     PetscCall(ISGeneralFilter(label->points[v], start, end));
16559f6c5813SMatthew G. Knepley     PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
16569f6c5813SMatthew G. Knepley   }
16579566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
16583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1659c58f1c22SToby Isaac }
1660c58f1c22SToby Isaac 
166184f0b6dfSMatthew G. Knepley /*@
166284f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
166384f0b6dfSMatthew G. Knepley 
166420f4b53cSBarry Smith   Not Collective
16655b5e7992SMatthew G. Knepley 
166684f0b6dfSMatthew G. Knepley   Input Parameters:
166720f4b53cSBarry Smith + label       - the `DMLabel`
166884f0b6dfSMatthew G. Knepley - permutation - the point permutation
166984f0b6dfSMatthew G. Knepley 
167084f0b6dfSMatthew G. Knepley   Output Parameter:
167160225df5SJacob Faibussowitsch . labelNew - the new label containing the permuted points
167284f0b6dfSMatthew G. Knepley 
167384f0b6dfSMatthew G. Knepley   Level: intermediate
167484f0b6dfSMatthew G. Knepley 
167520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
167684f0b6dfSMatthew G. Knepley @*/
1677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1678d71ae5a4SJacob Faibussowitsch {
1679c58f1c22SToby Isaac   const PetscInt *perm;
1680c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1681c58f1c22SToby Isaac 
1682c58f1c22SToby Isaac   PetscFunctionBegin;
1683d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1684d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
16859f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16869566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16879566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
16889566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
16899566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
16909566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1691c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1692c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1693ad8374ffSToby Isaac     const PetscInt *points;
1694ad8374ffSToby Isaac     PetscInt       *pointsNew;
1695c58f1c22SToby Isaac 
16969566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
16979f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(size, &pointsNew));
1698c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1699ad8374ffSToby Isaac       const PetscInt point = points[q];
1700c58f1c22SToby Isaac 
170163a3b9bcSJacob 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);
1702ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1703c58f1c22SToby Isaac     }
17049566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
17059566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
170657508eceSPierre Jolivet     PetscCall(ISDestroy(&(*labelNew)->points[v]));
1707fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
17089566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
17099566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1710fa8e8ae5SToby Isaac     } else {
17119566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1712fa8e8ae5SToby Isaac     }
17139566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1714c58f1c22SToby Isaac   }
17159566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1716c58f1c22SToby Isaac   if (label->bt) {
17179566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
17189566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1719c58f1c22SToby Isaac   }
17203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1721c58f1c22SToby Isaac }
1722c58f1c22SToby Isaac 
17235552b385SBrandon /*@
17245552b385SBrandon   DMLabelPermuteValues - Permute the values in a label
17255552b385SBrandon 
17265552b385SBrandon   Not collective
17275552b385SBrandon 
17285552b385SBrandon   Input Parameters:
17295552b385SBrandon + label       - the `DMLabel`
17305552b385SBrandon - permutation - the value permutation, permutation[old value] = new value
17315552b385SBrandon 
17325552b385SBrandon   Output Parameter:
17335552b385SBrandon . label - the `DMLabel` now with permuted values
17345552b385SBrandon 
17355552b385SBrandon   Note:
17365552b385SBrandon   The modification is done in-place
17375552b385SBrandon 
17385552b385SBrandon   Level: intermediate
17395552b385SBrandon 
17405552b385SBrandon .seealso: `DMLabelRewriteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
17415552b385SBrandon @*/
17425552b385SBrandon PetscErrorCode DMLabelPermuteValues(DMLabel label, IS permutation)
17435552b385SBrandon {
17445552b385SBrandon   PetscInt Nv, Np;
17455552b385SBrandon 
17465552b385SBrandon   PetscFunctionBegin;
17475552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17485552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
17495552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
17505552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
17515552b385SBrandon   PetscCheck(Np == Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " != %" PetscInt_FMT " number of label values", Np, Nv);
17525552b385SBrandon   if (PetscDefined(USE_DEBUG)) {
17535552b385SBrandon     PetscBool flg;
17545552b385SBrandon     PetscCall(ISGetInfo(permutation, IS_PERMUTATION, IS_LOCAL, PETSC_TRUE, &flg));
17555552b385SBrandon     PetscCheck(flg, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "IS is not a permutation");
17565552b385SBrandon   }
17575552b385SBrandon   PetscCall(DMLabelRewriteValues(label, permutation));
17585552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
17595552b385SBrandon }
17605552b385SBrandon 
17615552b385SBrandon /*@
17625552b385SBrandon   DMLabelRewriteValues - Permute the values in a label, but some may be omitted
17635552b385SBrandon 
17645552b385SBrandon   Not collective
17655552b385SBrandon 
17665552b385SBrandon   Input Parameters:
17675552b385SBrandon + label       - the `DMLabel`
17685552b385SBrandon - permutation - the value permutation, permutation[old value] = new value, but some maybe omitted
17695552b385SBrandon 
17705552b385SBrandon   Output Parameter:
17715552b385SBrandon . label - the `DMLabel` now with permuted values
17725552b385SBrandon 
17735552b385SBrandon   Note:
17745552b385SBrandon   The modification is done in-place
17755552b385SBrandon 
17765552b385SBrandon   Level: intermediate
17775552b385SBrandon 
17785552b385SBrandon .seealso: `DMLabelPermuteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
17795552b385SBrandon @*/
17805552b385SBrandon PetscErrorCode DMLabelRewriteValues(DMLabel label, IS permutation)
17815552b385SBrandon {
17825552b385SBrandon   const PetscInt *perm;
17835552b385SBrandon   PetscInt        Nv, Np;
17845552b385SBrandon 
17855552b385SBrandon   PetscFunctionBegin;
17865552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17875552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
17885552b385SBrandon   PetscCall(DMLabelMakeAllValid_Private(label));
17895552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
17905552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
17915552b385SBrandon   PetscCheck(Np >= Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " < %" PetscInt_FMT " number of label values", Np, Nv);
17925552b385SBrandon   PetscCall(ISGetIndices(permutation, &perm));
17935552b385SBrandon   for (PetscInt v = 0; v < Nv; ++v) label->stratumValues[v] = perm[label->stratumValues[v]];
17945552b385SBrandon   PetscCall(ISRestoreIndices(permutation, &perm));
17955552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
17965552b385SBrandon }
17975552b385SBrandon 
179866976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1799d71ae5a4SJacob Faibussowitsch {
180026c55118SMichael Lange   MPI_Comm     comm;
1801eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
180226c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
180326c55118SMichael Lange   PetscSection rootSection;
180426c55118SMichael Lange   PetscSF      labelSF;
180526c55118SMichael Lange 
180626c55118SMichael Lange   PetscFunctionBegin;
18079566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
18089566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
180926c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
181026c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
18119566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
18129566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
18139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
181426c55118SMichael Lange   if (label) {
181526c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1816ad8374ffSToby Isaac       const PetscInt *points;
1817ad8374ffSToby Isaac 
18189566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
181948a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
18209566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
182126c55118SMichael Lange     }
182226c55118SMichael Lange   }
18239566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
182426c55118SMichael Lange   /* Create a point-wise array of stratum values */
18259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
18269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
18279566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
182826c55118SMichael Lange   if (label) {
182926c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1830ad8374ffSToby Isaac       const PetscInt *points;
1831ad8374ffSToby Isaac 
18329566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
183326c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1834ad8374ffSToby Isaac         const PetscInt p = points[l];
18359566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
183626c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
183726c55118SMichael Lange       }
18389566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
183926c55118SMichael Lange     }
184026c55118SMichael Lange   }
184126c55118SMichael Lange   /* Build SF that maps label points to remote processes */
18429566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
18439566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
18449566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
18459566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
184626c55118SMichael Lange   /* Send the strata for each point over the derived SF */
18479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
18489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
18499566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
18509566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
185126c55118SMichael Lange   /* Clean up */
18529566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18539566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
18549566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18559566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
18563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185726c55118SMichael Lange }
185826c55118SMichael Lange 
185984f0b6dfSMatthew G. Knepley /*@
186020f4b53cSBarry Smith   DMLabelDistribute - Create a new label pushed forward over the `PetscSF`
186184f0b6dfSMatthew G. Knepley 
186220f4b53cSBarry Smith   Collective
18635b5e7992SMatthew G. Knepley 
186484f0b6dfSMatthew G. Knepley   Input Parameters:
186520f4b53cSBarry Smith + label - the `DMLabel`
186684f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
186784f0b6dfSMatthew G. Knepley 
186884f0b6dfSMatthew G. Knepley   Output Parameter:
186960225df5SJacob Faibussowitsch . labelNew - the new redistributed label
187084f0b6dfSMatthew G. Knepley 
187184f0b6dfSMatthew G. Knepley   Level: intermediate
187284f0b6dfSMatthew G. Knepley 
187320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
187484f0b6dfSMatthew G. Knepley @*/
1875d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1876d71ae5a4SJacob Faibussowitsch {
1877c58f1c22SToby Isaac   MPI_Comm     comm;
187826c55118SMichael Lange   PetscSection leafSection;
187926c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
188026c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1881ad8374ffSToby Isaac   PetscInt   **points;
1882d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1883c58f1c22SToby Isaac   char        *name;
1884835f2295SStefano Zampini   PetscMPIInt  nameSize;
1885e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1886c58f1c22SToby Isaac   size_t       len = 0;
188726c55118SMichael Lange   PetscMPIInt  rank;
1888c58f1c22SToby Isaac 
1889c58f1c22SToby Isaac   PetscFunctionBegin;
1890d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1891f018e600SMatthew G. Knepley   if (label) {
1892f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
18939f6c5813SMatthew G. Knepley     PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
18949566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1895f018e600SMatthew G. Knepley   }
18969566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
18979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1898c58f1c22SToby Isaac   /* Bcast name */
1899dd400576SPatrick Sanan   if (rank == 0) {
19009566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
19019566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1902d67d17b1SMatthew G. Knepley   }
1903835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
1904835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
19059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
19069566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
1907835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
19089566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
19099566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
191077d236dfSMichael Lange   /* Bcast defaultValue */
1911dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
19129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
191326c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
19149566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
19155cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
19169566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
19179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
19189566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
19199566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
19209566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1921ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
19229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
19235cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
19245cbdf6fcSMichael Lange   offset = 0;
19259566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
19269566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
192748a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
19285cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1929231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
19309371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
19319371c9d4SSatish Balay         leafStrata[p] = s;
19329371c9d4SSatish Balay         break;
19339371c9d4SSatish Balay       }
19345cbdf6fcSMichael Lange     }
19355cbdf6fcSMichael Lange   }
1936c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
19379566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
19389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1939c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19409566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19419566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1942ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1943c58f1c22SToby Isaac   }
19449566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
19459f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
19469f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1947c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
19489566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
1949f4f49eeaSPierre Jolivet     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &points[s]));
1950c58f1c22SToby Isaac   }
1951c58f1c22SToby Isaac   /* Insert points into new strata */
19529566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
19539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1954c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1957c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1958c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1959ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1960c58f1c22SToby Isaac     }
1961c58f1c22SToby Isaac   }
1962ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1963f4f49eeaSPierre Jolivet     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &points[s][0], PETSC_OWN_POINTER, &((*labelNew)->points[s])));
19649566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1965ad8374ffSToby Isaac   }
19669566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
19679566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
19689566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
19699566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
19709566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
19713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1972c58f1c22SToby Isaac }
1973c58f1c22SToby Isaac 
19747937d9ceSMichael Lange /*@
19757937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
19767937d9ceSMichael Lange 
197720f4b53cSBarry Smith   Collective
19785b5e7992SMatthew G. Knepley 
19797937d9ceSMichael Lange   Input Parameters:
198020f4b53cSBarry Smith + label - the `DMLabel`
198120f4b53cSBarry Smith - sf    - the `PetscSF` communication map
19827937d9ceSMichael Lange 
19832fe279fdSBarry Smith   Output Parameter:
198420f4b53cSBarry Smith . labelNew - the new `DMLabel` with localised leaf values
19857937d9ceSMichael Lange 
19867937d9ceSMichael Lange   Level: developer
19877937d9ceSMichael Lange 
198820f4b53cSBarry Smith   Note:
198920f4b53cSBarry Smith   This is the inverse operation to `DMLabelDistribute()`.
19907937d9ceSMichael Lange 
199120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
19927937d9ceSMichael Lange @*/
1993d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
1994d71ae5a4SJacob Faibussowitsch {
19957937d9ceSMichael Lange   MPI_Comm        comm;
19967937d9ceSMichael Lange   PetscSection    rootSection;
19977937d9ceSMichael Lange   PetscSF         sfLabel;
19987937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
19997937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
20007937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
20017937d9ceSMichael Lange   PetscInt       *rootStrata;
2002d67d17b1SMatthew G. Knepley   const char     *lname;
20037937d9ceSMichael Lange   char           *name;
2004835f2295SStefano Zampini   PetscMPIInt     nameSize;
20057937d9ceSMichael Lange   size_t          len = 0;
20069852e123SBarry Smith   PetscMPIInt     rank, size;
20077937d9ceSMichael Lange 
20087937d9ceSMichael Lange   PetscFunctionBegin;
2009d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2010d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
20119f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
20129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
20139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
20149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
20157937d9ceSMichael Lange   /* Bcast name */
2016dd400576SPatrick Sanan   if (rank == 0) {
20179566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
20189566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
2019d67d17b1SMatthew G. Knepley   }
2020835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
2021835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
20229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
20239566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
2024835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
20259566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
20269566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
20277937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
20287937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
20297937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
20309566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
20319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
2032dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
20337937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
20348212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
20358212dd46SStefano Zampini 
20368212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
20378212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
20387937d9ceSMichael Lange   }
20399566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
20409566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
20417937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
20429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
20436497c311SBarry Smith   PetscCall(PetscSFGatherBegin(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20446497c311SBarry Smith   PetscCall(PetscSFGatherEnd(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20459566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
20469566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
20477937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
20489566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
20497937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
20507937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
20517937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
20529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
20539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
20549566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
20557937d9ceSMichael Lange     }
20567937d9ceSMichael Lange     idx += rootDegree[p];
20577937d9ceSMichael Lange   }
20589566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
20599566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
20609566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
20619566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
20623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20637937d9ceSMichael Lange }
20647937d9ceSMichael Lange 
2065d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
2066d71ae5a4SJacob Faibussowitsch {
2067d42890abSMatthew G. Knepley   const PetscInt *degree;
2068d42890abSMatthew G. Knepley   const PetscInt *points;
2069d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2070d42890abSMatthew G. Knepley 
2071d42890abSMatthew G. Knepley   PetscFunctionBegin;
2072d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2073d42890abSMatthew G. Knepley   /* Add in leaves */
2074d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2075d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2076d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
2077d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
2078d42890abSMatthew G. Knepley   }
2079d42890abSMatthew G. Knepley   /* Add in shared roots */
2080d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2081d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2082d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2083d42890abSMatthew G. Knepley     if (degree[r]) {
2084d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
2085d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
2086d42890abSMatthew G. Knepley     }
2087d42890abSMatthew G. Knepley   }
20883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2089d42890abSMatthew G. Knepley }
2090d42890abSMatthew G. Knepley 
2091d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2092d71ae5a4SJacob Faibussowitsch {
2093d42890abSMatthew G. Knepley   const PetscInt *degree;
2094d42890abSMatthew G. Knepley   const PetscInt *points;
2095d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2096d42890abSMatthew G. Knepley 
2097d42890abSMatthew G. Knepley   PetscFunctionBegin;
2098d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2099d42890abSMatthew G. Knepley   /* Read out leaves */
2100d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2101d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2102d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
2103d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
2104d42890abSMatthew G. Knepley 
2105d42890abSMatthew G. Knepley     if (cval != defVal) {
2106d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
2107d42890abSMatthew G. Knepley       if (val == defVal) {
2108d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
210948a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
2110d42890abSMatthew G. Knepley       }
2111d42890abSMatthew G. Knepley     }
2112d42890abSMatthew G. Knepley   }
2113d42890abSMatthew G. Knepley   /* Read out shared roots */
2114d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2115d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2116d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2117d42890abSMatthew G. Knepley     if (degree[r]) {
2118d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
2119d42890abSMatthew G. Knepley 
2120d42890abSMatthew G. Knepley       if (cval != defVal) {
2121d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
2122d42890abSMatthew G. Knepley         if (val == defVal) {
2123d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
212448a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2125d42890abSMatthew G. Knepley         }
2126d42890abSMatthew G. Knepley       }
2127d42890abSMatthew G. Knepley     }
2128d42890abSMatthew G. Knepley   }
21293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2130d42890abSMatthew G. Knepley }
2131d42890abSMatthew G. Knepley 
2132d42890abSMatthew G. Knepley /*@
2133d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
2134d42890abSMatthew G. Knepley 
213520f4b53cSBarry Smith   Collective
2136d42890abSMatthew G. Knepley 
2137d42890abSMatthew G. Knepley   Input Parameters:
213820f4b53cSBarry Smith + label - The `DMLabel` to propagate across processes
213920f4b53cSBarry Smith - sf    - The `PetscSF` describing parallel layout of the label points
2140d42890abSMatthew G. Knepley 
2141d42890abSMatthew G. Knepley   Level: intermediate
2142d42890abSMatthew G. Knepley 
214320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2144d42890abSMatthew G. Knepley @*/
2145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2146d71ae5a4SJacob Faibussowitsch {
2147d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
2148d42890abSMatthew G. Knepley   PetscMPIInt size;
2149d42890abSMatthew G. Knepley 
2150d42890abSMatthew G. Knepley   PetscFunctionBegin;
21519f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2152d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2153d42890abSMatthew G. Knepley   if (size > 1) {
2154d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
2155d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2156d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2157d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2158d42890abSMatthew G. Knepley   }
21593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2160d42890abSMatthew G. Knepley }
2161d42890abSMatthew G. Knepley 
2162d42890abSMatthew G. Knepley /*@
2163d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
2164d42890abSMatthew G. Knepley 
216520f4b53cSBarry Smith   Collective
2166d42890abSMatthew G. Knepley 
2167d42890abSMatthew G. Knepley   Input Parameters:
216820f4b53cSBarry Smith + label   - The `DMLabel` to propagate across processes
216960225df5SJacob Faibussowitsch - pointSF - The `PetscSF` describing parallel layout of the label points
2170d42890abSMatthew G. Knepley 
2171d42890abSMatthew G. Knepley   Level: intermediate
2172d42890abSMatthew G. Knepley 
217320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2174d42890abSMatthew G. Knepley @*/
2175d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2176d71ae5a4SJacob Faibussowitsch {
2177d42890abSMatthew G. Knepley   PetscFunctionBegin;
21789f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2179d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
2180d42890abSMatthew G. Knepley   label->propArray = NULL;
21813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2182d42890abSMatthew G. Knepley }
2183d42890abSMatthew G. Knepley 
2184d42890abSMatthew G. Knepley /*@C
2185d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2186d42890abSMatthew G. Knepley 
218720f4b53cSBarry Smith   Collective
2188d42890abSMatthew G. Knepley 
2189d42890abSMatthew G. Knepley   Input Parameters:
219020f4b53cSBarry Smith + label     - The `DMLabel` to propagate across processes
2191a4e35b19SJacob Faibussowitsch . pointSF   - The `PetscSF` describing parallel layout of the label points
219220f4b53cSBarry Smith . markPoint - An optional callback that is called when a point is marked, or `NULL`
219320f4b53cSBarry Smith - ctx       - An optional user context for the callback, or `NULL`
2194d42890abSMatthew G. Knepley 
219520f4b53cSBarry Smith   Calling sequence of `markPoint`:
219620f4b53cSBarry Smith + label - The `DMLabel`
2197d42890abSMatthew G. Knepley . p     - The point being marked
2198a4e35b19SJacob Faibussowitsch . val   - The label value for `p`
2199d42890abSMatthew G. Knepley - ctx   - An optional user context
2200d42890abSMatthew G. Knepley 
2201d42890abSMatthew G. Knepley   Level: intermediate
2202d42890abSMatthew G. Knepley 
220320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2204d42890abSMatthew G. Knepley @*/
2205a4e35b19SJacob Faibussowitsch PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel label, PetscInt p, PetscInt val, void *ctx), void *ctx)
2206d71ae5a4SJacob Faibussowitsch {
2207c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2208d42890abSMatthew G. Knepley   PetscMPIInt size;
2209d42890abSMatthew G. Knepley 
2210d42890abSMatthew G. Knepley   PetscFunctionBegin;
22119f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2212d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2213c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2214c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2215d42890abSMatthew G. Knepley     /* Communicate marked edges
2216d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2217d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2218d42890abSMatthew G. Knepley 
2219d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2220d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2221d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2222d42890abSMatthew G. Knepley 
2223d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2224d42890abSMatthew 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
2225d42890abSMatthew G. Knepley        edge to the queue.
2226d42890abSMatthew G. Knepley     */
2227d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2228d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2229d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2230d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2231d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2232d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2233d42890abSMatthew G. Knepley   }
22343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2235d42890abSMatthew G. Knepley }
2236d42890abSMatthew G. Knepley 
223784f0b6dfSMatthew G. Knepley /*@
223820f4b53cSBarry Smith   DMLabelConvertToSection - Make a `PetscSection`/`IS` pair that encodes the label
223984f0b6dfSMatthew G. Knepley 
224020f4b53cSBarry Smith   Not Collective
22415b5e7992SMatthew G. Knepley 
224284f0b6dfSMatthew G. Knepley   Input Parameter:
224320f4b53cSBarry Smith . label - the `DMLabel`
224484f0b6dfSMatthew G. Knepley 
224584f0b6dfSMatthew G. Knepley   Output Parameters:
224684f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
224720f4b53cSBarry Smith - is      - An `IS` containing all the label points
224884f0b6dfSMatthew G. Knepley 
224984f0b6dfSMatthew G. Knepley   Level: developer
225084f0b6dfSMatthew G. Knepley 
225120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
225284f0b6dfSMatthew G. Knepley @*/
2253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2254d71ae5a4SJacob Faibussowitsch {
2255c58f1c22SToby Isaac   IS              vIS;
2256c58f1c22SToby Isaac   const PetscInt *values;
2257c58f1c22SToby Isaac   PetscInt       *points;
2258c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2259c58f1c22SToby Isaac 
2260c58f1c22SToby Isaac   PetscFunctionBegin;
2261d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
22629566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
22639566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
22649566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
22659371c9d4SSatish Balay   if (nV) {
22669371c9d4SSatish Balay     vS = values[0];
22679371c9d4SSatish Balay     vE = values[0] + 1;
22689371c9d4SSatish Balay   }
2269c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2270c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2271c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2272c58f1c22SToby Isaac   }
22739566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
22749566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2275c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2276c58f1c22SToby Isaac     PetscInt n;
2277c58f1c22SToby Isaac 
22789566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
22799566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2280c58f1c22SToby Isaac   }
22819566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
22829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
22839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2284c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2285c58f1c22SToby Isaac     IS              is;
2286c58f1c22SToby Isaac     const PetscInt *spoints;
2287c58f1c22SToby Isaac     PetscInt        dof, off, p;
2288c58f1c22SToby Isaac 
22899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
22909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
22919566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
22929566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2293c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
22949566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
22959566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2296c58f1c22SToby Isaac   }
22979566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
22989566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
22999566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
23003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2301c58f1c22SToby Isaac }
2302c58f1c22SToby Isaac 
23039f6c5813SMatthew G. Knepley /*@C
23049f6c5813SMatthew G. Knepley   DMLabelRegister - Adds a new label component implementation
23059f6c5813SMatthew G. Knepley 
23069f6c5813SMatthew G. Knepley   Not Collective
23079f6c5813SMatthew G. Knepley 
23089f6c5813SMatthew G. Knepley   Input Parameters:
23099f6c5813SMatthew G. Knepley + name        - The name of a new user-defined creation routine
23109f6c5813SMatthew G. Knepley - create_func - The creation routine itself
23119f6c5813SMatthew G. Knepley 
23129f6c5813SMatthew G. Knepley   Notes:
23139f6c5813SMatthew G. Knepley   `DMLabelRegister()` may be called multiple times to add several user-defined labels
23149f6c5813SMatthew G. Knepley 
231560225df5SJacob Faibussowitsch   Example Usage:
23169f6c5813SMatthew G. Knepley .vb
23179f6c5813SMatthew G. Knepley   DMLabelRegister("my_label", MyLabelCreate);
23189f6c5813SMatthew G. Knepley .ve
23199f6c5813SMatthew G. Knepley 
23209f6c5813SMatthew G. Knepley   Then, your label type can be chosen with the procedural interface via
23219f6c5813SMatthew G. Knepley .vb
23229f6c5813SMatthew G. Knepley   DMLabelCreate(MPI_Comm, DMLabel *);
23239f6c5813SMatthew G. Knepley   DMLabelSetType(DMLabel, "my_label");
23249f6c5813SMatthew G. Knepley .ve
23259f6c5813SMatthew G. Knepley   or at runtime via the option
23269f6c5813SMatthew G. Knepley .vb
23279f6c5813SMatthew G. Knepley   -dm_label_type my_label
23289f6c5813SMatthew G. Knepley .ve
23299f6c5813SMatthew G. Knepley 
23309f6c5813SMatthew G. Knepley   Level: advanced
23319f6c5813SMatthew G. Knepley 
233260225df5SJacob Faibussowitsch .seealso: `DMLabel`, `DM`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
23339f6c5813SMatthew G. Knepley @*/
23349f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
23359f6c5813SMatthew G. Knepley {
23369f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23379f6c5813SMatthew G. Knepley   PetscCall(DMInitializePackage());
23389f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
23393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23409f6c5813SMatthew G. Knepley }
23419f6c5813SMatthew G. Knepley 
23429f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
23439f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
23449f6c5813SMatthew G. Knepley 
23459f6c5813SMatthew G. Knepley /*@C
23469f6c5813SMatthew G. Knepley   DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
23479f6c5813SMatthew G. Knepley 
23489f6c5813SMatthew G. Knepley   Not Collective
23499f6c5813SMatthew G. Knepley 
23509f6c5813SMatthew G. Knepley   Level: advanced
23519f6c5813SMatthew G. Knepley 
235220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMRegisterAll()`, `DMLabelRegisterDestroy()`
23539f6c5813SMatthew G. Knepley @*/
23549f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterAll(void)
23559f6c5813SMatthew G. Knepley {
23569f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23573ba16761SJacob Faibussowitsch   if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
23589f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_TRUE;
23599f6c5813SMatthew G. Knepley 
23609f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
23619f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
23623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23639f6c5813SMatthew G. Knepley }
23649f6c5813SMatthew G. Knepley 
23659f6c5813SMatthew G. Knepley /*@C
23669f6c5813SMatthew G. Knepley   DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
23679f6c5813SMatthew G. Knepley 
23689f6c5813SMatthew G. Knepley   Level: developer
23699f6c5813SMatthew G. Knepley 
237020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscInitialize()`
23719f6c5813SMatthew G. Knepley @*/
23729f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterDestroy(void)
23739f6c5813SMatthew G. Knepley {
23749f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23759f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListDestroy(&DMLabelList));
23769f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_FALSE;
23773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23789f6c5813SMatthew G. Knepley }
23799f6c5813SMatthew G. Knepley 
2380cc4c1da9SBarry Smith /*@
23819f6c5813SMatthew G. Knepley   DMLabelSetType - Sets the particular implementation for a label.
23829f6c5813SMatthew G. Knepley 
238320f4b53cSBarry Smith   Collective
23849f6c5813SMatthew G. Knepley 
23859f6c5813SMatthew G. Knepley   Input Parameters:
23869f6c5813SMatthew G. Knepley + label  - The label
23879f6c5813SMatthew G. Knepley - method - The name of the label type
23889f6c5813SMatthew G. Knepley 
23899f6c5813SMatthew G. Knepley   Options Database Key:
239020f4b53cSBarry Smith . -dm_label_type <type> - Sets the label type; use -help for a list of available types or see `DMLabelType`
23919f6c5813SMatthew G. Knepley 
23929f6c5813SMatthew G. Knepley   Level: intermediate
23939f6c5813SMatthew G. Knepley 
239420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetType()`, `DMLabelCreate()`
23959f6c5813SMatthew G. Knepley @*/
23969f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
23979f6c5813SMatthew G. Knepley {
23989f6c5813SMatthew G. Knepley   PetscErrorCode (*r)(DMLabel);
23999f6c5813SMatthew G. Knepley   PetscBool match;
24009f6c5813SMatthew G. Knepley 
24019f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24029f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24039f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
24043ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
24059f6c5813SMatthew G. Knepley 
24069f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24079f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
24089f6c5813SMatthew G. Knepley   PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
24099f6c5813SMatthew G. Knepley 
24109f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, destroy);
24119f6c5813SMatthew G. Knepley   PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
24129f6c5813SMatthew G. Knepley   PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
24139f6c5813SMatthew G. Knepley   PetscCall((*r)(label));
24143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24159f6c5813SMatthew G. Knepley }
24169f6c5813SMatthew G. Knepley 
2417cc4c1da9SBarry Smith /*@
24189f6c5813SMatthew G. Knepley   DMLabelGetType - Gets the type name (as a string) from the label.
24199f6c5813SMatthew G. Knepley 
24209f6c5813SMatthew G. Knepley   Not Collective
24219f6c5813SMatthew G. Knepley 
24229f6c5813SMatthew G. Knepley   Input Parameter:
242320f4b53cSBarry Smith . label - The `DMLabel`
24249f6c5813SMatthew G. Knepley 
24259f6c5813SMatthew G. Knepley   Output Parameter:
242620f4b53cSBarry Smith . type - The `DMLabel` type name
24279f6c5813SMatthew G. Knepley 
24289f6c5813SMatthew G. Knepley   Level: intermediate
24299f6c5813SMatthew G. Knepley 
243020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetType()`, `DMLabelCreate()`
24319f6c5813SMatthew G. Knepley @*/
24329f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
24339f6c5813SMatthew G. Knepley {
24349f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24359f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24364f572ea9SToby Isaac   PetscAssertPointer(type, 2);
24379f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24389f6c5813SMatthew G. Knepley   *type = ((PetscObject)label)->type_name;
24393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24409f6c5813SMatthew G. Knepley }
24419f6c5813SMatthew G. Knepley 
24429f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
24439f6c5813SMatthew G. Knepley {
24449f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24459f6c5813SMatthew G. Knepley   label->ops->view         = DMLabelView_Concrete;
24469f6c5813SMatthew G. Knepley   label->ops->setup        = NULL;
24479f6c5813SMatthew G. Knepley   label->ops->duplicate    = DMLabelDuplicate_Concrete;
24489f6c5813SMatthew G. Knepley   label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
24493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24509f6c5813SMatthew G. Knepley }
24519f6c5813SMatthew G. Knepley 
24529f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
24539f6c5813SMatthew G. Knepley {
24549f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24559f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24569f6c5813SMatthew G. Knepley   PetscCall(DMLabelInitialize_Concrete(label));
24573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24589f6c5813SMatthew G. Knepley }
24599f6c5813SMatthew G. Knepley 
246084f0b6dfSMatthew G. Knepley /*@
2461c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
246220f4b53cSBarry Smith   the local section and an `PetscSF` describing the section point overlap.
2463c58f1c22SToby Isaac 
246420f4b53cSBarry Smith   Collective
24655b5e7992SMatthew G. Knepley 
2466c58f1c22SToby Isaac   Input Parameters:
246720f4b53cSBarry Smith + s                  - The `PetscSection` for the local field layout
246820f4b53cSBarry Smith . sf                 - The `PetscSF` describing parallel layout of the section points
246920f4b53cSBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
2470c58f1c22SToby Isaac . label              - The label specifying the points
2471c58f1c22SToby Isaac - labelValue         - The label stratum specifying the points
2472c58f1c22SToby Isaac 
2473c58f1c22SToby Isaac   Output Parameter:
247420f4b53cSBarry Smith . gsection - The `PetscSection` for the global field layout
2475c58f1c22SToby Isaac 
2476c58f1c22SToby Isaac   Level: developer
2477c58f1c22SToby Isaac 
247820f4b53cSBarry Smith   Note:
247920f4b53cSBarry Smith   This gives negative sizes and offsets to points not owned by this process
248020f4b53cSBarry Smith 
248120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionCreate()`
2482c58f1c22SToby Isaac @*/
2483d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2484d71ae5a4SJacob Faibussowitsch {
2485c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2486c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2487c58f1c22SToby Isaac 
2488c58f1c22SToby Isaac   PetscFunctionBegin;
2489d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2490d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2491d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
24929566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
24939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
24949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
24959566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2496c58f1c22SToby Isaac   if (nroots >= 0) {
249763a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
24989566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2499c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25009566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2501c58f1c22SToby Isaac     } else {
2502c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2503c58f1c22SToby Isaac     }
2504c58f1c22SToby Isaac   }
2505c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2506c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2507c58f1c22SToby Isaac     PetscInt value;
2508c58f1c22SToby Isaac 
25099566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2510c58f1c22SToby Isaac     if (value != labelValue) continue;
25119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
25129566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
25139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
25149566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2515c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2516c58f1c22SToby Isaac   }
25179566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2518c58f1c22SToby Isaac   if (nroots >= 0) {
25199566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25209566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2521c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25229371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25239371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
25249371c9d4SSatish Balay       }
2525c58f1c22SToby Isaac     }
2526c58f1c22SToby Isaac   }
252735cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
2528c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2529c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2530c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2531c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2532c58f1c22SToby Isaac   }
25339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2534c58f1c22SToby Isaac   globalOff -= off;
2535c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2536c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2537c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2538c58f1c22SToby Isaac   }
2539c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2540c58f1c22SToby Isaac   if (nroots >= 0) {
25419566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25429566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2543c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25449371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25459371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
25469371c9d4SSatish Balay       }
2547c58f1c22SToby Isaac     }
2548c58f1c22SToby Isaac   }
25499566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
25509566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
25513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2552c58f1c22SToby Isaac }
2553c58f1c22SToby Isaac 
25549371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
25555fdea053SToby Isaac   DMLabel              label;
25565fdea053SToby Isaac   PetscCopyMode       *modes;
25575fdea053SToby Isaac   PetscInt            *sizes;
25585fdea053SToby Isaac   const PetscInt    ***perms;
25595fdea053SToby Isaac   const PetscScalar ***rots;
25605fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
25615fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
25625fdea053SToby Isaac } PetscSectionSym_Label;
25635fdea053SToby Isaac 
2564d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2565d71ae5a4SJacob Faibussowitsch {
25665fdea053SToby Isaac   PetscInt               i, j;
25675fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
25685fdea053SToby Isaac 
25695fdea053SToby Isaac   PetscFunctionBegin;
25705fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
25715fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
25725fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
25739566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
25749566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
25755fdea053SToby Isaac       }
25765fdea053SToby Isaac       if (sl->perms[i]) {
25775fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
25785fdea053SToby Isaac 
25799566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
25805fdea053SToby Isaac       }
25815fdea053SToby Isaac       if (sl->rots[i]) {
25825fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
25835fdea053SToby Isaac 
25849566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
25855fdea053SToby Isaac       }
25865fdea053SToby Isaac     }
25875fdea053SToby Isaac   }
25889566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
25899566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
25905fdea053SToby Isaac   sl->numStrata = 0;
25913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25925fdea053SToby Isaac }
25935fdea053SToby Isaac 
2594d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2595d71ae5a4SJacob Faibussowitsch {
25965fdea053SToby Isaac   PetscFunctionBegin;
25979566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
25989566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
25993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26005fdea053SToby Isaac }
26015fdea053SToby Isaac 
2602d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2603d71ae5a4SJacob Faibussowitsch {
26045fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
26055fdea053SToby Isaac   PetscBool              isAscii;
26065fdea053SToby Isaac   DMLabel                label = sl->label;
2607d67d17b1SMatthew G. Knepley   const char            *name;
26085fdea053SToby Isaac 
26095fdea053SToby Isaac   PetscFunctionBegin;
26109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
26115fdea053SToby Isaac   if (isAscii) {
26125fdea053SToby Isaac     PetscInt          i, j, k;
26135fdea053SToby Isaac     PetscViewerFormat format;
26145fdea053SToby Isaac 
26159566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
26165fdea053SToby Isaac     if (label) {
26179566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
26185fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26199566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
26209566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
26219566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26225fdea053SToby Isaac       } else {
26239566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
26249566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
26255fdea053SToby Isaac       }
26265fdea053SToby Isaac     } else {
26279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
26285fdea053SToby Isaac     }
26299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
26305fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
26315fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
26325fdea053SToby Isaac 
26335fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
263463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
26355fdea053SToby Isaac       } else {
263663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
26379566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
263863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
26395fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26409566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
26415fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
26425fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
264363a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
26445fdea053SToby Isaac             } else {
26455fdea053SToby Isaac               PetscInt tab;
26465fdea053SToby Isaac 
264763a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
26489566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
26499566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
26505fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
26519566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
26529566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
265363a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
26549566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26559566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26565fdea053SToby Isaac               }
26575fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
26589566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
26599566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
26605fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
266163a3b9bcSJacob 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])));
26625fdea053SToby Isaac #else
266363a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
26645fdea053SToby Isaac #endif
26659566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26669566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26675fdea053SToby Isaac               }
26689566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
26695fdea053SToby Isaac             }
26705fdea053SToby Isaac           }
26719566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
26725fdea053SToby Isaac         }
26739566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26745fdea053SToby Isaac       }
26755fdea053SToby Isaac     }
26769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
26775fdea053SToby Isaac   }
26783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26795fdea053SToby Isaac }
26805fdea053SToby Isaac 
26815fdea053SToby Isaac /*@
26825fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
26835fdea053SToby Isaac 
268420f4b53cSBarry Smith   Logically
26855fdea053SToby Isaac 
268660225df5SJacob Faibussowitsch   Input Parameters:
26875fdea053SToby Isaac + sym   - the section symmetries
268820f4b53cSBarry Smith - label - the `DMLabel` describing the types of points
26895fdea053SToby Isaac 
26905fdea053SToby Isaac   Level: developer:
26915fdea053SToby Isaac 
269220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
26935fdea053SToby Isaac @*/
2694d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2695d71ae5a4SJacob Faibussowitsch {
26965fdea053SToby Isaac   PetscSectionSym_Label *sl;
26975fdea053SToby Isaac 
26985fdea053SToby Isaac   PetscFunctionBegin;
26995fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
27005fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
27019566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
27025fdea053SToby Isaac   if (label) {
27035fdea053SToby Isaac     sl->label = label;
27049566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
27059566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
27069566063dSJacob 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));
27079566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
27089566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
27099566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
27109566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
27119566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
27125fdea053SToby Isaac   }
27133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27145fdea053SToby Isaac }
27155fdea053SToby Isaac 
27165fdea053SToby Isaac /*@C
2717b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2718b004864fSMatthew G. Knepley 
271920f4b53cSBarry Smith   Logically Collective
2720b004864fSMatthew G. Knepley 
2721b004864fSMatthew G. Knepley   Input Parameters:
2722b004864fSMatthew G. Knepley + sym     - the section symmetries
2723b004864fSMatthew G. Knepley - stratum - the stratum value in the label that we are assigning symmetries for
2724b004864fSMatthew G. Knepley 
2725b004864fSMatthew G. Knepley   Output Parameters:
272620f4b53cSBarry Smith + size      - the number of dofs for points in the `stratum` of the label
272720f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
272820f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a ppoint in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
272920f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
273020f4b53cSBarry 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
2731b004864fSMatthew G. Knepley 
2732b004864fSMatthew G. Knepley   Level: developer
2733b004864fSMatthew G. Knepley 
273420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2735b004864fSMatthew G. Knepley @*/
2736d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2737d71ae5a4SJacob Faibussowitsch {
2738b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2739b004864fSMatthew G. Knepley   const char            *name;
2740b004864fSMatthew G. Knepley   PetscInt               i;
2741b004864fSMatthew G. Knepley 
2742b004864fSMatthew G. Knepley   PetscFunctionBegin;
2743b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2744b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2745b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2746b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2747b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2748b004864fSMatthew G. Knepley 
2749b004864fSMatthew G. Knepley     if (stratum == value) break;
2750b004864fSMatthew G. Knepley   }
27519566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2752b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
27539371c9d4SSatish Balay   if (size) {
27544f572ea9SToby Isaac     PetscAssertPointer(size, 3);
27559371c9d4SSatish Balay     *size = sl->sizes[i];
27569371c9d4SSatish Balay   }
27579371c9d4SSatish Balay   if (minOrient) {
27584f572ea9SToby Isaac     PetscAssertPointer(minOrient, 4);
27599371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
27609371c9d4SSatish Balay   }
27619371c9d4SSatish Balay   if (maxOrient) {
27624f572ea9SToby Isaac     PetscAssertPointer(maxOrient, 5);
27639371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
27649371c9d4SSatish Balay   }
27659371c9d4SSatish Balay   if (perms) {
27664f572ea9SToby Isaac     PetscAssertPointer(perms, 6);
27678e3a54c0SPierre Jolivet     *perms = PetscSafePointerPlusOffset(sl->perms[i], sl->minMaxOrients[i][0]);
27689371c9d4SSatish Balay   }
27699371c9d4SSatish Balay   if (rots) {
27704f572ea9SToby Isaac     PetscAssertPointer(rots, 7);
27718e3a54c0SPierre Jolivet     *rots = PetscSafePointerPlusOffset(sl->rots[i], sl->minMaxOrients[i][0]);
27729371c9d4SSatish Balay   }
27733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2774b004864fSMatthew G. Knepley }
2775b004864fSMatthew G. Knepley 
2776b004864fSMatthew G. Knepley /*@C
27775fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
27785fdea053SToby Isaac 
277920f4b53cSBarry Smith   Logically
27805fdea053SToby Isaac 
27815fdea053SToby Isaac   Input Parameters:
27825b5e7992SMatthew G. Knepley + sym       - the section symmetries
27835fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
278420f4b53cSBarry Smith . size      - the number of dofs for points in the `stratum` of the label
278520f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
278620f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a point in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
278720f4b53cSBarry Smith . mode      - how `sym` should copy the `perms` and `rots` arrays
278820f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
278920f4b53cSBarry 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
27905fdea053SToby Isaac 
27915fdea053SToby Isaac   Level: developer
27925fdea053SToby Isaac 
279320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
27945fdea053SToby Isaac @*/
2795d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2796d71ae5a4SJacob Faibussowitsch {
27975fdea053SToby Isaac   PetscSectionSym_Label *sl;
2798d67d17b1SMatthew G. Knepley   const char            *name;
2799d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
28005fdea053SToby Isaac 
28015fdea053SToby Isaac   PetscFunctionBegin;
28025fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
28035fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2804b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
28055fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
28065fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
28075fdea053SToby Isaac 
28085fdea053SToby Isaac     if (stratum == value) break;
28095fdea053SToby Isaac   }
28109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
281163a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
28125fdea053SToby Isaac   sl->sizes[i]            = size;
28135fdea053SToby Isaac   sl->modes[i]            = mode;
28145fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
28155fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
28165fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
28175fdea053SToby Isaac     if (perms) {
28185fdea053SToby Isaac       PetscInt **ownPerms;
28195fdea053SToby Isaac 
28209566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
28215fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28225fdea053SToby Isaac         if (perms[j]) {
28239566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2824ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
28255fdea053SToby Isaac         }
28265fdea053SToby Isaac       }
28275fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
28285fdea053SToby Isaac     }
28295fdea053SToby Isaac     if (rots) {
28305fdea053SToby Isaac       PetscScalar **ownRots;
28315fdea053SToby Isaac 
28329566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
28335fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28345fdea053SToby Isaac         if (rots[j]) {
28359566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2836ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
28375fdea053SToby Isaac         }
28385fdea053SToby Isaac       }
28395fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
28405fdea053SToby Isaac     }
28415fdea053SToby Isaac   } else {
28428e3a54c0SPierre Jolivet     sl->perms[i] = PetscSafePointerPlusOffset(perms, -minOrient);
28438e3a54c0SPierre Jolivet     sl->rots[i]  = PetscSafePointerPlusOffset(rots, -minOrient);
28445fdea053SToby Isaac   }
28453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28465fdea053SToby Isaac }
28475fdea053SToby Isaac 
2848d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2849d71ae5a4SJacob Faibussowitsch {
28505fdea053SToby Isaac   PetscInt               i, j, numStrata;
28515fdea053SToby Isaac   PetscSectionSym_Label *sl;
28525fdea053SToby Isaac   DMLabel                label;
28535fdea053SToby Isaac 
28545fdea053SToby Isaac   PetscFunctionBegin;
28555fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
28565fdea053SToby Isaac   numStrata = sl->numStrata;
28575fdea053SToby Isaac   label     = sl->label;
28585fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
28595fdea053SToby Isaac     PetscInt point = points[2 * i];
28605fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
28615fdea053SToby Isaac 
28625fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
28635fdea053SToby Isaac       if (label->validIS[j]) {
28645fdea053SToby Isaac         PetscInt k;
28655fdea053SToby Isaac 
28662b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(label->points[j], point, &k));
28675fdea053SToby Isaac         if (k >= 0) break;
28685fdea053SToby Isaac       } else {
28695fdea053SToby Isaac         PetscBool has;
28705fdea053SToby Isaac 
28719566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
28725fdea053SToby Isaac         if (has) break;
28735fdea053SToby Isaac       }
28745fdea053SToby Isaac     }
28759371c9d4SSatish 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],
28769371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2877ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2878ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
28795fdea053SToby Isaac   }
28803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28815fdea053SToby Isaac }
28825fdea053SToby Isaac 
2883d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2884d71ae5a4SJacob Faibussowitsch {
2885b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2886b004864fSMatthew G. Knepley   IS                     valIS;
2887b004864fSMatthew G. Knepley   const PetscInt        *values;
2888b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2889b004864fSMatthew G. Knepley 
2890b004864fSMatthew G. Knepley   PetscFunctionBegin;
28919566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
28929566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
28939566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2894b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2895b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2896b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2897b004864fSMatthew G. Knepley     const PetscInt    **perms;
2898b004864fSMatthew G. Knepley     const PetscScalar **rots;
2899b004864fSMatthew G. Knepley 
29009566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
29019566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2902b004864fSMatthew G. Knepley   }
29039566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
29043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2905b004864fSMatthew G. Knepley }
2906b004864fSMatthew G. Knepley 
2907d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2908d71ae5a4SJacob Faibussowitsch {
2909b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2910b004864fSMatthew G. Knepley   DMLabel                dlabel;
2911b004864fSMatthew G. Knepley 
2912b004864fSMatthew G. Knepley   PetscFunctionBegin;
29139566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
29149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
29159566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
29169566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
29173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2918b004864fSMatthew G. Knepley }
2919b004864fSMatthew G. Knepley 
2920d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2921d71ae5a4SJacob Faibussowitsch {
29225fdea053SToby Isaac   PetscSectionSym_Label *sl;
29235fdea053SToby Isaac 
29245fdea053SToby Isaac   PetscFunctionBegin;
29254dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
29265fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2927b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2928b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
29295fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
29305fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
29315fdea053SToby Isaac   sym->data            = (void *)sl;
29323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29335fdea053SToby Isaac }
29345fdea053SToby Isaac 
29355fdea053SToby Isaac /*@
29365fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
29375fdea053SToby Isaac 
29385fdea053SToby Isaac   Collective
29395fdea053SToby Isaac 
29405fdea053SToby Isaac   Input Parameters:
29415fdea053SToby Isaac + comm  - the MPI communicator for the new symmetry
29425fdea053SToby Isaac - label - the label defining the strata
29435fdea053SToby Isaac 
29442fe279fdSBarry Smith   Output Parameter:
29455fdea053SToby Isaac . sym - the section symmetries
29465fdea053SToby Isaac 
29475fdea053SToby Isaac   Level: developer
29485fdea053SToby Isaac 
294920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
29505fdea053SToby Isaac @*/
2951d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2952d71ae5a4SJacob Faibussowitsch {
29535fdea053SToby Isaac   PetscFunctionBegin;
29549566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
29559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
29569566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
29579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
29583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29595fdea053SToby Isaac }
2960