xref: /petsc/src/dm/label/dmlabel.c (revision 2a8381b23c702518c6b1ccbeafee50b9375df0e4)
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 {
4499f196a02SMartin Diehl   PetscBool isascii;
4509f6c5813SMatthew G. Knepley 
4519f6c5813SMatthew G. Knepley   PetscFunctionBegin;
4529f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4539f196a02SMartin 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 /*@
4824b793533SStefano Zampini   DMLabelViewFromOptions - View a `DMLabel` in a particular way based on a request in the options database
4834b793533SStefano Zampini 
4844b793533SStefano Zampini   Collective
4854b793533SStefano Zampini 
4864b793533SStefano Zampini   Input Parameters:
4874b793533SStefano Zampini + label - the `DMLabel` object
4884b793533SStefano Zampini . obj   - optional object that provides the prefix for the options database (if `NULL` then the prefix in `obj` is used)
4894b793533SStefano Zampini - name  - option string that is used to activate viewing
4904b793533SStefano Zampini 
4914b793533SStefano Zampini   Level: intermediate
4924b793533SStefano Zampini 
4934b793533SStefano Zampini   Note:
4944b793533SStefano Zampini   See `PetscObjectViewFromOptions()` for a list of values that can be provided in the options database to determine how the `DMLabel` is viewed
4954b793533SStefano Zampini 
4964b793533SStefano Zampini .seealso: [](ch_dmbase), `DMLabel`, `DMLabelView()`, `PetscObjectViewFromOptions()`, `DMLabelCreate()`
4974b793533SStefano Zampini @*/
4984b793533SStefano Zampini PetscErrorCode DMLabelViewFromOptions(DMLabel label, PeOp PetscObject obj, const char name[])
4994b793533SStefano Zampini {
5004b793533SStefano Zampini   PetscFunctionBegin;
5014b793533SStefano Zampini   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5024b793533SStefano Zampini   PetscCall(PetscObjectViewFromOptions((PetscObject)label, obj, name));
5034b793533SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
5044b793533SStefano Zampini }
5054b793533SStefano Zampini 
5064b793533SStefano Zampini /*@
50720f4b53cSBarry Smith   DMLabelReset - Destroys internal data structures in a `DMLabel`
508d67d17b1SMatthew G. Knepley 
50920f4b53cSBarry Smith   Not Collective
5105b5e7992SMatthew G. Knepley 
511d67d17b1SMatthew G. Knepley   Input Parameter:
51220f4b53cSBarry Smith . label - The `DMLabel`
513d67d17b1SMatthew G. Knepley 
514d67d17b1SMatthew G. Knepley   Level: beginner
515d67d17b1SMatthew G. Knepley 
51620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`, `DMLabelCreate()`
517d67d17b1SMatthew G. Knepley @*/
518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelReset(DMLabel label)
519d71ae5a4SJacob Faibussowitsch {
520d67d17b1SMatthew G. Knepley   PetscInt v;
521d67d17b1SMatthew G. Knepley 
522d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
523d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
524d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
5259f6c5813SMatthew G. Knepley     if (label->ht[v]) PetscCall(PetscHSetIDestroy(&label->ht[v]));
5269566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
527d67d17b1SMatthew G. Knepley   }
528b9907514SLisandro Dalcin   label->numStrata = 0;
5299566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
5309566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
5319566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
5329566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
5339566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
5349566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
535b9907514SLisandro Dalcin   label->pStart = -1;
536b9907514SLisandro Dalcin   label->pEnd   = -1;
5379566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
5383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
539d67d17b1SMatthew G. Knepley }
540d67d17b1SMatthew G. Knepley 
541d67d17b1SMatthew G. Knepley /*@
54220f4b53cSBarry Smith   DMLabelDestroy - Destroys a `DMLabel`
54384f0b6dfSMatthew G. Knepley 
54420f4b53cSBarry Smith   Collective
5455b5e7992SMatthew G. Knepley 
54684f0b6dfSMatthew G. Knepley   Input Parameter:
54720f4b53cSBarry Smith . label - The `DMLabel`
54884f0b6dfSMatthew G. Knepley 
54984f0b6dfSMatthew G. Knepley   Level: beginner
55084f0b6dfSMatthew G. Knepley 
55120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelReset()`, `DMLabelCreate()`
55284f0b6dfSMatthew G. Knepley @*/
553d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
554d71ae5a4SJacob Faibussowitsch {
555c58f1c22SToby Isaac   PetscFunctionBegin;
5563ba16761SJacob Faibussowitsch   if (!*label) PetscFunctionReturn(PETSC_SUCCESS);
557f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 1);
558f4f49eeaSPierre Jolivet   if (--((PetscObject)*label)->refct > 0) {
5599371c9d4SSatish Balay     *label = NULL;
5603ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5619371c9d4SSatish Balay   }
5629566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5639566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5649566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
5653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
566c58f1c22SToby Isaac }
567c58f1c22SToby Isaac 
56866976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDuplicate_Concrete(DMLabel label, DMLabel *labelnew)
5699f6c5813SMatthew G. Knepley {
5709f6c5813SMatthew G. Knepley   PetscFunctionBegin;
5719f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
5729f6c5813SMatthew G. Knepley     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
573f4f49eeaSPierre Jolivet     PetscCall(PetscObjectReference((PetscObject)label->points[v]));
5749f6c5813SMatthew G. Knepley     (*labelnew)->points[v] = label->points[v];
5759f6c5813SMatthew G. Knepley   }
5769f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5779f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5799f6c5813SMatthew G. Knepley }
5809f6c5813SMatthew G. Knepley 
58184f0b6dfSMatthew G. Knepley /*@
58220f4b53cSBarry Smith   DMLabelDuplicate - Duplicates a `DMLabel`
58384f0b6dfSMatthew G. Knepley 
58420f4b53cSBarry Smith   Collective
5855b5e7992SMatthew G. Knepley 
58684f0b6dfSMatthew G. Knepley   Input Parameter:
58720f4b53cSBarry Smith . label - The `DMLabel`
58884f0b6dfSMatthew G. Knepley 
58984f0b6dfSMatthew G. Knepley   Output Parameter:
59020f4b53cSBarry Smith . labelnew - new label
59184f0b6dfSMatthew G. Knepley 
59284f0b6dfSMatthew G. Knepley   Level: intermediate
59384f0b6dfSMatthew G. Knepley 
59420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
59584f0b6dfSMatthew G. Knepley @*/
596d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
597d71ae5a4SJacob Faibussowitsch {
598d67d17b1SMatthew G. Knepley   const char *name;
599c58f1c22SToby Isaac 
600c58f1c22SToby Isaac   PetscFunctionBegin;
601d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6029566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
6039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
6049566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
605c58f1c22SToby Isaac 
606c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
6075aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
6088dcf10e8SMatthew G. Knepley   (*labelnew)->readonly     = label->readonly;
6099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
6109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
6119f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->ht));
6129f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->points));
6139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
6149f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
615c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
616c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
617b9907514SLisandro Dalcin     (*labelnew)->validIS[v]       = PETSC_TRUE;
618c58f1c22SToby Isaac   }
619c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
620c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
621c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
6229f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, duplicate, labelnew);
6233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
624c58f1c22SToby Isaac }
625c58f1c22SToby Isaac 
626609dae6eSVaclav Hapla /*@C
62720f4b53cSBarry Smith   DMLabelCompare - Compare two `DMLabel` objects
628609dae6eSVaclav Hapla 
62920f4b53cSBarry Smith   Collective; No Fortran Support
630609dae6eSVaclav Hapla 
631609dae6eSVaclav Hapla   Input Parameters:
632f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
63320f4b53cSBarry Smith . l0   - First `DMLabel`
63420f4b53cSBarry Smith - l1   - Second `DMLabel`
635609dae6eSVaclav Hapla 
636a4e35b19SJacob Faibussowitsch   Output Parameters:
6375efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
6385efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
639609dae6eSVaclav Hapla 
640609dae6eSVaclav Hapla   Level: intermediate
641609dae6eSVaclav Hapla 
642609dae6eSVaclav Hapla   Notes:
6435efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
64420f4b53cSBarry Smith   If it is passed as `NULL` and difference is found, an error is thrown on all processes.
64520f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
646609dae6eSVaclav Hapla 
6475efe38ccSVaclav Hapla   The output message is set independently on each rank.
64820f4b53cSBarry Smith   It is set to `NULL` if no difference was found on the current rank. It must be freed by user.
64920f4b53cSBarry Smith   If message is passed as `NULL` and difference is found, the difference description is printed to stderr in synchronized manner.
65020f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
651609dae6eSVaclav Hapla 
652609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
653609dae6eSVaclav Hapla 
65420f4b53cSBarry Smith   The communicator needs to be specified because currently `DMLabel` can live on `PETSC_COMM_SELF` even if the underlying `DM` is parallel.
6555efe38ccSVaclav Hapla 
656a3b724e8SBarry Smith   Developer Note:
657a3b724e8SBarry Smith   Fortran stub cannot be generated automatically because `message` must be freed with `PetscFree()`
658a3b724e8SBarry Smith 
65920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
660609dae6eSVaclav Hapla @*/
661d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
662d71ae5a4SJacob Faibussowitsch {
663609dae6eSVaclav Hapla   const char *name0, *name1;
664609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6655efe38ccSVaclav Hapla   PetscBool   eq;
6665efe38ccSVaclav Hapla   PetscMPIInt rank;
667609dae6eSVaclav Hapla 
668609dae6eSVaclav Hapla   PetscFunctionBegin;
6695efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6705efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6714f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 4);
6724f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 5);
6739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6749566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6759566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
676609dae6eSVaclav Hapla   {
677609dae6eSVaclav Hapla     PetscInt v0, v1;
678609dae6eSVaclav Hapla 
6799566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6809566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6815efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
68248a46eb9SPierre 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));
6835440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPI_C_BOOL, MPI_LAND, comm));
6845efe38ccSVaclav Hapla     if (!eq) goto finish;
685609dae6eSVaclav Hapla   }
686609dae6eSVaclav Hapla   {
687609dae6eSVaclav Hapla     IS is0, is1;
688609dae6eSVaclav Hapla 
6899566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6909566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6919566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6939566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
69448a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
6955440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPI_C_BOOL, MPI_LAND, comm));
6965efe38ccSVaclav Hapla     if (!eq) goto finish;
697609dae6eSVaclav Hapla   }
698609dae6eSVaclav Hapla   {
699609dae6eSVaclav Hapla     PetscInt i, nValues;
700609dae6eSVaclav Hapla 
7019566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
702609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
703609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
704609dae6eSVaclav Hapla       PetscInt       n;
705609dae6eSVaclav Hapla       IS             is0, is1;
706609dae6eSVaclav Hapla 
7079566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
708609dae6eSVaclav Hapla       if (!n) continue;
7099566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
7109566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
7119566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
7129566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
7139566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
7145efe38ccSVaclav Hapla       if (!eq) {
71563a3b9bcSJacob 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));
7165efe38ccSVaclav Hapla         break;
717609dae6eSVaclav Hapla       }
718609dae6eSVaclav Hapla     }
7195440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPI_C_BOOL, MPI_LAND, comm));
720609dae6eSVaclav Hapla   }
721609dae6eSVaclav Hapla finish:
7225efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
723609dae6eSVaclav Hapla   if (message) {
724609dae6eSVaclav Hapla     *message = NULL;
72548a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
7265efe38ccSVaclav Hapla   } else {
72748a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
7289566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
7295efe38ccSVaclav Hapla   }
7305efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
7315efe38ccSVaclav Hapla   if (equal) *equal = eq;
73263a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
7333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
734609dae6eSVaclav Hapla }
735609dae6eSVaclav Hapla 
736c6a43d28SMatthew G. Knepley /*@
737c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
738c6a43d28SMatthew G. Knepley 
73920f4b53cSBarry Smith   Not Collective
7405b5e7992SMatthew G. Knepley 
741c6a43d28SMatthew G. Knepley   Input Parameter:
74220f4b53cSBarry Smith . label - The `DMLabel`
743c6a43d28SMatthew G. Knepley 
744c6a43d28SMatthew G. Knepley   Level: intermediate
745c6a43d28SMatthew G. Knepley 
74620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
747c6a43d28SMatthew G. Knepley @*/
748d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
749d71ae5a4SJacob Faibussowitsch {
7501690c2aeSBarry Smith   PetscInt pStart = PETSC_INT_MAX, pEnd = -1, v;
751c6a43d28SMatthew G. Knepley 
752c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
753c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7549566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
755c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
756c6a43d28SMatthew G. Knepley     const PetscInt *points;
757c6a43d28SMatthew G. Knepley     PetscInt        i;
758c6a43d28SMatthew G. Knepley 
7599566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
760c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
761c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
762c6a43d28SMatthew G. Knepley 
763c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
764c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
765c6a43d28SMatthew G. Knepley     }
7669566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
767c6a43d28SMatthew G. Knepley   }
7681690c2aeSBarry Smith   label->pStart = pStart == PETSC_INT_MAX ? -1 : pStart;
769c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7709566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
7713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
772c6a43d28SMatthew G. Knepley }
773c6a43d28SMatthew G. Knepley 
774c6a43d28SMatthew G. Knepley /*@
775c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
776c6a43d28SMatthew G. Knepley 
77720f4b53cSBarry Smith   Not Collective
7785b5e7992SMatthew G. Knepley 
779c6a43d28SMatthew G. Knepley   Input Parameters:
78020f4b53cSBarry Smith + label  - The `DMLabel`
781c6a43d28SMatthew G. Knepley . pStart - The smallest point
782c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
783c6a43d28SMatthew G. Knepley 
784c6a43d28SMatthew G. Knepley   Level: intermediate
785c6a43d28SMatthew G. Knepley 
78620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
787c6a43d28SMatthew G. Knepley @*/
788d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
789d71ae5a4SJacob Faibussowitsch {
790c58f1c22SToby Isaac   PetscInt v;
791c58f1c22SToby Isaac 
792c58f1c22SToby Isaac   PetscFunctionBegin;
793d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7949566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7959566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
796c58f1c22SToby Isaac   label->pStart = pStart;
797c58f1c22SToby Isaac   label->pEnd   = pEnd;
798c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7999566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
800c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
8019f6c5813SMatthew G. Knepley     IS              pointIS;
802ad8374ffSToby Isaac     const PetscInt *points;
803c58f1c22SToby Isaac     PetscInt        i;
804c58f1c22SToby Isaac 
8059f6c5813SMatthew G. Knepley     PetscUseTypeMethod(label, getstratumis, v, &pointIS);
8069f6c5813SMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
807c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
808ad8374ffSToby Isaac       const PetscInt point = points[i];
809c58f1c22SToby Isaac 
8109f6c5813SMatthew 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);
8119566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
812c58f1c22SToby Isaac     }
8139566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
8149f6c5813SMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
815c58f1c22SToby Isaac   }
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817c58f1c22SToby Isaac }
818c58f1c22SToby Isaac 
819c6a43d28SMatthew G. Knepley /*@
820c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
821c6a43d28SMatthew G. Knepley 
82220f4b53cSBarry Smith   Not Collective
8235b5e7992SMatthew G. Knepley 
824c6a43d28SMatthew G. Knepley   Input Parameter:
82520f4b53cSBarry Smith . label - the `DMLabel`
826c6a43d28SMatthew G. Knepley 
827c6a43d28SMatthew G. Knepley   Level: intermediate
828c6a43d28SMatthew G. Knepley 
82920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
830c6a43d28SMatthew G. Knepley @*/
831d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
832d71ae5a4SJacob Faibussowitsch {
833c58f1c22SToby Isaac   PetscFunctionBegin;
834d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
835c58f1c22SToby Isaac   label->pStart = -1;
836c58f1c22SToby Isaac   label->pEnd   = -1;
8379566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
8383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
839c58f1c22SToby Isaac }
840c58f1c22SToby Isaac 
841c58f1c22SToby Isaac /*@
842c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
843c6a43d28SMatthew G. Knepley 
84420f4b53cSBarry Smith   Not Collective
8455b5e7992SMatthew G. Knepley 
846c6a43d28SMatthew G. Knepley   Input Parameter:
84720f4b53cSBarry Smith . label - the `DMLabel`
848c6a43d28SMatthew G. Knepley 
849c6a43d28SMatthew G. Knepley   Output Parameters:
850c6a43d28SMatthew G. Knepley + pStart - The smallest point
851c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
852c6a43d28SMatthew G. Knepley 
853c6a43d28SMatthew G. Knepley   Level: intermediate
854c6a43d28SMatthew G. Knepley 
85520f4b53cSBarry Smith   Note:
85620f4b53cSBarry Smith   This will compute an index for the label if one does not exist.
85720f4b53cSBarry Smith 
85820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
859c6a43d28SMatthew G. Knepley @*/
860d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
861d71ae5a4SJacob Faibussowitsch {
862c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
863c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8649566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
865c6a43d28SMatthew G. Knepley   if (pStart) {
8664f572ea9SToby Isaac     PetscAssertPointer(pStart, 2);
867c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
868c6a43d28SMatthew G. Knepley   }
869c6a43d28SMatthew G. Knepley   if (pEnd) {
8704f572ea9SToby Isaac     PetscAssertPointer(pEnd, 3);
871c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
872c6a43d28SMatthew G. Knepley   }
8733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
874c6a43d28SMatthew G. Knepley }
875c6a43d28SMatthew G. Knepley 
876c6a43d28SMatthew G. Knepley /*@
877c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
878c58f1c22SToby Isaac 
87920f4b53cSBarry Smith   Not Collective
8805b5e7992SMatthew G. Knepley 
881c58f1c22SToby Isaac   Input Parameters:
88220f4b53cSBarry Smith + label - the `DMLabel`
883c58f1c22SToby Isaac - value - the value
884c58f1c22SToby Isaac 
885c58f1c22SToby Isaac   Output Parameter:
886c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
887c58f1c22SToby Isaac 
888c58f1c22SToby Isaac   Level: developer
889c58f1c22SToby Isaac 
89020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
891c58f1c22SToby Isaac @*/
892d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
893d71ae5a4SJacob Faibussowitsch {
894c58f1c22SToby Isaac   PetscInt v;
895c58f1c22SToby Isaac 
896c58f1c22SToby Isaac   PetscFunctionBegin;
897d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8984f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
8999566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
9000c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
9013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
902c58f1c22SToby Isaac }
903c58f1c22SToby Isaac 
904c58f1c22SToby Isaac /*@
905c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
906c58f1c22SToby Isaac 
90720f4b53cSBarry Smith   Not Collective
9085b5e7992SMatthew G. Knepley 
909c58f1c22SToby Isaac   Input Parameters:
91020f4b53cSBarry Smith + label - the `DMLabel`
911c58f1c22SToby Isaac - point - the point
912c58f1c22SToby Isaac 
913c58f1c22SToby Isaac   Output Parameter:
914c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
915c58f1c22SToby Isaac 
916c58f1c22SToby Isaac   Level: developer
917c58f1c22SToby Isaac 
91820f4b53cSBarry Smith   Note:
91920f4b53cSBarry Smith   The user must call `DMLabelCreateIndex()` before this function.
92020f4b53cSBarry Smith 
92120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
922c58f1c22SToby Isaac @*/
923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
924d71ae5a4SJacob Faibussowitsch {
925f1d0ab6dSZach Atkins   PetscInt pStart, pEnd;
926f1d0ab6dSZach Atkins 
927c58f1c22SToby Isaac   PetscFunctionBeginHot;
928d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9294f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
930f1d0ab6dSZach Atkins   /* DMLabelGetBounds() calls DMLabelCreateIndex() only if needed */
931f1d0ab6dSZach Atkins   PetscCall(DMLabelGetBounds(label, &pStart, &pEnd));
9329566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
933f1d0ab6dSZach Atkins   *contains = point >= pStart && point < pEnd && (PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE);
9343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
935c58f1c22SToby Isaac }
936c58f1c22SToby Isaac 
937c58f1c22SToby Isaac /*@
938c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
939c58f1c22SToby Isaac 
94020f4b53cSBarry Smith   Not Collective
9415b5e7992SMatthew G. Knepley 
942c58f1c22SToby Isaac   Input Parameters:
94320f4b53cSBarry Smith + label - the `DMLabel`
944c58f1c22SToby Isaac . value - the stratum value
945c58f1c22SToby Isaac - point - the point
946c58f1c22SToby Isaac 
947c58f1c22SToby Isaac   Output Parameter:
948c58f1c22SToby Isaac . contains - true if the stratum contains the point
949c58f1c22SToby Isaac 
950c58f1c22SToby Isaac   Level: intermediate
951c58f1c22SToby Isaac 
95220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
953c58f1c22SToby Isaac @*/
954d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
955d71ae5a4SJacob Faibussowitsch {
9560c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
957d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9584f572ea9SToby Isaac   PetscAssertPointer(contains, 4);
959cffad2c9SToby Isaac   if (value == label->defaultValue) {
960cffad2c9SToby Isaac     PetscInt pointVal;
9610c3c4a36SLisandro Dalcin 
962cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
963cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
964cffad2c9SToby Isaac   } else {
965cffad2c9SToby Isaac     PetscInt v;
966cffad2c9SToby Isaac 
967cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
968cffad2c9SToby Isaac     if (v >= 0) {
9699f6c5813SMatthew G. Knepley       if (label->validIS[v] || label->readonly) {
9709f6c5813SMatthew G. Knepley         IS       is;
971c58f1c22SToby Isaac         PetscInt i;
972c58f1c22SToby Isaac 
9739f6c5813SMatthew G. Knepley         PetscUseTypeMethod(label, getstratumis, v, &is);
9742b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(is, point, &i));
9759f6c5813SMatthew G. Knepley         PetscCall(ISDestroy(&is));
976cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
977c58f1c22SToby Isaac       } else {
978cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
979cffad2c9SToby Isaac       }
980cffad2c9SToby Isaac     } else { // value is not present
981cffad2c9SToby Isaac       *contains = PETSC_FALSE;
982cffad2c9SToby Isaac     }
983c58f1c22SToby Isaac   }
9843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
985c58f1c22SToby Isaac }
986c58f1c22SToby Isaac 
98784f0b6dfSMatthew G. Knepley /*@
98820f4b53cSBarry Smith   DMLabelGetDefaultValue - Get the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9895aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9905aa44df4SToby Isaac 
99120f4b53cSBarry Smith   Not Collective
9925b5e7992SMatthew G. Knepley 
99360225df5SJacob Faibussowitsch   Input Parameter:
99420f4b53cSBarry Smith . label - a `DMLabel` object
9955aa44df4SToby Isaac 
99660225df5SJacob Faibussowitsch   Output Parameter:
9975aa44df4SToby Isaac . defaultValue - the default value
9985aa44df4SToby Isaac 
9995aa44df4SToby Isaac   Level: beginner
10005aa44df4SToby Isaac 
100120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
100284f0b6dfSMatthew G. Knepley @*/
1003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
1004d71ae5a4SJacob Faibussowitsch {
10055aa44df4SToby Isaac   PetscFunctionBegin;
1006d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10075aa44df4SToby Isaac   *defaultValue = label->defaultValue;
10083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10095aa44df4SToby Isaac }
10105aa44df4SToby Isaac 
101184f0b6dfSMatthew G. Knepley /*@
101220f4b53cSBarry Smith   DMLabelSetDefaultValue - Set the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
10135aa44df4SToby Isaac   When a label is created, it is initialized to -1.
10145aa44df4SToby Isaac 
101520f4b53cSBarry Smith   Not Collective
10165b5e7992SMatthew G. Knepley 
101760225df5SJacob Faibussowitsch   Input Parameter:
101820f4b53cSBarry Smith . label - a `DMLabel` object
10195aa44df4SToby Isaac 
102060225df5SJacob Faibussowitsch   Output Parameter:
10215aa44df4SToby Isaac . defaultValue - the default value
10225aa44df4SToby Isaac 
10235aa44df4SToby Isaac   Level: beginner
10245aa44df4SToby Isaac 
102520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
102684f0b6dfSMatthew G. Knepley @*/
1027d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1028d71ae5a4SJacob Faibussowitsch {
10295aa44df4SToby Isaac   PetscFunctionBegin;
1030d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10315aa44df4SToby Isaac   label->defaultValue = defaultValue;
10323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10335aa44df4SToby Isaac }
10345aa44df4SToby Isaac 
1035c58f1c22SToby Isaac /*@
103620f4b53cSBarry 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
103720f4b53cSBarry Smith   `DMLabelSetDefaultValue()`)
1038c58f1c22SToby Isaac 
103920f4b53cSBarry Smith   Not Collective
10405b5e7992SMatthew G. Knepley 
1041c58f1c22SToby Isaac   Input Parameters:
104220f4b53cSBarry Smith + label - the `DMLabel`
1043c58f1c22SToby Isaac - point - the point
1044c58f1c22SToby Isaac 
1045c58f1c22SToby Isaac   Output Parameter:
10468e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
1047c58f1c22SToby Isaac 
1048c58f1c22SToby Isaac   Level: intermediate
1049c58f1c22SToby Isaac 
105020f4b53cSBarry Smith   Note:
105120f4b53cSBarry Smith   A label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.
105220f4b53cSBarry Smith   Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
105320f4b53cSBarry Smith 
105420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1055c58f1c22SToby Isaac @*/
1056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1057d71ae5a4SJacob Faibussowitsch {
1058c58f1c22SToby Isaac   PetscInt v;
1059c58f1c22SToby Isaac 
10600c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
1061d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10624f572ea9SToby Isaac   PetscAssertPointer(value, 3);
10635aa44df4SToby Isaac   *value = label->defaultValue;
1064c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
10659f6c5813SMatthew G. Knepley     if (label->validIS[v] || label->readonly) {
10669f6c5813SMatthew G. Knepley       IS       is;
1067c58f1c22SToby Isaac       PetscInt i;
1068c58f1c22SToby Isaac 
10699f6c5813SMatthew G. Knepley       PetscUseTypeMethod(label, getstratumis, v, &is);
10702b4d18a0SMatthew G. Knepley       PetscCall(ISLocate(label->points[v], point, &i));
10719f6c5813SMatthew G. Knepley       PetscCall(ISDestroy(&is));
1072c58f1c22SToby Isaac       if (i >= 0) {
1073c58f1c22SToby Isaac         *value = label->stratumValues[v];
1074c58f1c22SToby Isaac         break;
1075c58f1c22SToby Isaac       }
1076c58f1c22SToby Isaac     } else {
1077c58f1c22SToby Isaac       PetscBool has;
1078c58f1c22SToby Isaac 
10799566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1080c58f1c22SToby Isaac       if (has) {
1081c58f1c22SToby Isaac         *value = label->stratumValues[v];
1082c58f1c22SToby Isaac         break;
1083c58f1c22SToby Isaac       }
1084c58f1c22SToby Isaac     }
1085c58f1c22SToby Isaac   }
10863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1087c58f1c22SToby Isaac }
1088c58f1c22SToby Isaac 
1089c58f1c22SToby Isaac /*@
109020f4b53cSBarry 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
109120f4b53cSBarry Smith   be changed with `DMLabelSetDefaultValue()` to something different), then this function will do nothing.
1092c58f1c22SToby Isaac 
109320f4b53cSBarry Smith   Not Collective
10945b5e7992SMatthew G. Knepley 
1095c58f1c22SToby Isaac   Input Parameters:
109620f4b53cSBarry Smith + label - the `DMLabel`
1097c58f1c22SToby Isaac . point - the point
1098c58f1c22SToby Isaac - value - The point value
1099c58f1c22SToby Isaac 
1100c58f1c22SToby Isaac   Level: intermediate
1101c58f1c22SToby Isaac 
110220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1103c58f1c22SToby Isaac @*/
1104d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1105d71ae5a4SJacob Faibussowitsch {
1106c58f1c22SToby Isaac   PetscInt v;
1107c58f1c22SToby Isaac 
1108c58f1c22SToby Isaac   PetscFunctionBegin;
1109d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11100c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11113ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11129f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11139566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1114c58f1c22SToby Isaac   /* Set key */
11159566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11169566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
11173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1118c58f1c22SToby Isaac }
1119c58f1c22SToby Isaac 
1120c58f1c22SToby Isaac /*@
1121c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1122c58f1c22SToby Isaac 
112320f4b53cSBarry Smith   Not Collective
11245b5e7992SMatthew G. Knepley 
1125c58f1c22SToby Isaac   Input Parameters:
112620f4b53cSBarry Smith + label - the `DMLabel`
1127c58f1c22SToby Isaac . point - the point
1128c58f1c22SToby Isaac - value - The point value
1129c58f1c22SToby Isaac 
1130c58f1c22SToby Isaac   Level: intermediate
1131c58f1c22SToby Isaac 
113220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1133c58f1c22SToby Isaac @*/
1134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1135d71ae5a4SJacob Faibussowitsch {
1136ad8374ffSToby Isaac   PetscInt v;
1137c58f1c22SToby Isaac 
1138c58f1c22SToby Isaac   PetscFunctionBegin;
1139d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11409f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1141c58f1c22SToby Isaac   /* Find label value */
11429566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
11433ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
11440c3c4a36SLisandro Dalcin 
1145f1d0ab6dSZach Atkins   if (label->bt && point >= label->pStart && point < label->pEnd) PetscCall(PetscBTClear(label->bt, point - label->pStart));
11460c3c4a36SLisandro Dalcin 
11470c3c4a36SLisandro Dalcin   /* Delete key */
11489566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11499566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
11503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1151c58f1c22SToby Isaac }
1152c58f1c22SToby Isaac 
1153c58f1c22SToby Isaac /*@
115420f4b53cSBarry Smith   DMLabelInsertIS - Set all points in the `IS` to a value
1155c58f1c22SToby Isaac 
115620f4b53cSBarry Smith   Not Collective
11575b5e7992SMatthew G. Knepley 
1158c58f1c22SToby Isaac   Input Parameters:
115920f4b53cSBarry Smith + label - the `DMLabel`
11602fe279fdSBarry Smith . is    - the point `IS`
1161c58f1c22SToby Isaac - value - The point value
1162c58f1c22SToby Isaac 
1163c58f1c22SToby Isaac   Level: intermediate
1164c58f1c22SToby Isaac 
116520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1166c58f1c22SToby Isaac @*/
1167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1168d71ae5a4SJacob Faibussowitsch {
11690c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1170c58f1c22SToby Isaac   const PetscInt *points;
1171c58f1c22SToby Isaac 
1172c58f1c22SToby Isaac   PetscFunctionBegin;
1173d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1174c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11750c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11763ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11779f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11789566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11790c3c4a36SLisandro Dalcin   /* Set keys */
11809566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11819566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11829566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11839566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11849566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
11853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1186c58f1c22SToby Isaac }
1187c58f1c22SToby Isaac 
118884f0b6dfSMatthew G. Knepley /*@
118920f4b53cSBarry Smith   DMLabelGetNumValues - Get the number of values that the `DMLabel` takes
119084f0b6dfSMatthew G. Knepley 
119120f4b53cSBarry Smith   Not Collective
11925b5e7992SMatthew G. Knepley 
119384f0b6dfSMatthew G. Knepley   Input Parameter:
119420f4b53cSBarry Smith . label - the `DMLabel`
119584f0b6dfSMatthew G. Knepley 
119601d2d390SJose E. Roman   Output Parameter:
119784f0b6dfSMatthew G. Knepley . numValues - the number of values
119884f0b6dfSMatthew G. Knepley 
119984f0b6dfSMatthew G. Knepley   Level: intermediate
120084f0b6dfSMatthew G. Knepley 
120120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
120284f0b6dfSMatthew G. Knepley @*/
1203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1204d71ae5a4SJacob Faibussowitsch {
1205c58f1c22SToby Isaac   PetscFunctionBegin;
1206d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12074f572ea9SToby Isaac   PetscAssertPointer(numValues, 2);
1208c58f1c22SToby Isaac   *numValues = label->numStrata;
12093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1210c58f1c22SToby Isaac }
1211c58f1c22SToby Isaac 
121284f0b6dfSMatthew G. Knepley /*@
121320f4b53cSBarry Smith   DMLabelGetValueIS - Get an `IS` of all values that the `DMlabel` takes
121484f0b6dfSMatthew G. Knepley 
121520f4b53cSBarry Smith   Not Collective
12165b5e7992SMatthew G. Knepley 
121784f0b6dfSMatthew G. Knepley   Input Parameter:
121820f4b53cSBarry Smith . label - the `DMLabel`
121984f0b6dfSMatthew G. Knepley 
122001d2d390SJose E. Roman   Output Parameter:
122160225df5SJacob Faibussowitsch . values - the value `IS`
122284f0b6dfSMatthew G. Knepley 
122384f0b6dfSMatthew G. Knepley   Level: intermediate
122484f0b6dfSMatthew G. Knepley 
12251d04cbbeSVaclav Hapla   Notes:
122620f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
122720f4b53cSBarry Smith   Strata which are allocated but empty [`DMLabelGetStratumSize()` yields 0] are counted.
122820f4b53cSBarry Smith   If you need to count only nonempty strata, use `DMLabelGetNonEmptyStratumValuesIS()`.
12291d04cbbeSVaclav Hapla 
123020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
123184f0b6dfSMatthew G. Knepley @*/
1232d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1233d71ae5a4SJacob Faibussowitsch {
1234c58f1c22SToby Isaac   PetscFunctionBegin;
1235d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12364f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12379566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1239c58f1c22SToby Isaac }
1240c58f1c22SToby Isaac 
124184f0b6dfSMatthew G. Knepley /*@
12428696263dSMatthew G. Knepley   DMLabelGetValueBounds - Return the smallest and largest value in the label
12438696263dSMatthew G. Knepley 
12448696263dSMatthew G. Knepley   Not Collective
12458696263dSMatthew G. Knepley 
12468696263dSMatthew G. Knepley   Input Parameter:
12478696263dSMatthew G. Knepley . label - the `DMLabel`
12488696263dSMatthew G. Knepley 
12498696263dSMatthew G. Knepley   Output Parameters:
12508696263dSMatthew G. Knepley + minValue - The smallest value
12518696263dSMatthew G. Knepley - maxValue - The largest value
12528696263dSMatthew G. Knepley 
12538696263dSMatthew G. Knepley   Level: intermediate
12548696263dSMatthew G. Knepley 
12558696263dSMatthew G. Knepley .seealso: `DMLabel`, `DM`, `DMLabelGetBounds()`, `DMLabelGetValue()`, `DMLabelSetValue()`
12568696263dSMatthew G. Knepley @*/
12578696263dSMatthew G. Knepley PetscErrorCode DMLabelGetValueBounds(DMLabel label, PetscInt *minValue, PetscInt *maxValue)
12588696263dSMatthew G. Knepley {
12591690c2aeSBarry Smith   PetscInt min = PETSC_INT_MAX, max = PETSC_INT_MIN;
12608696263dSMatthew G. Knepley 
12618696263dSMatthew G. Knepley   PetscFunctionBegin;
12628696263dSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12638696263dSMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
12648696263dSMatthew G. Knepley     min = PetscMin(min, label->stratumValues[v]);
12658696263dSMatthew G. Knepley     max = PetscMax(max, label->stratumValues[v]);
12668696263dSMatthew G. Knepley   }
12678696263dSMatthew G. Knepley   if (minValue) {
12688696263dSMatthew G. Knepley     PetscAssertPointer(minValue, 2);
12698696263dSMatthew G. Knepley     *minValue = min;
12708696263dSMatthew G. Knepley   }
12718696263dSMatthew G. Knepley   if (maxValue) {
12728696263dSMatthew G. Knepley     PetscAssertPointer(maxValue, 3);
12738696263dSMatthew G. Knepley     *maxValue = max;
12748696263dSMatthew G. Knepley   }
12758696263dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
12768696263dSMatthew G. Knepley }
12778696263dSMatthew G. Knepley 
12788696263dSMatthew G. Knepley /*@
127920f4b53cSBarry Smith   DMLabelGetNonEmptyStratumValuesIS - Get an `IS` of all values that the `DMlabel` takes
12801d04cbbeSVaclav Hapla 
128120f4b53cSBarry Smith   Not Collective
12821d04cbbeSVaclav Hapla 
12831d04cbbeSVaclav Hapla   Input Parameter:
128420f4b53cSBarry Smith . label - the `DMLabel`
12851d04cbbeSVaclav Hapla 
1286d5b43468SJose E. Roman   Output Parameter:
128760225df5SJacob Faibussowitsch . values - the value `IS`
12881d04cbbeSVaclav Hapla 
12891d04cbbeSVaclav Hapla   Level: intermediate
12901d04cbbeSVaclav Hapla 
12911d04cbbeSVaclav Hapla   Notes:
129220f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
129320f4b53cSBarry Smith   This is similar to `DMLabelGetValueIS()` but counts only nonempty strata.
12941d04cbbeSVaclav Hapla 
129520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
12961d04cbbeSVaclav Hapla @*/
1297d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1298d71ae5a4SJacob Faibussowitsch {
12991d04cbbeSVaclav Hapla   PetscInt  i, j;
13001d04cbbeSVaclav Hapla   PetscInt *valuesArr;
13011d04cbbeSVaclav Hapla 
13021d04cbbeSVaclav Hapla   PetscFunctionBegin;
13031d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13044f572ea9SToby Isaac   PetscAssertPointer(values, 2);
13059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
13061d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
13071d04cbbeSVaclav Hapla     PetscInt n;
13081d04cbbeSVaclav Hapla 
13099566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
13101d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
13111d04cbbeSVaclav Hapla   }
13121d04cbbeSVaclav Hapla   if (j == label->numStrata) {
13139566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
13141d04cbbeSVaclav Hapla   } else {
13159566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
13161d04cbbeSVaclav Hapla   }
13179566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
13183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13191d04cbbeSVaclav Hapla }
13201d04cbbeSVaclav Hapla 
13211d04cbbeSVaclav Hapla /*@
132220f4b53cSBarry Smith   DMLabelGetValueIndex - Get the index of a given value in the list of values for the `DMlabel`, or -1 if it is not present
1323d123abd9SMatthew G. Knepley 
132420f4b53cSBarry Smith   Not Collective
1325d123abd9SMatthew G. Knepley 
1326d123abd9SMatthew G. Knepley   Input Parameters:
132720f4b53cSBarry Smith + label - the `DMLabel`
132897bb3fdcSJose E. Roman - value - the value
1329d123abd9SMatthew G. Knepley 
133001d2d390SJose E. Roman   Output Parameter:
1331d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1332d123abd9SMatthew G. Knepley 
1333d123abd9SMatthew G. Knepley   Level: intermediate
1334d123abd9SMatthew G. Knepley 
133520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1336d123abd9SMatthew G. Knepley @*/
1337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1338d71ae5a4SJacob Faibussowitsch {
1339d123abd9SMatthew G. Knepley   PetscInt v;
1340d123abd9SMatthew G. Knepley 
1341d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1342d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13434f572ea9SToby Isaac   PetscAssertPointer(index, 3);
1344d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
13459371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
13469371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1347d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1348d123abd9SMatthew G. Knepley   else *index = v;
13493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1350d123abd9SMatthew G. Knepley }
1351d123abd9SMatthew G. Knepley 
1352d123abd9SMatthew G. Knepley /*@
135384f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
135484f0b6dfSMatthew G. Knepley 
135520f4b53cSBarry Smith   Not Collective
13565b5e7992SMatthew G. Knepley 
135784f0b6dfSMatthew G. Knepley   Input Parameters:
135820f4b53cSBarry Smith + label - the `DMLabel`
135984f0b6dfSMatthew G. Knepley - value - the stratum value
136084f0b6dfSMatthew G. Knepley 
136101d2d390SJose E. Roman   Output Parameter:
136284f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
136384f0b6dfSMatthew G. Knepley 
136484f0b6dfSMatthew G. Knepley   Level: intermediate
136584f0b6dfSMatthew G. Knepley 
136620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
136784f0b6dfSMatthew G. Knepley @*/
1368d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1369d71ae5a4SJacob Faibussowitsch {
1370fada774cSMatthew G. Knepley   PetscInt v;
1371fada774cSMatthew G. Knepley 
1372fada774cSMatthew G. Knepley   PetscFunctionBegin;
1373d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13744f572ea9SToby Isaac   PetscAssertPointer(exists, 3);
13759566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13760c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
13773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1378fada774cSMatthew G. Knepley }
1379fada774cSMatthew G. Knepley 
138084f0b6dfSMatthew G. Knepley /*@
138184f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
138284f0b6dfSMatthew G. Knepley 
138320f4b53cSBarry Smith   Not Collective
13845b5e7992SMatthew G. Knepley 
138584f0b6dfSMatthew G. Knepley   Input Parameters:
138620f4b53cSBarry Smith + label - the `DMLabel`
138784f0b6dfSMatthew G. Knepley - value - the stratum value
138884f0b6dfSMatthew G. Knepley 
138901d2d390SJose E. Roman   Output Parameter:
139084f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
139184f0b6dfSMatthew G. Knepley 
139284f0b6dfSMatthew G. Knepley   Level: intermediate
139384f0b6dfSMatthew G. Knepley 
139420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
139584f0b6dfSMatthew G. Knepley @*/
1396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1397d71ae5a4SJacob Faibussowitsch {
1398c58f1c22SToby Isaac   PetscInt v;
1399c58f1c22SToby Isaac 
1400c58f1c22SToby Isaac   PetscFunctionBegin;
1401d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14024f572ea9SToby Isaac   PetscAssertPointer(size, 3);
14039566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14049566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
14053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1406c58f1c22SToby Isaac }
1407c58f1c22SToby Isaac 
140884f0b6dfSMatthew G. Knepley /*@
140984f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
141084f0b6dfSMatthew G. Knepley 
141120f4b53cSBarry Smith   Not Collective
14125b5e7992SMatthew G. Knepley 
141384f0b6dfSMatthew G. Knepley   Input Parameters:
141420f4b53cSBarry Smith + label - the `DMLabel`
141584f0b6dfSMatthew G. Knepley - value - the stratum value
141684f0b6dfSMatthew G. Knepley 
141701d2d390SJose E. Roman   Output Parameters:
141884f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
141984f0b6dfSMatthew G. Knepley - end   - the largest point in the stratum
142084f0b6dfSMatthew G. Knepley 
142184f0b6dfSMatthew G. Knepley   Level: intermediate
142284f0b6dfSMatthew G. Knepley 
142320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
142484f0b6dfSMatthew G. Knepley @*/
1425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1426d71ae5a4SJacob Faibussowitsch {
14279f6c5813SMatthew G. Knepley   IS       is;
14280c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1429c58f1c22SToby Isaac 
1430c58f1c22SToby Isaac   PetscFunctionBegin;
1431d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14329371c9d4SSatish Balay   if (start) {
14334f572ea9SToby Isaac     PetscAssertPointer(start, 3);
14349371c9d4SSatish Balay     *start = -1;
14359371c9d4SSatish Balay   }
14369371c9d4SSatish Balay   if (end) {
14374f572ea9SToby Isaac     PetscAssertPointer(end, 4);
14389371c9d4SSatish Balay     *end = -1;
14399371c9d4SSatish Balay   }
14409566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14413ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14429566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14433ba16761SJacob Faibussowitsch   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
14449f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &is);
14459f6c5813SMatthew G. Knepley   PetscCall(ISGetMinMax(is, &min, &max));
14469f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&is));
1447d6cb179aSToby Isaac   if (start) *start = min;
1448d6cb179aSToby Isaac   if (end) *end = max + 1;
14493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1450c58f1c22SToby Isaac }
1451c58f1c22SToby Isaac 
145266976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
14539f6c5813SMatthew G. Knepley {
14549f6c5813SMatthew G. Knepley   PetscFunctionBegin;
14559f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
14569f6c5813SMatthew G. Knepley   *pointIS = label->points[v];
14573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14589f6c5813SMatthew G. Knepley }
14599f6c5813SMatthew G. Knepley 
146084f0b6dfSMatthew G. Knepley /*@
146120f4b53cSBarry Smith   DMLabelGetStratumIS - Get an `IS` with the stratum points
146284f0b6dfSMatthew G. Knepley 
146320f4b53cSBarry Smith   Not Collective
14645b5e7992SMatthew G. Knepley 
146584f0b6dfSMatthew G. Knepley   Input Parameters:
146620f4b53cSBarry Smith + label - the `DMLabel`
146784f0b6dfSMatthew G. Knepley - value - the stratum value
146884f0b6dfSMatthew G. Knepley 
146901d2d390SJose E. Roman   Output Parameter:
147084f0b6dfSMatthew G. Knepley . points - The stratum points
147184f0b6dfSMatthew G. Knepley 
147284f0b6dfSMatthew G. Knepley   Level: intermediate
147384f0b6dfSMatthew G. Knepley 
1474593ce467SVaclav Hapla   Notes:
147520f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
147620f4b53cSBarry Smith   Returns `NULL` if the stratum is empty.
1477593ce467SVaclav Hapla 
147820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
147984f0b6dfSMatthew G. Knepley @*/
1480d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1481d71ae5a4SJacob Faibussowitsch {
1482c58f1c22SToby Isaac   PetscInt v;
1483c58f1c22SToby Isaac 
1484c58f1c22SToby Isaac   PetscFunctionBegin;
1485d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14864f572ea9SToby Isaac   PetscAssertPointer(points, 3);
1487c58f1c22SToby Isaac   *points = NULL;
14889566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14893ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14909566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14919f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, points);
14923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1493c58f1c22SToby Isaac }
1494c58f1c22SToby Isaac 
149584f0b6dfSMatthew G. Knepley /*@
149620f4b53cSBarry Smith   DMLabelSetStratumIS - Set the stratum points using an `IS`
149784f0b6dfSMatthew G. Knepley 
149820f4b53cSBarry Smith   Not Collective
14995b5e7992SMatthew G. Knepley 
150084f0b6dfSMatthew G. Knepley   Input Parameters:
150120f4b53cSBarry Smith + label - the `DMLabel`
150284f0b6dfSMatthew G. Knepley . value - the stratum value
150360225df5SJacob Faibussowitsch - is    - The stratum points
150484f0b6dfSMatthew G. Knepley 
150584f0b6dfSMatthew G. Knepley   Level: intermediate
150684f0b6dfSMatthew G. Knepley 
150720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
150884f0b6dfSMatthew G. Knepley @*/
1509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1510d71ae5a4SJacob Faibussowitsch {
15110c3c4a36SLisandro Dalcin   PetscInt v;
15124de306b1SToby Isaac 
15134de306b1SToby Isaac   PetscFunctionBegin;
1514d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1515d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
15169f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15179566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
15183ba16761SJacob Faibussowitsch   if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
15199566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
1520f4f49eeaSPierre Jolivet   PetscCall(ISGetLocalSize(is, &label->stratumSizes[v]));
15219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
1522f4f49eeaSPierre Jolivet   PetscCall(ISDestroy(&label->points[v]));
15230c3c4a36SLisandro Dalcin   label->points[v]  = is;
15240c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
15259566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
15264de306b1SToby Isaac   if (label->bt) {
15274de306b1SToby Isaac     const PetscInt *points;
15284de306b1SToby Isaac     PetscInt        p;
15294de306b1SToby Isaac 
15309566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
15314de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
15324de306b1SToby Isaac       const PetscInt point = points[p];
15334de306b1SToby Isaac 
153463a3b9bcSJacob 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);
15359566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
15364de306b1SToby Isaac     }
15374de306b1SToby Isaac   }
15383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15394de306b1SToby Isaac }
15404de306b1SToby Isaac 
154184f0b6dfSMatthew G. Knepley /*@
154284f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
15434de306b1SToby Isaac 
154420f4b53cSBarry Smith   Not Collective
15455b5e7992SMatthew G. Knepley 
154684f0b6dfSMatthew G. Knepley   Input Parameters:
154720f4b53cSBarry Smith + label - the `DMLabel`
154884f0b6dfSMatthew G. Knepley - value - the stratum value
154984f0b6dfSMatthew G. Knepley 
155084f0b6dfSMatthew G. Knepley   Level: intermediate
155184f0b6dfSMatthew G. Knepley 
155220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
155384f0b6dfSMatthew G. Knepley @*/
1554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1555d71ae5a4SJacob Faibussowitsch {
1556c58f1c22SToby Isaac   PetscInt v;
1557c58f1c22SToby Isaac 
1558c58f1c22SToby Isaac   PetscFunctionBegin;
1559d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15609f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15619566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15623ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15634de306b1SToby Isaac   if (label->validIS[v]) {
15644de306b1SToby Isaac     if (label->bt) {
1565c58f1c22SToby Isaac       PetscInt        i;
1566ad8374ffSToby Isaac       const PetscInt *points;
1567c58f1c22SToby Isaac 
15689566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1569c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1570ad8374ffSToby Isaac         const PetscInt point = points[i];
1571c58f1c22SToby Isaac 
1572f1d0ab6dSZach Atkins         if (point >= label->pStart && point < label->pEnd) PetscCall(PetscBTClear(label->bt, point - label->pStart));
1573c58f1c22SToby Isaac       }
15749566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1575c58f1c22SToby Isaac     }
1576c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
15779566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
15789566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
15799566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
15809566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1581c58f1c22SToby Isaac   } else {
15829566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1583c58f1c22SToby Isaac   }
15843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1585c58f1c22SToby Isaac }
1586c58f1c22SToby Isaac 
158784f0b6dfSMatthew G. Knepley /*@
1588412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1589412e9a14SMatthew G. Knepley 
159020f4b53cSBarry Smith   Not Collective
1591412e9a14SMatthew G. Knepley 
1592412e9a14SMatthew G. Knepley   Input Parameters:
159320f4b53cSBarry Smith + label  - The `DMLabel`
1594412e9a14SMatthew G. Knepley . value  - The label value for all points
1595412e9a14SMatthew G. Knepley . pStart - The first point
1596412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1597412e9a14SMatthew G. Knepley 
1598412e9a14SMatthew G. Knepley   Level: intermediate
1599412e9a14SMatthew G. Knepley 
160020f4b53cSBarry Smith   Note:
160120f4b53cSBarry Smith   The marks points are [`pStart`, `pEnd`), and only the bounds are stored.
160220f4b53cSBarry Smith 
160320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1604412e9a14SMatthew G. Knepley @*/
1605d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1606d71ae5a4SJacob Faibussowitsch {
1607412e9a14SMatthew G. Knepley   IS pIS;
1608412e9a14SMatthew G. Knepley 
1609412e9a14SMatthew G. Knepley   PetscFunctionBegin;
16109566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
16119566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
16129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
16133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1614412e9a14SMatthew G. Knepley }
1615412e9a14SMatthew G. Knepley 
1616412e9a14SMatthew G. Knepley /*@
1617d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1618d123abd9SMatthew G. Knepley 
161920f4b53cSBarry Smith   Not Collective
1620d123abd9SMatthew G. Knepley 
1621d123abd9SMatthew G. Knepley   Input Parameters:
162220f4b53cSBarry Smith + label - The `DMLabel`
1623d123abd9SMatthew G. Knepley . value - The label value
1624d123abd9SMatthew G. Knepley - p     - A point with this value
1625d123abd9SMatthew G. Knepley 
1626d123abd9SMatthew G. Knepley   Output Parameter:
1627d123abd9SMatthew 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
1628d123abd9SMatthew G. Knepley 
1629d123abd9SMatthew G. Knepley   Level: intermediate
1630d123abd9SMatthew G. Knepley 
163120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1632d123abd9SMatthew G. Knepley @*/
1633d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1634d71ae5a4SJacob Faibussowitsch {
16359f6c5813SMatthew G. Knepley   IS       pointIS;
1636d123abd9SMatthew G. Knepley   PetscInt v;
1637d123abd9SMatthew G. Knepley 
1638d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1639d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16404f572ea9SToby Isaac   PetscAssertPointer(index, 4);
1641d123abd9SMatthew G. Knepley   *index = -1;
16429566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
16433ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
16449566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
16459f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &pointIS);
1646f622de60SMatthew G. Knepley   PetscCall(ISLocate(pointIS, p, index));
16479f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&pointIS));
16483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1649d123abd9SMatthew G. Knepley }
1650d123abd9SMatthew G. Knepley 
1651d123abd9SMatthew G. Knepley /*@
165220f4b53cSBarry Smith   DMLabelFilter - Remove all points outside of [`start`, `end`)
165384f0b6dfSMatthew G. Knepley 
165420f4b53cSBarry Smith   Not Collective
16555b5e7992SMatthew G. Knepley 
165684f0b6dfSMatthew G. Knepley   Input Parameters:
165720f4b53cSBarry Smith + label - the `DMLabel`
165822cd2cdaSVaclav Hapla . start - the first point kept
165922cd2cdaSVaclav Hapla - end   - one more than the last point kept
166084f0b6dfSMatthew G. Knepley 
166184f0b6dfSMatthew G. Knepley   Level: intermediate
166284f0b6dfSMatthew G. Knepley 
166320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
166484f0b6dfSMatthew G. Knepley @*/
1665d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1666d71ae5a4SJacob Faibussowitsch {
1667c58f1c22SToby Isaac   PetscInt v;
1668c58f1c22SToby Isaac 
1669c58f1c22SToby Isaac   PetscFunctionBegin;
1670d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16719f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16729566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
16739566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16749f6c5813SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
16759f6c5813SMatthew G. Knepley     PetscCall(ISGeneralFilter(label->points[v], start, end));
16769f6c5813SMatthew G. Knepley     PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
16779f6c5813SMatthew G. Knepley   }
16789566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
16793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1680c58f1c22SToby Isaac }
1681c58f1c22SToby Isaac 
168284f0b6dfSMatthew G. Knepley /*@
168384f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
168484f0b6dfSMatthew G. Knepley 
168520f4b53cSBarry Smith   Not Collective
16865b5e7992SMatthew G. Knepley 
168784f0b6dfSMatthew G. Knepley   Input Parameters:
168820f4b53cSBarry Smith + label       - the `DMLabel`
168984f0b6dfSMatthew G. Knepley - permutation - the point permutation
169084f0b6dfSMatthew G. Knepley 
169184f0b6dfSMatthew G. Knepley   Output Parameter:
169260225df5SJacob Faibussowitsch . labelNew - the new label containing the permuted points
169384f0b6dfSMatthew G. Knepley 
169484f0b6dfSMatthew G. Knepley   Level: intermediate
169584f0b6dfSMatthew G. Knepley 
169620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
169784f0b6dfSMatthew G. Knepley @*/
1698d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1699d71ae5a4SJacob Faibussowitsch {
1700c58f1c22SToby Isaac   const PetscInt *perm;
1701c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1702c58f1c22SToby Isaac 
1703c58f1c22SToby Isaac   PetscFunctionBegin;
1704d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1705d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
17069f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
17079566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
17089566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
17099566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
17109566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
17119566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1712c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1713c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1714ad8374ffSToby Isaac     const PetscInt *points;
1715ad8374ffSToby Isaac     PetscInt       *pointsNew;
1716c58f1c22SToby Isaac 
17179566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
17189f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(size, &pointsNew));
1719c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1720ad8374ffSToby Isaac       const PetscInt point = points[q];
1721c58f1c22SToby Isaac 
172263a3b9bcSJacob 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);
1723ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1724c58f1c22SToby Isaac     }
17259566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
17269566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
172757508eceSPierre Jolivet     PetscCall(ISDestroy(&(*labelNew)->points[v]));
1728fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
17299566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
17309566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1731fa8e8ae5SToby Isaac     } else {
17329566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1733fa8e8ae5SToby Isaac     }
17349566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1735c58f1c22SToby Isaac   }
17369566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1737c58f1c22SToby Isaac   if (label->bt) {
17389566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
17399566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1740c58f1c22SToby Isaac   }
17413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1742c58f1c22SToby Isaac }
1743c58f1c22SToby Isaac 
17445552b385SBrandon /*@
17455552b385SBrandon   DMLabelPermuteValues - Permute the values in a label
17465552b385SBrandon 
17475552b385SBrandon   Not collective
17485552b385SBrandon 
17495552b385SBrandon   Input Parameters:
17505552b385SBrandon + label       - the `DMLabel`
17515552b385SBrandon - permutation - the value permutation, permutation[old value] = new value
17525552b385SBrandon 
17535552b385SBrandon   Output Parameter:
17545552b385SBrandon . label - the `DMLabel` now with permuted values
17555552b385SBrandon 
17565552b385SBrandon   Note:
17575552b385SBrandon   The modification is done in-place
17585552b385SBrandon 
17595552b385SBrandon   Level: intermediate
17605552b385SBrandon 
17615552b385SBrandon .seealso: `DMLabelRewriteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
17625552b385SBrandon @*/
17635552b385SBrandon PetscErrorCode DMLabelPermuteValues(DMLabel label, IS permutation)
17645552b385SBrandon {
17655552b385SBrandon   PetscInt Nv, Np;
17665552b385SBrandon 
17675552b385SBrandon   PetscFunctionBegin;
17685552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17695552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
17705552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
17715552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
17725552b385SBrandon   PetscCheck(Np == Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " != %" PetscInt_FMT " number of label values", Np, Nv);
17735552b385SBrandon   if (PetscDefined(USE_DEBUG)) {
17745552b385SBrandon     PetscBool flg;
17755552b385SBrandon     PetscCall(ISGetInfo(permutation, IS_PERMUTATION, IS_LOCAL, PETSC_TRUE, &flg));
17765552b385SBrandon     PetscCheck(flg, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "IS is not a permutation");
17775552b385SBrandon   }
17785552b385SBrandon   PetscCall(DMLabelRewriteValues(label, permutation));
17795552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
17805552b385SBrandon }
17815552b385SBrandon 
17825552b385SBrandon /*@
17835552b385SBrandon   DMLabelRewriteValues - Permute the values in a label, but some may be omitted
17845552b385SBrandon 
17855552b385SBrandon   Not collective
17865552b385SBrandon 
17875552b385SBrandon   Input Parameters:
17885552b385SBrandon + label       - the `DMLabel`
17895552b385SBrandon - permutation - the value permutation, permutation[old value] = new value, but some maybe omitted
17905552b385SBrandon 
17915552b385SBrandon   Output Parameter:
17925552b385SBrandon . label - the `DMLabel` now with permuted values
17935552b385SBrandon 
17945552b385SBrandon   Note:
17955552b385SBrandon   The modification is done in-place
17965552b385SBrandon 
17975552b385SBrandon   Level: intermediate
17985552b385SBrandon 
17995552b385SBrandon .seealso: `DMLabelPermuteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
18005552b385SBrandon @*/
18015552b385SBrandon PetscErrorCode DMLabelRewriteValues(DMLabel label, IS permutation)
18025552b385SBrandon {
18035552b385SBrandon   const PetscInt *perm;
18045552b385SBrandon   PetscInt        Nv, Np;
18055552b385SBrandon 
18065552b385SBrandon   PetscFunctionBegin;
18075552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
18085552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
18095552b385SBrandon   PetscCall(DMLabelMakeAllValid_Private(label));
18105552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
18115552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
18125552b385SBrandon   PetscCheck(Np >= Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " < %" PetscInt_FMT " number of label values", Np, Nv);
18135552b385SBrandon   PetscCall(ISGetIndices(permutation, &perm));
18145552b385SBrandon   for (PetscInt v = 0; v < Nv; ++v) label->stratumValues[v] = perm[label->stratumValues[v]];
18155552b385SBrandon   PetscCall(ISRestoreIndices(permutation, &perm));
18165552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
18175552b385SBrandon }
18185552b385SBrandon 
181966976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1820d71ae5a4SJacob Faibussowitsch {
182126c55118SMichael Lange   MPI_Comm     comm;
1822eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
182326c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
182426c55118SMichael Lange   PetscSection rootSection;
182526c55118SMichael Lange   PetscSF      labelSF;
182626c55118SMichael Lange 
182726c55118SMichael Lange   PetscFunctionBegin;
18289566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
18299566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
183026c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
183126c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
18329566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
18339566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
18349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
183526c55118SMichael Lange   if (label) {
183626c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1837ad8374ffSToby Isaac       const PetscInt *points;
1838ad8374ffSToby Isaac 
18399566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
184048a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
18419566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
184226c55118SMichael Lange     }
184326c55118SMichael Lange   }
18449566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
184526c55118SMichael Lange   /* Create a point-wise array of stratum values */
18469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
18479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
18489566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
184926c55118SMichael Lange   if (label) {
185026c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1851ad8374ffSToby Isaac       const PetscInt *points;
1852ad8374ffSToby Isaac 
18539566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
185426c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1855ad8374ffSToby Isaac         const PetscInt p = points[l];
18569566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
185726c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
185826c55118SMichael Lange       }
18599566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
186026c55118SMichael Lange     }
186126c55118SMichael Lange   }
186226c55118SMichael Lange   /* Build SF that maps label points to remote processes */
18639566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
18649566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
18659566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
18669566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
186726c55118SMichael Lange   /* Send the strata for each point over the derived SF */
18689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
18699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
18709566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
18719566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
187226c55118SMichael Lange   /* Clean up */
18739566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18749566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
18759566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18769566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
18773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
187826c55118SMichael Lange }
187926c55118SMichael Lange 
188084f0b6dfSMatthew G. Knepley /*@
188120f4b53cSBarry Smith   DMLabelDistribute - Create a new label pushed forward over the `PetscSF`
188284f0b6dfSMatthew G. Knepley 
188320f4b53cSBarry Smith   Collective
18845b5e7992SMatthew G. Knepley 
188584f0b6dfSMatthew G. Knepley   Input Parameters:
188620f4b53cSBarry Smith + label - the `DMLabel`
188784f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
188884f0b6dfSMatthew G. Knepley 
188984f0b6dfSMatthew G. Knepley   Output Parameter:
189060225df5SJacob Faibussowitsch . labelNew - the new redistributed label
189184f0b6dfSMatthew G. Knepley 
189284f0b6dfSMatthew G. Knepley   Level: intermediate
189384f0b6dfSMatthew G. Knepley 
189420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
189584f0b6dfSMatthew G. Knepley @*/
1896d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1897d71ae5a4SJacob Faibussowitsch {
1898c58f1c22SToby Isaac   MPI_Comm     comm;
189926c55118SMichael Lange   PetscSection leafSection;
190026c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
190126c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1902ad8374ffSToby Isaac   PetscInt   **points;
1903d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1904c58f1c22SToby Isaac   char        *name;
1905835f2295SStefano Zampini   PetscMPIInt  nameSize;
1906e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1907c58f1c22SToby Isaac   size_t       len = 0;
190826c55118SMichael Lange   PetscMPIInt  rank;
1909c58f1c22SToby Isaac 
1910c58f1c22SToby Isaac   PetscFunctionBegin;
1911d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1912f018e600SMatthew G. Knepley   if (label) {
1913f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
19149f6c5813SMatthew G. Knepley     PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
19159566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1916f018e600SMatthew G. Knepley   }
19179566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
19189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1919c58f1c22SToby Isaac   /* Bcast name */
1920dd400576SPatrick Sanan   if (rank == 0) {
19219566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
19229566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1923d67d17b1SMatthew G. Knepley   }
1924835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
1925835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
19269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
19279566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
1928835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
19299566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
19309566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
193177d236dfSMichael Lange   /* Bcast defaultValue */
1932dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
19339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
193426c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
19359566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
19365cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
19379566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
19389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
19399566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
19409566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
19419566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1942ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
19439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
19445cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
19455cbdf6fcSMichael Lange   offset = 0;
19469566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
19479566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
194848a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
19495cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1950231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
19519371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
19529371c9d4SSatish Balay         leafStrata[p] = s;
19539371c9d4SSatish Balay         break;
19549371c9d4SSatish Balay       }
19555cbdf6fcSMichael Lange     }
19565cbdf6fcSMichael Lange   }
1957c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
19589566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
19599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1960c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1963ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1964c58f1c22SToby Isaac   }
19659566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
19669f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
19679f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1968c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
19699566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
1970f4f49eeaSPierre Jolivet     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &points[s]));
1971c58f1c22SToby Isaac   }
1972c58f1c22SToby Isaac   /* Insert points into new strata */
19739566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
19749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1975c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1978c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1979c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1980ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1981c58f1c22SToby Isaac     }
1982c58f1c22SToby Isaac   }
1983ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1984f4f49eeaSPierre Jolivet     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &points[s][0], PETSC_OWN_POINTER, &((*labelNew)->points[s])));
19859566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1986ad8374ffSToby Isaac   }
19879566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
19889566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
19899566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
19909566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
19919566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
19923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1993c58f1c22SToby Isaac }
1994c58f1c22SToby Isaac 
19957937d9ceSMichael Lange /*@
19967937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
19977937d9ceSMichael Lange 
199820f4b53cSBarry Smith   Collective
19995b5e7992SMatthew G. Knepley 
20007937d9ceSMichael Lange   Input Parameters:
200120f4b53cSBarry Smith + label - the `DMLabel`
200220f4b53cSBarry Smith - sf    - the `PetscSF` communication map
20037937d9ceSMichael Lange 
20042fe279fdSBarry Smith   Output Parameter:
200520f4b53cSBarry Smith . labelNew - the new `DMLabel` with localised leaf values
20067937d9ceSMichael Lange 
20077937d9ceSMichael Lange   Level: developer
20087937d9ceSMichael Lange 
200920f4b53cSBarry Smith   Note:
201020f4b53cSBarry Smith   This is the inverse operation to `DMLabelDistribute()`.
20117937d9ceSMichael Lange 
201220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
20137937d9ceSMichael Lange @*/
2014d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
2015d71ae5a4SJacob Faibussowitsch {
20167937d9ceSMichael Lange   MPI_Comm        comm;
20177937d9ceSMichael Lange   PetscSection    rootSection;
20187937d9ceSMichael Lange   PetscSF         sfLabel;
20197937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
20207937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
20217937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
20227937d9ceSMichael Lange   PetscInt       *rootStrata;
2023d67d17b1SMatthew G. Knepley   const char     *lname;
20247937d9ceSMichael Lange   char           *name;
2025835f2295SStefano Zampini   PetscMPIInt     nameSize;
20267937d9ceSMichael Lange   size_t          len = 0;
20279852e123SBarry Smith   PetscMPIInt     rank, size;
20287937d9ceSMichael Lange 
20297937d9ceSMichael Lange   PetscFunctionBegin;
2030d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2031d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
20329f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
20339566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
20349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
20359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
20367937d9ceSMichael Lange   /* Bcast name */
2037dd400576SPatrick Sanan   if (rank == 0) {
20389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
20399566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
2040d67d17b1SMatthew G. Knepley   }
2041835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
2042835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
20439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
20449566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
2045835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
20469566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
20479566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
20487937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
20497937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
20507937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
20519566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
20529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
2053dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
20547937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
20558212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
20568212dd46SStefano Zampini 
20578212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
20588212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
20597937d9ceSMichael Lange   }
20609566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
20619566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
20627937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
20639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
20646497c311SBarry Smith   PetscCall(PetscSFGatherBegin(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20656497c311SBarry Smith   PetscCall(PetscSFGatherEnd(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20669566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
20679566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
20687937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
20699566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
20707937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
20717937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
20727937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
20739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
20749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
20759566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
20767937d9ceSMichael Lange     }
20777937d9ceSMichael Lange     idx += rootDegree[p];
20787937d9ceSMichael Lange   }
20799566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
20809566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
20819566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
20829566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
20833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20847937d9ceSMichael Lange }
20857937d9ceSMichael Lange 
2086d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
2087d71ae5a4SJacob Faibussowitsch {
2088d42890abSMatthew G. Knepley   const PetscInt *degree;
2089d42890abSMatthew G. Knepley   const PetscInt *points;
2090d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2091d42890abSMatthew G. Knepley 
2092d42890abSMatthew G. Knepley   PetscFunctionBegin;
2093d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2094d42890abSMatthew G. Knepley   /* Add in leaves */
2095d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2096d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2097d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
2098d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
2099d42890abSMatthew G. Knepley   }
2100d42890abSMatthew G. Knepley   /* Add in shared roots */
2101d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2102d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2103d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2104d42890abSMatthew G. Knepley     if (degree[r]) {
2105d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
2106d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
2107d42890abSMatthew G. Knepley     }
2108d42890abSMatthew G. Knepley   }
21093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2110d42890abSMatthew G. Knepley }
2111d42890abSMatthew G. Knepley 
2112*2a8381b2SBarry Smith static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), PetscCtx ctx)
2113d71ae5a4SJacob Faibussowitsch {
2114d42890abSMatthew G. Knepley   const PetscInt *degree;
2115d42890abSMatthew G. Knepley   const PetscInt *points;
2116d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2117d42890abSMatthew G. Knepley 
2118d42890abSMatthew G. Knepley   PetscFunctionBegin;
2119d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2120d42890abSMatthew G. Knepley   /* Read out leaves */
2121d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2122d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2123d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
2124d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
2125d42890abSMatthew G. Knepley 
2126d42890abSMatthew G. Knepley     if (cval != defVal) {
2127d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
2128d42890abSMatthew G. Knepley       if (val == defVal) {
2129d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
213048a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
2131d42890abSMatthew G. Knepley       }
2132d42890abSMatthew G. Knepley     }
2133d42890abSMatthew G. Knepley   }
2134d42890abSMatthew G. Knepley   /* Read out shared roots */
2135d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2136d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2137d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2138d42890abSMatthew G. Knepley     if (degree[r]) {
2139d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
2140d42890abSMatthew G. Knepley 
2141d42890abSMatthew G. Knepley       if (cval != defVal) {
2142d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
2143d42890abSMatthew G. Knepley         if (val == defVal) {
2144d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
214548a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2146d42890abSMatthew G. Knepley         }
2147d42890abSMatthew G. Knepley       }
2148d42890abSMatthew G. Knepley     }
2149d42890abSMatthew G. Knepley   }
21503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2151d42890abSMatthew G. Knepley }
2152d42890abSMatthew G. Knepley 
2153d42890abSMatthew G. Knepley /*@
2154d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
2155d42890abSMatthew G. Knepley 
215620f4b53cSBarry Smith   Collective
2157d42890abSMatthew G. Knepley 
2158d42890abSMatthew G. Knepley   Input Parameters:
215920f4b53cSBarry Smith + label - The `DMLabel` to propagate across processes
216020f4b53cSBarry Smith - sf    - The `PetscSF` describing parallel layout of the label points
2161d42890abSMatthew G. Knepley 
2162d42890abSMatthew G. Knepley   Level: intermediate
2163d42890abSMatthew G. Knepley 
216420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2165d42890abSMatthew G. Knepley @*/
2166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2167d71ae5a4SJacob Faibussowitsch {
2168d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
2169d42890abSMatthew G. Knepley   PetscMPIInt size;
2170d42890abSMatthew G. Knepley 
2171d42890abSMatthew G. Knepley   PetscFunctionBegin;
21729f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2173d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2174d42890abSMatthew G. Knepley   if (size > 1) {
2175d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
2176d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2177d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2178d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2179d42890abSMatthew G. Knepley   }
21803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2181d42890abSMatthew G. Knepley }
2182d42890abSMatthew G. Knepley 
2183d42890abSMatthew G. Knepley /*@
2184d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
2185d42890abSMatthew G. Knepley 
218620f4b53cSBarry Smith   Collective
2187d42890abSMatthew G. Knepley 
2188d42890abSMatthew G. Knepley   Input Parameters:
218920f4b53cSBarry Smith + label   - The `DMLabel` to propagate across processes
219060225df5SJacob Faibussowitsch - pointSF - The `PetscSF` describing parallel layout of the label points
2191d42890abSMatthew G. Knepley 
2192d42890abSMatthew G. Knepley   Level: intermediate
2193d42890abSMatthew G. Knepley 
219420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2195d42890abSMatthew G. Knepley @*/
2196d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2197d71ae5a4SJacob Faibussowitsch {
2198d42890abSMatthew G. Knepley   PetscFunctionBegin;
21999f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2200d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
2201d42890abSMatthew G. Knepley   label->propArray = NULL;
22023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2203d42890abSMatthew G. Knepley }
2204d42890abSMatthew G. Knepley 
2205d42890abSMatthew G. Knepley /*@C
2206d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2207d42890abSMatthew G. Knepley 
220820f4b53cSBarry Smith   Collective
2209d42890abSMatthew G. Knepley 
2210d42890abSMatthew G. Knepley   Input Parameters:
221120f4b53cSBarry Smith + label     - The `DMLabel` to propagate across processes
2212a4e35b19SJacob Faibussowitsch . pointSF   - The `PetscSF` describing parallel layout of the label points
221320f4b53cSBarry Smith . markPoint - An optional callback that is called when a point is marked, or `NULL`
221420f4b53cSBarry Smith - ctx       - An optional user context for the callback, or `NULL`
2215d42890abSMatthew G. Knepley 
221620f4b53cSBarry Smith   Calling sequence of `markPoint`:
221720f4b53cSBarry Smith + label - The `DMLabel`
2218d42890abSMatthew G. Knepley . p     - The point being marked
2219a4e35b19SJacob Faibussowitsch . val   - The label value for `p`
2220d42890abSMatthew G. Knepley - ctx   - An optional user context
2221d42890abSMatthew G. Knepley 
2222d42890abSMatthew G. Knepley   Level: intermediate
2223d42890abSMatthew G. Knepley 
222420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2225d42890abSMatthew G. Knepley @*/
2226*2a8381b2SBarry Smith PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel label, PetscInt p, PetscInt val, PetscCtx ctx), PetscCtx ctx)
2227d71ae5a4SJacob Faibussowitsch {
2228c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2229d42890abSMatthew G. Knepley   PetscMPIInt size;
2230d42890abSMatthew G. Knepley 
2231d42890abSMatthew G. Knepley   PetscFunctionBegin;
22329f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2233d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2234c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2235c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2236d42890abSMatthew G. Knepley     /* Communicate marked edges
2237d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2238d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2239d42890abSMatthew G. Knepley 
2240d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2241d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2242d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2243d42890abSMatthew G. Knepley 
2244d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2245d42890abSMatthew 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
2246d42890abSMatthew G. Knepley        edge to the queue.
2247d42890abSMatthew G. Knepley     */
2248d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2249d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2250d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2251d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2252d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2253d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2254d42890abSMatthew G. Knepley   }
22553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2256d42890abSMatthew G. Knepley }
2257d42890abSMatthew G. Knepley 
225884f0b6dfSMatthew G. Knepley /*@
225920f4b53cSBarry Smith   DMLabelConvertToSection - Make a `PetscSection`/`IS` pair that encodes the label
226084f0b6dfSMatthew G. Knepley 
226120f4b53cSBarry Smith   Not Collective
22625b5e7992SMatthew G. Knepley 
226384f0b6dfSMatthew G. Knepley   Input Parameter:
226420f4b53cSBarry Smith . label - the `DMLabel`
226584f0b6dfSMatthew G. Knepley 
226684f0b6dfSMatthew G. Knepley   Output Parameters:
226784f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
226820f4b53cSBarry Smith - is      - An `IS` containing all the label points
226984f0b6dfSMatthew G. Knepley 
227084f0b6dfSMatthew G. Knepley   Level: developer
227184f0b6dfSMatthew G. Knepley 
227220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
227384f0b6dfSMatthew G. Knepley @*/
2274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2275d71ae5a4SJacob Faibussowitsch {
2276c58f1c22SToby Isaac   IS              vIS;
2277c58f1c22SToby Isaac   const PetscInt *values;
2278c58f1c22SToby Isaac   PetscInt       *points;
2279c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2280c58f1c22SToby Isaac 
2281c58f1c22SToby Isaac   PetscFunctionBegin;
2282d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
22839566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
22849566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
22859566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
22869371c9d4SSatish Balay   if (nV) {
22879371c9d4SSatish Balay     vS = values[0];
22889371c9d4SSatish Balay     vE = values[0] + 1;
22899371c9d4SSatish Balay   }
2290c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2291c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2292c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2293c58f1c22SToby Isaac   }
22949566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
22959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2296c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2297c58f1c22SToby Isaac     PetscInt n;
2298c58f1c22SToby Isaac 
22999566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
23009566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2301c58f1c22SToby Isaac   }
23029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
23039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
23049566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2305c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2306c58f1c22SToby Isaac     IS              is;
2307c58f1c22SToby Isaac     const PetscInt *spoints;
2308c58f1c22SToby Isaac     PetscInt        dof, off, p;
2309c58f1c22SToby Isaac 
23109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
23119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
23129566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
23139566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2314c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
23159566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
23169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2317c58f1c22SToby Isaac   }
23189566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
23199566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
23209566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
23213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2322c58f1c22SToby Isaac }
2323c58f1c22SToby Isaac 
23249f6c5813SMatthew G. Knepley /*@C
23259f6c5813SMatthew G. Knepley   DMLabelRegister - Adds a new label component implementation
23269f6c5813SMatthew G. Knepley 
23279f6c5813SMatthew G. Knepley   Not Collective
23289f6c5813SMatthew G. Knepley 
23299f6c5813SMatthew G. Knepley   Input Parameters:
23309f6c5813SMatthew G. Knepley + name        - The name of a new user-defined creation routine
23319f6c5813SMatthew G. Knepley - create_func - The creation routine itself
23329f6c5813SMatthew G. Knepley 
23339f6c5813SMatthew G. Knepley   Notes:
23349f6c5813SMatthew G. Knepley   `DMLabelRegister()` may be called multiple times to add several user-defined labels
23359f6c5813SMatthew G. Knepley 
233660225df5SJacob Faibussowitsch   Example Usage:
23379f6c5813SMatthew G. Knepley .vb
23389f6c5813SMatthew G. Knepley   DMLabelRegister("my_label", MyLabelCreate);
23399f6c5813SMatthew G. Knepley .ve
23409f6c5813SMatthew G. Knepley 
23419f6c5813SMatthew G. Knepley   Then, your label type can be chosen with the procedural interface via
23429f6c5813SMatthew G. Knepley .vb
23439f6c5813SMatthew G. Knepley   DMLabelCreate(MPI_Comm, DMLabel *);
23449f6c5813SMatthew G. Knepley   DMLabelSetType(DMLabel, "my_label");
23459f6c5813SMatthew G. Knepley .ve
23469f6c5813SMatthew G. Knepley   or at runtime via the option
23479f6c5813SMatthew G. Knepley .vb
23489f6c5813SMatthew G. Knepley   -dm_label_type my_label
23499f6c5813SMatthew G. Knepley .ve
23509f6c5813SMatthew G. Knepley 
23519f6c5813SMatthew G. Knepley   Level: advanced
23529f6c5813SMatthew G. Knepley 
235360225df5SJacob Faibussowitsch .seealso: `DMLabel`, `DM`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
23549f6c5813SMatthew G. Knepley @*/
23559f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
23569f6c5813SMatthew G. Knepley {
23579f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23589f6c5813SMatthew G. Knepley   PetscCall(DMInitializePackage());
23599f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
23603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23619f6c5813SMatthew G. Knepley }
23629f6c5813SMatthew G. Knepley 
23639f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
23649f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
23659f6c5813SMatthew G. Knepley 
23669f6c5813SMatthew G. Knepley /*@C
23679f6c5813SMatthew G. Knepley   DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
23689f6c5813SMatthew G. Knepley 
23699f6c5813SMatthew G. Knepley   Not Collective
23709f6c5813SMatthew G. Knepley 
23719f6c5813SMatthew G. Knepley   Level: advanced
23729f6c5813SMatthew G. Knepley 
237320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMRegisterAll()`, `DMLabelRegisterDestroy()`
23749f6c5813SMatthew G. Knepley @*/
23759f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterAll(void)
23769f6c5813SMatthew G. Knepley {
23779f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23783ba16761SJacob Faibussowitsch   if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
23799f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_TRUE;
23809f6c5813SMatthew G. Knepley 
23819f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
23829f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
23833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23849f6c5813SMatthew G. Knepley }
23859f6c5813SMatthew G. Knepley 
23869f6c5813SMatthew G. Knepley /*@C
23879f6c5813SMatthew G. Knepley   DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
23889f6c5813SMatthew G. Knepley 
23899f6c5813SMatthew G. Knepley   Level: developer
23909f6c5813SMatthew G. Knepley 
239120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscInitialize()`
23929f6c5813SMatthew G. Knepley @*/
23939f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterDestroy(void)
23949f6c5813SMatthew G. Knepley {
23959f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23969f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListDestroy(&DMLabelList));
23979f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_FALSE;
23983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23999f6c5813SMatthew G. Knepley }
24009f6c5813SMatthew G. Knepley 
2401cc4c1da9SBarry Smith /*@
24029f6c5813SMatthew G. Knepley   DMLabelSetType - Sets the particular implementation for a label.
24039f6c5813SMatthew G. Knepley 
240420f4b53cSBarry Smith   Collective
24059f6c5813SMatthew G. Knepley 
24069f6c5813SMatthew G. Knepley   Input Parameters:
24079f6c5813SMatthew G. Knepley + label  - The label
24089f6c5813SMatthew G. Knepley - method - The name of the label type
24099f6c5813SMatthew G. Knepley 
24109f6c5813SMatthew G. Knepley   Options Database Key:
241120f4b53cSBarry Smith . -dm_label_type <type> - Sets the label type; use -help for a list of available types or see `DMLabelType`
24129f6c5813SMatthew G. Knepley 
24139f6c5813SMatthew G. Knepley   Level: intermediate
24149f6c5813SMatthew G. Knepley 
241520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetType()`, `DMLabelCreate()`
24169f6c5813SMatthew G. Knepley @*/
24179f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
24189f6c5813SMatthew G. Knepley {
24199f6c5813SMatthew G. Knepley   PetscErrorCode (*r)(DMLabel);
24209f6c5813SMatthew G. Knepley   PetscBool match;
24219f6c5813SMatthew G. Knepley 
24229f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24239f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24249f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
24253ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
24269f6c5813SMatthew G. Knepley 
24279f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24289f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
24299f6c5813SMatthew G. Knepley   PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
24309f6c5813SMatthew G. Knepley 
24319f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, destroy);
24329f6c5813SMatthew G. Knepley   PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
24339f6c5813SMatthew G. Knepley   PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
24349f6c5813SMatthew G. Knepley   PetscCall((*r)(label));
24353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24369f6c5813SMatthew G. Knepley }
24379f6c5813SMatthew G. Knepley 
2438cc4c1da9SBarry Smith /*@
24399f6c5813SMatthew G. Knepley   DMLabelGetType - Gets the type name (as a string) from the label.
24409f6c5813SMatthew G. Knepley 
24419f6c5813SMatthew G. Knepley   Not Collective
24429f6c5813SMatthew G. Knepley 
24439f6c5813SMatthew G. Knepley   Input Parameter:
244420f4b53cSBarry Smith . label - The `DMLabel`
24459f6c5813SMatthew G. Knepley 
24469f6c5813SMatthew G. Knepley   Output Parameter:
244720f4b53cSBarry Smith . type - The `DMLabel` type name
24489f6c5813SMatthew G. Knepley 
24499f6c5813SMatthew G. Knepley   Level: intermediate
24509f6c5813SMatthew G. Knepley 
245120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetType()`, `DMLabelCreate()`
24529f6c5813SMatthew G. Knepley @*/
24539f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
24549f6c5813SMatthew G. Knepley {
24559f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24569f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24574f572ea9SToby Isaac   PetscAssertPointer(type, 2);
24589f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24599f6c5813SMatthew G. Knepley   *type = ((PetscObject)label)->type_name;
24603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24619f6c5813SMatthew G. Knepley }
24629f6c5813SMatthew G. Knepley 
24639f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
24649f6c5813SMatthew G. Knepley {
24659f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24669f6c5813SMatthew G. Knepley   label->ops->view         = DMLabelView_Concrete;
24679f6c5813SMatthew G. Knepley   label->ops->setup        = NULL;
24689f6c5813SMatthew G. Knepley   label->ops->duplicate    = DMLabelDuplicate_Concrete;
24699f6c5813SMatthew G. Knepley   label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
24703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24719f6c5813SMatthew G. Knepley }
24729f6c5813SMatthew G. Knepley 
24739f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
24749f6c5813SMatthew G. Knepley {
24759f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24769f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24779f6c5813SMatthew G. Knepley   PetscCall(DMLabelInitialize_Concrete(label));
24783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24799f6c5813SMatthew G. Knepley }
24809f6c5813SMatthew G. Knepley 
248184f0b6dfSMatthew G. Knepley /*@
2482c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
248320f4b53cSBarry Smith   the local section and an `PetscSF` describing the section point overlap.
2484c58f1c22SToby Isaac 
248520f4b53cSBarry Smith   Collective
24865b5e7992SMatthew G. Knepley 
2487c58f1c22SToby Isaac   Input Parameters:
248820f4b53cSBarry Smith + s                  - The `PetscSection` for the local field layout
248920f4b53cSBarry Smith . sf                 - The `PetscSF` describing parallel layout of the section points
249020f4b53cSBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
2491c58f1c22SToby Isaac . label              - The label specifying the points
2492c58f1c22SToby Isaac - labelValue         - The label stratum specifying the points
2493c58f1c22SToby Isaac 
2494c58f1c22SToby Isaac   Output Parameter:
249520f4b53cSBarry Smith . gsection - The `PetscSection` for the global field layout
2496c58f1c22SToby Isaac 
2497c58f1c22SToby Isaac   Level: developer
2498c58f1c22SToby Isaac 
249920f4b53cSBarry Smith   Note:
250020f4b53cSBarry Smith   This gives negative sizes and offsets to points not owned by this process
250120f4b53cSBarry Smith 
250220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionCreate()`
2503c58f1c22SToby Isaac @*/
2504d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2505d71ae5a4SJacob Faibussowitsch {
2506c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2507c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2508c58f1c22SToby Isaac 
2509c58f1c22SToby Isaac   PetscFunctionBegin;
2510d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2511d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2512d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
25139566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
25149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
25159566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
25169566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2517c58f1c22SToby Isaac   if (nroots >= 0) {
251863a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
25199566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2520c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25219566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2522c58f1c22SToby Isaac     } else {
2523c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2524c58f1c22SToby Isaac     }
2525c58f1c22SToby Isaac   }
2526c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2527c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2528c58f1c22SToby Isaac     PetscInt value;
2529c58f1c22SToby Isaac 
25309566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2531c58f1c22SToby Isaac     if (value != labelValue) continue;
25329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
25339566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
25349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
25359566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2536c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2537c58f1c22SToby Isaac   }
25389566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2539c58f1c22SToby Isaac   if (nroots >= 0) {
25409566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25419566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2542c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25439371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25449371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
25459371c9d4SSatish Balay       }
2546c58f1c22SToby Isaac     }
2547c58f1c22SToby Isaac   }
254835cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
2549c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2550c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2551c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2552c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2553c58f1c22SToby Isaac   }
25549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2555c58f1c22SToby Isaac   globalOff -= off;
2556c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2557c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2558c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2559c58f1c22SToby Isaac   }
2560c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2561c58f1c22SToby Isaac   if (nroots >= 0) {
25629566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25639566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2564c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25659371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25669371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
25679371c9d4SSatish Balay       }
2568c58f1c22SToby Isaac     }
2569c58f1c22SToby Isaac   }
25709566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
25719566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
25723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2573c58f1c22SToby Isaac }
2574c58f1c22SToby Isaac 
25759371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
25765fdea053SToby Isaac   DMLabel              label;
25775fdea053SToby Isaac   PetscCopyMode       *modes;
25785fdea053SToby Isaac   PetscInt            *sizes;
25795fdea053SToby Isaac   const PetscInt    ***perms;
25805fdea053SToby Isaac   const PetscScalar ***rots;
25815fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
25825fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
25835fdea053SToby Isaac } PetscSectionSym_Label;
25845fdea053SToby Isaac 
2585d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2586d71ae5a4SJacob Faibussowitsch {
25875fdea053SToby Isaac   PetscInt               i, j;
25885fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
25895fdea053SToby Isaac 
25905fdea053SToby Isaac   PetscFunctionBegin;
25915fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
25925fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
25935fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
25949566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
25959566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
25965fdea053SToby Isaac       }
25975fdea053SToby Isaac       if (sl->perms[i]) {
25985fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
25995fdea053SToby Isaac 
26009566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
26015fdea053SToby Isaac       }
26025fdea053SToby Isaac       if (sl->rots[i]) {
26035fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
26045fdea053SToby Isaac 
26059566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
26065fdea053SToby Isaac       }
26075fdea053SToby Isaac     }
26085fdea053SToby Isaac   }
26099566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
26109566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
26115fdea053SToby Isaac   sl->numStrata = 0;
26123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26135fdea053SToby Isaac }
26145fdea053SToby Isaac 
2615d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2616d71ae5a4SJacob Faibussowitsch {
26175fdea053SToby Isaac   PetscFunctionBegin;
26189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
26199566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
26203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26215fdea053SToby Isaac }
26225fdea053SToby Isaac 
2623d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2624d71ae5a4SJacob Faibussowitsch {
26255fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
26265fdea053SToby Isaac   PetscBool              isAscii;
26275fdea053SToby Isaac   DMLabel                label = sl->label;
2628d67d17b1SMatthew G. Knepley   const char            *name;
26295fdea053SToby Isaac 
26305fdea053SToby Isaac   PetscFunctionBegin;
26319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
26325fdea053SToby Isaac   if (isAscii) {
26335fdea053SToby Isaac     PetscInt          i, j, k;
26345fdea053SToby Isaac     PetscViewerFormat format;
26355fdea053SToby Isaac 
26369566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
26375fdea053SToby Isaac     if (label) {
26389566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
26395fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26409566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
26419566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
26429566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26435fdea053SToby Isaac       } else {
26449566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
26459566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
26465fdea053SToby Isaac       }
26475fdea053SToby Isaac     } else {
26489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
26495fdea053SToby Isaac     }
26509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
26515fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
26525fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
26535fdea053SToby Isaac 
26545fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
265563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
26565fdea053SToby Isaac       } else {
265763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
26589566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
265963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
26605fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26619566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
26625fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
26635fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
266463a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
26655fdea053SToby Isaac             } else {
26665fdea053SToby Isaac               PetscInt tab;
26675fdea053SToby Isaac 
266863a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
26699566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
26709566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
26715fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
26729566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
26739566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
267463a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
26759566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26769566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26775fdea053SToby Isaac               }
26785fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
26799566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
26809566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
26815fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
268263a3b9bcSJacob 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])));
26835fdea053SToby Isaac #else
268463a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
26855fdea053SToby Isaac #endif
26869566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26879566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26885fdea053SToby Isaac               }
26899566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
26905fdea053SToby Isaac             }
26915fdea053SToby Isaac           }
26929566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
26935fdea053SToby Isaac         }
26949566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26955fdea053SToby Isaac       }
26965fdea053SToby Isaac     }
26979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
26985fdea053SToby Isaac   }
26993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27005fdea053SToby Isaac }
27015fdea053SToby Isaac 
27025fdea053SToby Isaac /*@
27035fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
27045fdea053SToby Isaac 
270520f4b53cSBarry Smith   Logically
27065fdea053SToby Isaac 
270760225df5SJacob Faibussowitsch   Input Parameters:
27085fdea053SToby Isaac + sym   - the section symmetries
270920f4b53cSBarry Smith - label - the `DMLabel` describing the types of points
27105fdea053SToby Isaac 
27115fdea053SToby Isaac   Level: developer:
27125fdea053SToby Isaac 
271320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
27145fdea053SToby Isaac @*/
2715d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2716d71ae5a4SJacob Faibussowitsch {
27175fdea053SToby Isaac   PetscSectionSym_Label *sl;
27185fdea053SToby Isaac 
27195fdea053SToby Isaac   PetscFunctionBegin;
27205fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
27215fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
27229566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
27235fdea053SToby Isaac   if (label) {
27245fdea053SToby Isaac     sl->label = label;
27259566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
27269566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
27279566063dSJacob 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));
27289566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
27299566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
27309566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
27319566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
27329566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
27335fdea053SToby Isaac   }
27343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27355fdea053SToby Isaac }
27365fdea053SToby Isaac 
27375fdea053SToby Isaac /*@C
2738b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2739b004864fSMatthew G. Knepley 
274020f4b53cSBarry Smith   Logically Collective
2741b004864fSMatthew G. Knepley 
2742b004864fSMatthew G. Knepley   Input Parameters:
2743b004864fSMatthew G. Knepley + sym     - the section symmetries
2744b004864fSMatthew G. Knepley - stratum - the stratum value in the label that we are assigning symmetries for
2745b004864fSMatthew G. Knepley 
2746b004864fSMatthew G. Knepley   Output Parameters:
274720f4b53cSBarry Smith + size      - the number of dofs for points in the `stratum` of the label
274820f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
274920f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a ppoint in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
275020f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
275120f4b53cSBarry 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
2752b004864fSMatthew G. Knepley 
2753b004864fSMatthew G. Knepley   Level: developer
2754b004864fSMatthew G. Knepley 
275520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2756b004864fSMatthew G. Knepley @*/
2757d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2758d71ae5a4SJacob Faibussowitsch {
2759b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2760b004864fSMatthew G. Knepley   const char            *name;
2761b004864fSMatthew G. Knepley   PetscInt               i;
2762b004864fSMatthew G. Knepley 
2763b004864fSMatthew G. Knepley   PetscFunctionBegin;
2764b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2765b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2766b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2767b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2768b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2769b004864fSMatthew G. Knepley 
2770b004864fSMatthew G. Knepley     if (stratum == value) break;
2771b004864fSMatthew G. Knepley   }
27729566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2773b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
27749371c9d4SSatish Balay   if (size) {
27754f572ea9SToby Isaac     PetscAssertPointer(size, 3);
27769371c9d4SSatish Balay     *size = sl->sizes[i];
27779371c9d4SSatish Balay   }
27789371c9d4SSatish Balay   if (minOrient) {
27794f572ea9SToby Isaac     PetscAssertPointer(minOrient, 4);
27809371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
27819371c9d4SSatish Balay   }
27829371c9d4SSatish Balay   if (maxOrient) {
27834f572ea9SToby Isaac     PetscAssertPointer(maxOrient, 5);
27849371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
27859371c9d4SSatish Balay   }
27869371c9d4SSatish Balay   if (perms) {
27874f572ea9SToby Isaac     PetscAssertPointer(perms, 6);
27888e3a54c0SPierre Jolivet     *perms = PetscSafePointerPlusOffset(sl->perms[i], sl->minMaxOrients[i][0]);
27899371c9d4SSatish Balay   }
27909371c9d4SSatish Balay   if (rots) {
27914f572ea9SToby Isaac     PetscAssertPointer(rots, 7);
27928e3a54c0SPierre Jolivet     *rots = PetscSafePointerPlusOffset(sl->rots[i], sl->minMaxOrients[i][0]);
27939371c9d4SSatish Balay   }
27943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2795b004864fSMatthew G. Knepley }
2796b004864fSMatthew G. Knepley 
2797b004864fSMatthew G. Knepley /*@C
27985fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
27995fdea053SToby Isaac 
280020f4b53cSBarry Smith   Logically
28015fdea053SToby Isaac 
28025fdea053SToby Isaac   Input Parameters:
28035b5e7992SMatthew G. Knepley + sym       - the section symmetries
28045fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
280520f4b53cSBarry Smith . size      - the number of dofs for points in the `stratum` of the label
280620f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
280720f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a point in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
280820f4b53cSBarry Smith . mode      - how `sym` should copy the `perms` and `rots` arrays
280920f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
281020f4b53cSBarry 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
28115fdea053SToby Isaac 
28125fdea053SToby Isaac   Level: developer
28135fdea053SToby Isaac 
281420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
28155fdea053SToby Isaac @*/
2816d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2817d71ae5a4SJacob Faibussowitsch {
28185fdea053SToby Isaac   PetscSectionSym_Label *sl;
2819d67d17b1SMatthew G. Knepley   const char            *name;
2820d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
28215fdea053SToby Isaac 
28225fdea053SToby Isaac   PetscFunctionBegin;
28235fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
28245fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2825b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
28265fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
28275fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
28285fdea053SToby Isaac 
28295fdea053SToby Isaac     if (stratum == value) break;
28305fdea053SToby Isaac   }
28319566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
283263a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
28335fdea053SToby Isaac   sl->sizes[i]            = size;
28345fdea053SToby Isaac   sl->modes[i]            = mode;
28355fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
28365fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
28375fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
28385fdea053SToby Isaac     if (perms) {
28395fdea053SToby Isaac       PetscInt **ownPerms;
28405fdea053SToby Isaac 
28419566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
28425fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28435fdea053SToby Isaac         if (perms[j]) {
28449566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2845ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
28465fdea053SToby Isaac         }
28475fdea053SToby Isaac       }
28485fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
28495fdea053SToby Isaac     }
28505fdea053SToby Isaac     if (rots) {
28515fdea053SToby Isaac       PetscScalar **ownRots;
28525fdea053SToby Isaac 
28539566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
28545fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28555fdea053SToby Isaac         if (rots[j]) {
28569566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2857ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
28585fdea053SToby Isaac         }
28595fdea053SToby Isaac       }
28605fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
28615fdea053SToby Isaac     }
28625fdea053SToby Isaac   } else {
28638e3a54c0SPierre Jolivet     sl->perms[i] = PetscSafePointerPlusOffset(perms, -minOrient);
28648e3a54c0SPierre Jolivet     sl->rots[i]  = PetscSafePointerPlusOffset(rots, -minOrient);
28655fdea053SToby Isaac   }
28663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28675fdea053SToby Isaac }
28685fdea053SToby Isaac 
2869d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2870d71ae5a4SJacob Faibussowitsch {
28715fdea053SToby Isaac   PetscInt               i, j, numStrata;
28725fdea053SToby Isaac   PetscSectionSym_Label *sl;
28735fdea053SToby Isaac   DMLabel                label;
28745fdea053SToby Isaac 
28755fdea053SToby Isaac   PetscFunctionBegin;
28765fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
28775fdea053SToby Isaac   numStrata = sl->numStrata;
28785fdea053SToby Isaac   label     = sl->label;
28795fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
28805fdea053SToby Isaac     PetscInt point = points[2 * i];
28815fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
28825fdea053SToby Isaac 
28835fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
28845fdea053SToby Isaac       if (label->validIS[j]) {
28855fdea053SToby Isaac         PetscInt k;
28865fdea053SToby Isaac 
28872b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(label->points[j], point, &k));
28885fdea053SToby Isaac         if (k >= 0) break;
28895fdea053SToby Isaac       } else {
28905fdea053SToby Isaac         PetscBool has;
28915fdea053SToby Isaac 
28929566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
28935fdea053SToby Isaac         if (has) break;
28945fdea053SToby Isaac       }
28955fdea053SToby Isaac     }
28969371c9d4SSatish 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],
28979371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2898ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2899ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
29005fdea053SToby Isaac   }
29013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29025fdea053SToby Isaac }
29035fdea053SToby Isaac 
2904d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2905d71ae5a4SJacob Faibussowitsch {
2906b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2907b004864fSMatthew G. Knepley   IS                     valIS;
2908b004864fSMatthew G. Knepley   const PetscInt        *values;
2909b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2910b004864fSMatthew G. Knepley 
2911b004864fSMatthew G. Knepley   PetscFunctionBegin;
29129566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
29139566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
29149566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2915b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2916b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2917b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2918b004864fSMatthew G. Knepley     const PetscInt    **perms;
2919b004864fSMatthew G. Knepley     const PetscScalar **rots;
2920b004864fSMatthew G. Knepley 
29219566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
29229566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2923b004864fSMatthew G. Knepley   }
29249566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
29253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2926b004864fSMatthew G. Knepley }
2927b004864fSMatthew G. Knepley 
2928d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2929d71ae5a4SJacob Faibussowitsch {
2930b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2931b004864fSMatthew G. Knepley   DMLabel                dlabel;
2932b004864fSMatthew G. Knepley 
2933b004864fSMatthew G. Knepley   PetscFunctionBegin;
29349566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
29359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
29369566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
29379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
29383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2939b004864fSMatthew G. Knepley }
2940b004864fSMatthew G. Knepley 
2941d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2942d71ae5a4SJacob Faibussowitsch {
29435fdea053SToby Isaac   PetscSectionSym_Label *sl;
29445fdea053SToby Isaac 
29455fdea053SToby Isaac   PetscFunctionBegin;
29464dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
29475fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2948b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2949b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
29505fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
29515fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
29525fdea053SToby Isaac   sym->data            = (void *)sl;
29533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29545fdea053SToby Isaac }
29555fdea053SToby Isaac 
29565fdea053SToby Isaac /*@
29575fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
29585fdea053SToby Isaac 
29595fdea053SToby Isaac   Collective
29605fdea053SToby Isaac 
29615fdea053SToby Isaac   Input Parameters:
29625fdea053SToby Isaac + comm  - the MPI communicator for the new symmetry
29635fdea053SToby Isaac - label - the label defining the strata
29645fdea053SToby Isaac 
29652fe279fdSBarry Smith   Output Parameter:
29665fdea053SToby Isaac . sym - the section symmetries
29675fdea053SToby Isaac 
29685fdea053SToby Isaac   Level: developer
29695fdea053SToby Isaac 
297020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
29715fdea053SToby Isaac @*/
2972d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2973d71ae5a4SJacob Faibussowitsch {
29745fdea053SToby Isaac   PetscFunctionBegin;
29759566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
29769566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
29779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
29789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
29793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29805fdea053SToby Isaac }
2981