xref: /petsc/src/dm/label/dmlabel.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
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 
10c58f1c22SToby Isaac /*@C
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));
37d67d17b1SMatthew G. Knepley 
38c58f1c22SToby Isaac   (*label)->numStrata     = 0;
395aa44df4SToby Isaac   (*label)->defaultValue  = -1;
40c58f1c22SToby Isaac   (*label)->stratumValues = NULL;
41ad8374ffSToby Isaac   (*label)->validIS       = NULL;
42c58f1c22SToby Isaac   (*label)->stratumSizes  = NULL;
43c58f1c22SToby Isaac   (*label)->points        = NULL;
44c58f1c22SToby Isaac   (*label)->ht            = NULL;
45c58f1c22SToby Isaac   (*label)->pStart        = -1;
46c58f1c22SToby Isaac   (*label)->pEnd          = -1;
47c58f1c22SToby Isaac   (*label)->bt            = NULL;
489566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
499566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*label, name));
509f6c5813SMatthew G. Knepley   PetscCall(DMLabelSetType(*label, DMLABELCONCRETE));
513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
529f6c5813SMatthew G. Knepley }
539f6c5813SMatthew G. Knepley 
549f6c5813SMatthew G. Knepley /*@C
559f6c5813SMatthew G. Knepley   DMLabelSetUp - SetUp a `DMLabel` object
569f6c5813SMatthew G. Knepley 
579f6c5813SMatthew G. Knepley   Collective
589f6c5813SMatthew G. Knepley 
5960225df5SJacob Faibussowitsch   Input Parameters:
609f6c5813SMatthew G. Knepley . label - The `DMLabel`
619f6c5813SMatthew G. Knepley 
629f6c5813SMatthew G. Knepley   Level: intermediate
639f6c5813SMatthew G. Knepley 
6420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
659f6c5813SMatthew G. Knepley @*/
669f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetUp(DMLabel label)
679f6c5813SMatthew G. Knepley {
689f6c5813SMatthew G. Knepley   PetscFunctionBegin;
699f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
709f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, setup);
713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72c58f1c22SToby Isaac }
73c58f1c22SToby Isaac 
74c58f1c22SToby Isaac /*
75c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
76c58f1c22SToby Isaac 
775b5e7992SMatthew G. Knepley   Not collective
785b5e7992SMatthew G. Knepley 
79c58f1c22SToby Isaac   Input parameter:
8020f4b53cSBarry Smith + label - The `DMLabel`
81c58f1c22SToby Isaac - v - The stratum value
82c58f1c22SToby Isaac 
83c58f1c22SToby Isaac   Output parameter:
8420f4b53cSBarry Smith . label - The `DMLabel` with stratum in sorted list format
85c58f1c22SToby Isaac 
86c58f1c22SToby Isaac   Level: developer
87c58f1c22SToby Isaac 
8820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
89c58f1c22SToby Isaac */
90d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
91d71ae5a4SJacob Faibussowitsch {
92277ea44aSLisandro Dalcin   IS       is;
93b9907514SLisandro Dalcin   PetscInt off = 0, *pointArray, p;
94c58f1c22SToby Isaac 
95c58f1c22SToby Isaac   PetscFunctionBegin;
964d86920dSPierre Jolivet   if ((PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) || label->readonly) PetscFunctionReturn(PETSC_SUCCESS);
971dca8a05SBarry 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);
989566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
1009566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
1019566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
1029566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
103c58f1c22SToby Isaac   if (label->bt) {
104c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
105ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
10663a3b9bcSJacob 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);
1079566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
108c58f1c22SToby Isaac     }
109c58f1c22SToby Isaac   }
110ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v] - 1] == pointArray[0] + label->stratumSizes[v] - 1) {
1119566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
1129566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
113ba2698f1SMatthew G. Knepley   } else {
1149566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
115ba2698f1SMatthew G. Knepley   }
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));
175*f4f49eeaSPierre 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 {
4499f6c5813SMatthew G. Knepley   PetscBool iascii;
4509f6c5813SMatthew G. Knepley 
4519f6c5813SMatthew G. Knepley   PetscFunctionBegin;
4529f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4539f6c5813SMatthew G. Knepley   if (iascii) PetscCall(DMLabelView_Concrete_Ascii(label, viewer));
4543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4559f6c5813SMatthew G. Knepley }
4569f6c5813SMatthew G. Knepley 
457c58f1c22SToby Isaac /*@C
458c58f1c22SToby Isaac   DMLabelView - View the label
459c58f1c22SToby Isaac 
46020f4b53cSBarry Smith   Collective
4615b5e7992SMatthew G. Knepley 
462c58f1c22SToby Isaac   Input Parameters:
46320f4b53cSBarry Smith + label  - The `DMLabel`
46420f4b53cSBarry Smith - viewer - The `PetscViewer`
465c58f1c22SToby Isaac 
466c58f1c22SToby Isaac   Level: intermediate
467c58f1c22SToby Isaac 
46820f4b53cSBarry Smith .seealso: `DMLabel`, `PetscViewer`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
469c58f1c22SToby Isaac @*/
470d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
471d71ae5a4SJacob Faibussowitsch {
472c58f1c22SToby Isaac   PetscFunctionBegin;
473d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4749566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
475c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4769f6c5813SMatthew G. Knepley   PetscCall(DMLabelMakeAllValid_Private(label));
4779f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, view, viewer);
4783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
479c58f1c22SToby Isaac }
480c58f1c22SToby Isaac 
48184f0b6dfSMatthew G. Knepley /*@
48220f4b53cSBarry Smith   DMLabelReset - Destroys internal data structures in a `DMLabel`
483d67d17b1SMatthew G. Knepley 
48420f4b53cSBarry Smith   Not Collective
4855b5e7992SMatthew G. Knepley 
486d67d17b1SMatthew G. Knepley   Input Parameter:
48720f4b53cSBarry Smith . label - The `DMLabel`
488d67d17b1SMatthew G. Knepley 
489d67d17b1SMatthew G. Knepley   Level: beginner
490d67d17b1SMatthew G. Knepley 
49120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`, `DMLabelCreate()`
492d67d17b1SMatthew G. Knepley @*/
493d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelReset(DMLabel label)
494d71ae5a4SJacob Faibussowitsch {
495d67d17b1SMatthew G. Knepley   PetscInt v;
496d67d17b1SMatthew G. Knepley 
497d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
498d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
499d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
5009f6c5813SMatthew G. Knepley     if (label->ht[v]) PetscCall(PetscHSetIDestroy(&label->ht[v]));
5019566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
502d67d17b1SMatthew G. Knepley   }
503b9907514SLisandro Dalcin   label->numStrata = 0;
5049566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
5059566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
5069566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
5079566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
5089566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
5099566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
510b9907514SLisandro Dalcin   label->pStart = -1;
511b9907514SLisandro Dalcin   label->pEnd   = -1;
5129566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
5133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
514d67d17b1SMatthew G. Knepley }
515d67d17b1SMatthew G. Knepley 
516d67d17b1SMatthew G. Knepley /*@
51720f4b53cSBarry Smith   DMLabelDestroy - Destroys a `DMLabel`
51884f0b6dfSMatthew G. Knepley 
51920f4b53cSBarry Smith   Collective
5205b5e7992SMatthew G. Knepley 
52184f0b6dfSMatthew G. Knepley   Input Parameter:
52220f4b53cSBarry Smith . label - The `DMLabel`
52384f0b6dfSMatthew G. Knepley 
52484f0b6dfSMatthew G. Knepley   Level: beginner
52584f0b6dfSMatthew G. Knepley 
52620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelReset()`, `DMLabelCreate()`
52784f0b6dfSMatthew G. Knepley @*/
528d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
529d71ae5a4SJacob Faibussowitsch {
530c58f1c22SToby Isaac   PetscFunctionBegin;
5313ba16761SJacob Faibussowitsch   if (!*label) PetscFunctionReturn(PETSC_SUCCESS);
532*f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 1);
533*f4f49eeaSPierre Jolivet   if (--((PetscObject)*label)->refct > 0) {
5349371c9d4SSatish Balay     *label = NULL;
5353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5369371c9d4SSatish Balay   }
5379566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5389566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5399566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
5403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
541c58f1c22SToby Isaac }
542c58f1c22SToby Isaac 
54366976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDuplicate_Concrete(DMLabel label, DMLabel *labelnew)
5449f6c5813SMatthew G. Knepley {
5459f6c5813SMatthew G. Knepley   PetscFunctionBegin;
5469f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
5479f6c5813SMatthew G. Knepley     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
548*f4f49eeaSPierre Jolivet     PetscCall(PetscObjectReference((PetscObject)label->points[v]));
5499f6c5813SMatthew G. Knepley     (*labelnew)->points[v] = label->points[v];
5509f6c5813SMatthew G. Knepley   }
5519f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5529f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
5533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5549f6c5813SMatthew G. Knepley }
5559f6c5813SMatthew G. Knepley 
55684f0b6dfSMatthew G. Knepley /*@
55720f4b53cSBarry Smith   DMLabelDuplicate - Duplicates a `DMLabel`
55884f0b6dfSMatthew G. Knepley 
55920f4b53cSBarry Smith   Collective
5605b5e7992SMatthew G. Knepley 
56184f0b6dfSMatthew G. Knepley   Input Parameter:
56220f4b53cSBarry Smith . label - The `DMLabel`
56384f0b6dfSMatthew G. Knepley 
56484f0b6dfSMatthew G. Knepley   Output Parameter:
56520f4b53cSBarry Smith . labelnew - new label
56684f0b6dfSMatthew G. Knepley 
56784f0b6dfSMatthew G. Knepley   Level: intermediate
56884f0b6dfSMatthew G. Knepley 
56920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
57084f0b6dfSMatthew G. Knepley @*/
571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
572d71ae5a4SJacob Faibussowitsch {
573d67d17b1SMatthew G. Knepley   const char *name;
574c58f1c22SToby Isaac 
575c58f1c22SToby Isaac   PetscFunctionBegin;
576d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5779566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
5799566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
580c58f1c22SToby Isaac 
581c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5825aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5838dcf10e8SMatthew G. Knepley   (*labelnew)->readonly     = label->readonly;
5849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5869f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->ht));
5879f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->points));
5889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
5899f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
590c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
591c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
592b9907514SLisandro Dalcin     (*labelnew)->validIS[v]       = PETSC_TRUE;
593c58f1c22SToby Isaac   }
594c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
595c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
596c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
5979f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, duplicate, labelnew);
5983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
599c58f1c22SToby Isaac }
600c58f1c22SToby Isaac 
601609dae6eSVaclav Hapla /*@C
60220f4b53cSBarry Smith   DMLabelCompare - Compare two `DMLabel` objects
603609dae6eSVaclav Hapla 
60420f4b53cSBarry Smith   Collective; No Fortran Support
605609dae6eSVaclav Hapla 
606609dae6eSVaclav Hapla   Input Parameters:
607f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
60820f4b53cSBarry Smith . l0   - First `DMLabel`
60920f4b53cSBarry Smith - l1   - Second `DMLabel`
610609dae6eSVaclav Hapla 
611a4e35b19SJacob Faibussowitsch   Output Parameters:
6125efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
6135efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
614609dae6eSVaclav Hapla 
615609dae6eSVaclav Hapla   Level: intermediate
616609dae6eSVaclav Hapla 
617609dae6eSVaclav Hapla   Notes:
6185efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
61920f4b53cSBarry Smith   If it is passed as `NULL` and difference is found, an error is thrown on all processes.
62020f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
621609dae6eSVaclav Hapla 
6225efe38ccSVaclav Hapla   The output message is set independently on each rank.
62320f4b53cSBarry Smith   It is set to `NULL` if no difference was found on the current rank. It must be freed by user.
62420f4b53cSBarry Smith   If message is passed as `NULL` and difference is found, the difference description is printed to stderr in synchronized manner.
62520f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
626609dae6eSVaclav Hapla 
627609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
628609dae6eSVaclav Hapla 
62920f4b53cSBarry Smith   The communicator needs to be specified because currently `DMLabel` can live on `PETSC_COMM_SELF` even if the underlying `DM` is parallel.
6305efe38ccSVaclav Hapla 
63120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
632609dae6eSVaclav Hapla @*/
633d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
634d71ae5a4SJacob Faibussowitsch {
635609dae6eSVaclav Hapla   const char *name0, *name1;
636609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6375efe38ccSVaclav Hapla   PetscBool   eq;
6385efe38ccSVaclav Hapla   PetscMPIInt rank;
639609dae6eSVaclav Hapla 
640609dae6eSVaclav Hapla   PetscFunctionBegin;
6415efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6425efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6434f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 4);
6444f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 5);
6459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6469566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6479566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
648609dae6eSVaclav Hapla   {
649609dae6eSVaclav Hapla     PetscInt v0, v1;
650609dae6eSVaclav Hapla 
6519566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6529566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6535efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
65448a46eb9SPierre 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));
655712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6565efe38ccSVaclav Hapla     if (!eq) goto finish;
657609dae6eSVaclav Hapla   }
658609dae6eSVaclav Hapla   {
659609dae6eSVaclav Hapla     IS is0, is1;
660609dae6eSVaclav Hapla 
6619566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6629566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6639566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6649566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6659566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
66648a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
667712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6685efe38ccSVaclav Hapla     if (!eq) goto finish;
669609dae6eSVaclav Hapla   }
670609dae6eSVaclav Hapla   {
671609dae6eSVaclav Hapla     PetscInt i, nValues;
672609dae6eSVaclav Hapla 
6739566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
674609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
675609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
676609dae6eSVaclav Hapla       PetscInt       n;
677609dae6eSVaclav Hapla       IS             is0, is1;
678609dae6eSVaclav Hapla 
6799566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
680609dae6eSVaclav Hapla       if (!n) continue;
6819566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6829566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6839566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6849566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6859566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6865efe38ccSVaclav Hapla       if (!eq) {
68763a3b9bcSJacob 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));
6885efe38ccSVaclav Hapla         break;
689609dae6eSVaclav Hapla       }
690609dae6eSVaclav Hapla     }
691712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
692609dae6eSVaclav Hapla   }
693609dae6eSVaclav Hapla finish:
6945efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
695609dae6eSVaclav Hapla   if (message) {
696609dae6eSVaclav Hapla     *message = NULL;
69748a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
6985efe38ccSVaclav Hapla   } else {
69948a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
7009566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
7015efe38ccSVaclav Hapla   }
7025efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
7035efe38ccSVaclav Hapla   if (equal) *equal = eq;
70463a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
7053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
706609dae6eSVaclav Hapla }
707609dae6eSVaclav Hapla 
708c6a43d28SMatthew G. Knepley /*@
709c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
710c6a43d28SMatthew G. Knepley 
71120f4b53cSBarry Smith   Not Collective
7125b5e7992SMatthew G. Knepley 
713c6a43d28SMatthew G. Knepley   Input Parameter:
71420f4b53cSBarry Smith . label - The `DMLabel`
715c6a43d28SMatthew G. Knepley 
716c6a43d28SMatthew G. Knepley   Level: intermediate
717c6a43d28SMatthew G. Knepley 
71820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
719c6a43d28SMatthew G. Knepley @*/
720d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
721d71ae5a4SJacob Faibussowitsch {
722c6a43d28SMatthew G. Knepley   PetscInt pStart = PETSC_MAX_INT, pEnd = -1, v;
723c6a43d28SMatthew G. Knepley 
724c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
725c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7269566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
727c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
728c6a43d28SMatthew G. Knepley     const PetscInt *points;
729c6a43d28SMatthew G. Knepley     PetscInt        i;
730c6a43d28SMatthew G. Knepley 
7319566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
732c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
733c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
734c6a43d28SMatthew G. Knepley 
735c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
736c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
737c6a43d28SMatthew G. Knepley     }
7389566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
739c6a43d28SMatthew G. Knepley   }
740c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
741c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7429566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
7433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
744c6a43d28SMatthew G. Knepley }
745c6a43d28SMatthew G. Knepley 
746c6a43d28SMatthew G. Knepley /*@
747c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
748c6a43d28SMatthew G. Knepley 
74920f4b53cSBarry Smith   Not Collective
7505b5e7992SMatthew G. Knepley 
751c6a43d28SMatthew G. Knepley   Input Parameters:
75220f4b53cSBarry Smith + label  - The `DMLabel`
753c6a43d28SMatthew G. Knepley . pStart - The smallest point
754c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
755c6a43d28SMatthew G. Knepley 
756c6a43d28SMatthew G. Knepley   Level: intermediate
757c6a43d28SMatthew G. Knepley 
75820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
759c6a43d28SMatthew G. Knepley @*/
760d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
761d71ae5a4SJacob Faibussowitsch {
762c58f1c22SToby Isaac   PetscInt v;
763c58f1c22SToby Isaac 
764c58f1c22SToby Isaac   PetscFunctionBegin;
765d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7669566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7679566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
768c58f1c22SToby Isaac   label->pStart = pStart;
769c58f1c22SToby Isaac   label->pEnd   = pEnd;
770c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7719566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
772c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
7739f6c5813SMatthew G. Knepley     IS              pointIS;
774ad8374ffSToby Isaac     const PetscInt *points;
775c58f1c22SToby Isaac     PetscInt        i;
776c58f1c22SToby Isaac 
7779f6c5813SMatthew G. Knepley     PetscUseTypeMethod(label, getstratumis, v, &pointIS);
7789f6c5813SMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
779c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
780ad8374ffSToby Isaac       const PetscInt point = points[i];
781c58f1c22SToby Isaac 
7829f6c5813SMatthew 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);
7839566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
784c58f1c22SToby Isaac     }
7859566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
7869f6c5813SMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
787c58f1c22SToby Isaac   }
7883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
789c58f1c22SToby Isaac }
790c58f1c22SToby Isaac 
791c6a43d28SMatthew G. Knepley /*@
792c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
793c6a43d28SMatthew G. Knepley 
79420f4b53cSBarry Smith   Not Collective
7955b5e7992SMatthew G. Knepley 
796c6a43d28SMatthew G. Knepley   Input Parameter:
79720f4b53cSBarry Smith . label - the `DMLabel`
798c6a43d28SMatthew G. Knepley 
799c6a43d28SMatthew G. Knepley   Level: intermediate
800c6a43d28SMatthew G. Knepley 
80120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
802c6a43d28SMatthew G. Knepley @*/
803d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
804d71ae5a4SJacob Faibussowitsch {
805c58f1c22SToby Isaac   PetscFunctionBegin;
806d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
807c58f1c22SToby Isaac   label->pStart = -1;
808c58f1c22SToby Isaac   label->pEnd   = -1;
8099566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
8103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
811c58f1c22SToby Isaac }
812c58f1c22SToby Isaac 
813c58f1c22SToby Isaac /*@
814c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
815c6a43d28SMatthew G. Knepley 
81620f4b53cSBarry Smith   Not Collective
8175b5e7992SMatthew G. Knepley 
818c6a43d28SMatthew G. Knepley   Input Parameter:
81920f4b53cSBarry Smith . label - the `DMLabel`
820c6a43d28SMatthew G. Knepley 
821c6a43d28SMatthew G. Knepley   Output Parameters:
822c6a43d28SMatthew G. Knepley + pStart - The smallest point
823c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
824c6a43d28SMatthew G. Knepley 
825c6a43d28SMatthew G. Knepley   Level: intermediate
826c6a43d28SMatthew G. Knepley 
82720f4b53cSBarry Smith   Note:
82820f4b53cSBarry Smith   This will compute an index for the label if one does not exist.
82920f4b53cSBarry Smith 
83020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
831c6a43d28SMatthew G. Knepley @*/
832d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
833d71ae5a4SJacob Faibussowitsch {
834c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
835c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8369566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
837c6a43d28SMatthew G. Knepley   if (pStart) {
8384f572ea9SToby Isaac     PetscAssertPointer(pStart, 2);
839c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
840c6a43d28SMatthew G. Knepley   }
841c6a43d28SMatthew G. Knepley   if (pEnd) {
8424f572ea9SToby Isaac     PetscAssertPointer(pEnd, 3);
843c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
844c6a43d28SMatthew G. Knepley   }
8453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
846c6a43d28SMatthew G. Knepley }
847c6a43d28SMatthew G. Knepley 
848c6a43d28SMatthew G. Knepley /*@
849c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
850c58f1c22SToby Isaac 
85120f4b53cSBarry Smith   Not Collective
8525b5e7992SMatthew G. Knepley 
853c58f1c22SToby Isaac   Input Parameters:
85420f4b53cSBarry Smith + label - the `DMLabel`
855c58f1c22SToby Isaac - value - the value
856c58f1c22SToby Isaac 
857c58f1c22SToby Isaac   Output Parameter:
858c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
859c58f1c22SToby Isaac 
860c58f1c22SToby Isaac   Level: developer
861c58f1c22SToby Isaac 
86220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
863c58f1c22SToby Isaac @*/
864d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
865d71ae5a4SJacob Faibussowitsch {
866c58f1c22SToby Isaac   PetscInt v;
867c58f1c22SToby Isaac 
868c58f1c22SToby Isaac   PetscFunctionBegin;
869d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8704f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
8719566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8720c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
8733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
874c58f1c22SToby Isaac }
875c58f1c22SToby Isaac 
876c58f1c22SToby Isaac /*@
877c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
878c58f1c22SToby Isaac 
87920f4b53cSBarry Smith   Not Collective
8805b5e7992SMatthew G. Knepley 
881c58f1c22SToby Isaac   Input Parameters:
88220f4b53cSBarry Smith + label - the `DMLabel`
883c58f1c22SToby Isaac - point - the point
884c58f1c22SToby Isaac 
885c58f1c22SToby Isaac   Output Parameter:
886c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
887c58f1c22SToby Isaac 
888c58f1c22SToby Isaac   Level: developer
889c58f1c22SToby Isaac 
89020f4b53cSBarry Smith   Note:
89120f4b53cSBarry Smith   The user must call `DMLabelCreateIndex()` before this function.
89220f4b53cSBarry Smith 
89320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
894c58f1c22SToby Isaac @*/
895d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
896d71ae5a4SJacob Faibussowitsch {
897c58f1c22SToby Isaac   PetscFunctionBeginHot;
898d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8994f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
9009566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
90176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
90228b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
90363a3b9bcSJacob 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);
90476bd3646SJed Brown   }
905c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
9063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
907c58f1c22SToby Isaac }
908c58f1c22SToby Isaac 
909c58f1c22SToby Isaac /*@
910c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
911c58f1c22SToby Isaac 
91220f4b53cSBarry Smith   Not Collective
9135b5e7992SMatthew G. Knepley 
914c58f1c22SToby Isaac   Input Parameters:
91520f4b53cSBarry Smith + label - the `DMLabel`
916c58f1c22SToby Isaac . value - the stratum value
917c58f1c22SToby Isaac - point - the point
918c58f1c22SToby Isaac 
919c58f1c22SToby Isaac   Output Parameter:
920c58f1c22SToby Isaac . contains - true if the stratum contains the point
921c58f1c22SToby Isaac 
922c58f1c22SToby Isaac   Level: intermediate
923c58f1c22SToby Isaac 
92420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
925c58f1c22SToby Isaac @*/
926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
927d71ae5a4SJacob Faibussowitsch {
9280c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
929d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9304f572ea9SToby Isaac   PetscAssertPointer(contains, 4);
931cffad2c9SToby Isaac   if (value == label->defaultValue) {
932cffad2c9SToby Isaac     PetscInt pointVal;
9330c3c4a36SLisandro Dalcin 
934cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
935cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
936cffad2c9SToby Isaac   } else {
937cffad2c9SToby Isaac     PetscInt v;
938cffad2c9SToby Isaac 
939cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
940cffad2c9SToby Isaac     if (v >= 0) {
9419f6c5813SMatthew G. Knepley       if (label->validIS[v] || label->readonly) {
9429f6c5813SMatthew G. Knepley         IS       is;
943c58f1c22SToby Isaac         PetscInt i;
944c58f1c22SToby Isaac 
9459f6c5813SMatthew G. Knepley         PetscUseTypeMethod(label, getstratumis, v, &is);
9469f6c5813SMatthew G. Knepley         PetscCall(ISLocate(is, point, &i));
9479f6c5813SMatthew G. Knepley         PetscCall(ISDestroy(&is));
948cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
949c58f1c22SToby Isaac       } else {
950cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
951cffad2c9SToby Isaac       }
952cffad2c9SToby Isaac     } else { // value is not present
953cffad2c9SToby Isaac       *contains = PETSC_FALSE;
954cffad2c9SToby Isaac     }
955c58f1c22SToby Isaac   }
9563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
957c58f1c22SToby Isaac }
958c58f1c22SToby Isaac 
95984f0b6dfSMatthew G. Knepley /*@
96020f4b53cSBarry Smith   DMLabelGetDefaultValue - Get the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9615aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9625aa44df4SToby Isaac 
96320f4b53cSBarry Smith   Not Collective
9645b5e7992SMatthew G. Knepley 
96560225df5SJacob Faibussowitsch   Input Parameter:
96620f4b53cSBarry Smith . label - a `DMLabel` object
9675aa44df4SToby Isaac 
96860225df5SJacob Faibussowitsch   Output Parameter:
9695aa44df4SToby Isaac . defaultValue - the default value
9705aa44df4SToby Isaac 
9715aa44df4SToby Isaac   Level: beginner
9725aa44df4SToby Isaac 
97320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
97484f0b6dfSMatthew G. Knepley @*/
975d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
976d71ae5a4SJacob Faibussowitsch {
9775aa44df4SToby Isaac   PetscFunctionBegin;
978d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9795aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9815aa44df4SToby Isaac }
9825aa44df4SToby Isaac 
98384f0b6dfSMatthew G. Knepley /*@
98420f4b53cSBarry Smith   DMLabelSetDefaultValue - Set the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9855aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9865aa44df4SToby Isaac 
98720f4b53cSBarry Smith   Not Collective
9885b5e7992SMatthew G. Knepley 
98960225df5SJacob Faibussowitsch   Input Parameter:
99020f4b53cSBarry Smith . label - a `DMLabel` object
9915aa44df4SToby Isaac 
99260225df5SJacob Faibussowitsch   Output Parameter:
9935aa44df4SToby Isaac . defaultValue - the default value
9945aa44df4SToby Isaac 
9955aa44df4SToby Isaac   Level: beginner
9965aa44df4SToby Isaac 
99720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
99884f0b6dfSMatthew G. Knepley @*/
999d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1000d71ae5a4SJacob Faibussowitsch {
10015aa44df4SToby Isaac   PetscFunctionBegin;
1002d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10035aa44df4SToby Isaac   label->defaultValue = defaultValue;
10043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10055aa44df4SToby Isaac }
10065aa44df4SToby Isaac 
1007c58f1c22SToby Isaac /*@
100820f4b53cSBarry 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
100920f4b53cSBarry Smith   `DMLabelSetDefaultValue()`)
1010c58f1c22SToby Isaac 
101120f4b53cSBarry Smith   Not Collective
10125b5e7992SMatthew G. Knepley 
1013c58f1c22SToby Isaac   Input Parameters:
101420f4b53cSBarry Smith + label - the `DMLabel`
1015c58f1c22SToby Isaac - point - the point
1016c58f1c22SToby Isaac 
1017c58f1c22SToby Isaac   Output Parameter:
10188e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
1019c58f1c22SToby Isaac 
1020c58f1c22SToby Isaac   Level: intermediate
1021c58f1c22SToby Isaac 
102220f4b53cSBarry Smith   Note:
102320f4b53cSBarry Smith   A label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.
102420f4b53cSBarry Smith   Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
102520f4b53cSBarry Smith 
102620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1027c58f1c22SToby Isaac @*/
1028d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1029d71ae5a4SJacob Faibussowitsch {
1030c58f1c22SToby Isaac   PetscInt v;
1031c58f1c22SToby Isaac 
10320c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
1033d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10344f572ea9SToby Isaac   PetscAssertPointer(value, 3);
10355aa44df4SToby Isaac   *value = label->defaultValue;
1036c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
10379f6c5813SMatthew G. Knepley     if (label->validIS[v] || label->readonly) {
10389f6c5813SMatthew G. Knepley       IS       is;
1039c58f1c22SToby Isaac       PetscInt i;
1040c58f1c22SToby Isaac 
10419f6c5813SMatthew G. Knepley       PetscUseTypeMethod(label, getstratumis, v, &is);
10429566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
10439f6c5813SMatthew G. Knepley       PetscCall(ISDestroy(&is));
1044c58f1c22SToby Isaac       if (i >= 0) {
1045c58f1c22SToby Isaac         *value = label->stratumValues[v];
1046c58f1c22SToby Isaac         break;
1047c58f1c22SToby Isaac       }
1048c58f1c22SToby Isaac     } else {
1049c58f1c22SToby Isaac       PetscBool has;
1050c58f1c22SToby Isaac 
10519566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1052c58f1c22SToby Isaac       if (has) {
1053c58f1c22SToby Isaac         *value = label->stratumValues[v];
1054c58f1c22SToby Isaac         break;
1055c58f1c22SToby Isaac       }
1056c58f1c22SToby Isaac     }
1057c58f1c22SToby Isaac   }
10583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1059c58f1c22SToby Isaac }
1060c58f1c22SToby Isaac 
1061c58f1c22SToby Isaac /*@
106220f4b53cSBarry 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
106320f4b53cSBarry Smith   be changed with `DMLabelSetDefaultValue()` to something different), then this function will do nothing.
1064c58f1c22SToby Isaac 
106520f4b53cSBarry Smith   Not Collective
10665b5e7992SMatthew G. Knepley 
1067c58f1c22SToby Isaac   Input Parameters:
106820f4b53cSBarry Smith + label - the `DMLabel`
1069c58f1c22SToby Isaac . point - the point
1070c58f1c22SToby Isaac - value - The point value
1071c58f1c22SToby Isaac 
1072c58f1c22SToby Isaac   Level: intermediate
1073c58f1c22SToby Isaac 
107420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1075c58f1c22SToby Isaac @*/
1076d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1077d71ae5a4SJacob Faibussowitsch {
1078c58f1c22SToby Isaac   PetscInt v;
1079c58f1c22SToby Isaac 
1080c58f1c22SToby Isaac   PetscFunctionBegin;
1081d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10820c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10833ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
10849f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
10859566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1086c58f1c22SToby Isaac   /* Set key */
10879566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10889566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
10893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1090c58f1c22SToby Isaac }
1091c58f1c22SToby Isaac 
1092c58f1c22SToby Isaac /*@
1093c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1094c58f1c22SToby Isaac 
109520f4b53cSBarry Smith   Not Collective
10965b5e7992SMatthew G. Knepley 
1097c58f1c22SToby Isaac   Input Parameters:
109820f4b53cSBarry Smith + label - the `DMLabel`
1099c58f1c22SToby Isaac . point - the point
1100c58f1c22SToby Isaac - value - The point value
1101c58f1c22SToby Isaac 
1102c58f1c22SToby Isaac   Level: intermediate
1103c58f1c22SToby Isaac 
110420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1105c58f1c22SToby Isaac @*/
1106d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1107d71ae5a4SJacob Faibussowitsch {
1108ad8374ffSToby Isaac   PetscInt v;
1109c58f1c22SToby Isaac 
1110c58f1c22SToby Isaac   PetscFunctionBegin;
1111d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11129f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1113c58f1c22SToby Isaac   /* Find label value */
11149566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
11153ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
11160c3c4a36SLisandro Dalcin 
1117eeed21e7SToby Isaac   if (label->bt) {
111863a3b9bcSJacob 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);
11199566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1120eeed21e7SToby Isaac   }
11210c3c4a36SLisandro Dalcin 
11220c3c4a36SLisandro Dalcin   /* Delete key */
11239566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11249566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
11253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1126c58f1c22SToby Isaac }
1127c58f1c22SToby Isaac 
1128c58f1c22SToby Isaac /*@
112920f4b53cSBarry Smith   DMLabelInsertIS - Set all points in the `IS` to a value
1130c58f1c22SToby Isaac 
113120f4b53cSBarry Smith   Not Collective
11325b5e7992SMatthew G. Knepley 
1133c58f1c22SToby Isaac   Input Parameters:
113420f4b53cSBarry Smith + label - the `DMLabel`
11352fe279fdSBarry Smith . is    - the point `IS`
1136c58f1c22SToby Isaac - value - The point value
1137c58f1c22SToby Isaac 
1138c58f1c22SToby Isaac   Level: intermediate
1139c58f1c22SToby Isaac 
114020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1141c58f1c22SToby Isaac @*/
1142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1143d71ae5a4SJacob Faibussowitsch {
11440c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1145c58f1c22SToby Isaac   const PetscInt *points;
1146c58f1c22SToby Isaac 
1147c58f1c22SToby Isaac   PetscFunctionBegin;
1148d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1149c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11500c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11513ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11529f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11539566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11540c3c4a36SLisandro Dalcin   /* Set keys */
11559566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11569566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11579566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11589566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11599566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
11603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1161c58f1c22SToby Isaac }
1162c58f1c22SToby Isaac 
116384f0b6dfSMatthew G. Knepley /*@
116420f4b53cSBarry Smith   DMLabelGetNumValues - Get the number of values that the `DMLabel` takes
116584f0b6dfSMatthew G. Knepley 
116620f4b53cSBarry Smith   Not Collective
11675b5e7992SMatthew G. Knepley 
116884f0b6dfSMatthew G. Knepley   Input Parameter:
116920f4b53cSBarry Smith . label - the `DMLabel`
117084f0b6dfSMatthew G. Knepley 
117101d2d390SJose E. Roman   Output Parameter:
117284f0b6dfSMatthew G. Knepley . numValues - the number of values
117384f0b6dfSMatthew G. Knepley 
117484f0b6dfSMatthew G. Knepley   Level: intermediate
117584f0b6dfSMatthew G. Knepley 
117620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
117784f0b6dfSMatthew G. Knepley @*/
1178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1179d71ae5a4SJacob Faibussowitsch {
1180c58f1c22SToby Isaac   PetscFunctionBegin;
1181d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11824f572ea9SToby Isaac   PetscAssertPointer(numValues, 2);
1183c58f1c22SToby Isaac   *numValues = label->numStrata;
11843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1185c58f1c22SToby Isaac }
1186c58f1c22SToby Isaac 
118784f0b6dfSMatthew G. Knepley /*@
118820f4b53cSBarry Smith   DMLabelGetValueIS - Get an `IS` of all values that the `DMlabel` takes
118984f0b6dfSMatthew G. Knepley 
119020f4b53cSBarry Smith   Not Collective
11915b5e7992SMatthew G. Knepley 
119284f0b6dfSMatthew G. Knepley   Input Parameter:
119320f4b53cSBarry Smith . label - the `DMLabel`
119484f0b6dfSMatthew G. Knepley 
119501d2d390SJose E. Roman   Output Parameter:
119660225df5SJacob Faibussowitsch . values - the value `IS`
119784f0b6dfSMatthew G. Knepley 
119884f0b6dfSMatthew G. Knepley   Level: intermediate
119984f0b6dfSMatthew G. Knepley 
12001d04cbbeSVaclav Hapla   Notes:
120120f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
120220f4b53cSBarry Smith   Strata which are allocated but empty [`DMLabelGetStratumSize()` yields 0] are counted.
120320f4b53cSBarry Smith   If you need to count only nonempty strata, use `DMLabelGetNonEmptyStratumValuesIS()`.
12041d04cbbeSVaclav Hapla 
120520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
120684f0b6dfSMatthew G. Knepley @*/
1207d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1208d71ae5a4SJacob Faibussowitsch {
1209c58f1c22SToby Isaac   PetscFunctionBegin;
1210d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12114f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12129566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1214c58f1c22SToby Isaac }
1215c58f1c22SToby Isaac 
121684f0b6dfSMatthew G. Knepley /*@
121720f4b53cSBarry Smith   DMLabelGetNonEmptyStratumValuesIS - Get an `IS` of all values that the `DMlabel` takes
12181d04cbbeSVaclav Hapla 
121920f4b53cSBarry Smith   Not Collective
12201d04cbbeSVaclav Hapla 
12211d04cbbeSVaclav Hapla   Input Parameter:
122220f4b53cSBarry Smith . label - the `DMLabel`
12231d04cbbeSVaclav Hapla 
1224d5b43468SJose E. Roman   Output Parameter:
122560225df5SJacob Faibussowitsch . values - the value `IS`
12261d04cbbeSVaclav Hapla 
12271d04cbbeSVaclav Hapla   Level: intermediate
12281d04cbbeSVaclav Hapla 
12291d04cbbeSVaclav Hapla   Notes:
123020f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
123120f4b53cSBarry Smith   This is similar to `DMLabelGetValueIS()` but counts only nonempty strata.
12321d04cbbeSVaclav Hapla 
123320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
12341d04cbbeSVaclav Hapla @*/
1235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1236d71ae5a4SJacob Faibussowitsch {
12371d04cbbeSVaclav Hapla   PetscInt  i, j;
12381d04cbbeSVaclav Hapla   PetscInt *valuesArr;
12391d04cbbeSVaclav Hapla 
12401d04cbbeSVaclav Hapla   PetscFunctionBegin;
12411d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12424f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
12441d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
12451d04cbbeSVaclav Hapla     PetscInt n;
12461d04cbbeSVaclav Hapla 
12479566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
12481d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
12491d04cbbeSVaclav Hapla   }
12501d04cbbeSVaclav Hapla   if (j == label->numStrata) {
12519566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12521d04cbbeSVaclav Hapla   } else {
12539566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
12541d04cbbeSVaclav Hapla   }
12559566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
12563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12571d04cbbeSVaclav Hapla }
12581d04cbbeSVaclav Hapla 
12591d04cbbeSVaclav Hapla /*@
126020f4b53cSBarry Smith   DMLabelGetValueIndex - Get the index of a given value in the list of values for the `DMlabel`, or -1 if it is not present
1261d123abd9SMatthew G. Knepley 
126220f4b53cSBarry Smith   Not Collective
1263d123abd9SMatthew G. Knepley 
1264d123abd9SMatthew G. Knepley   Input Parameters:
126520f4b53cSBarry Smith + label - the `DMLabel`
126697bb3fdcSJose E. Roman - value - the value
1267d123abd9SMatthew G. Knepley 
126801d2d390SJose E. Roman   Output Parameter:
1269d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1270d123abd9SMatthew G. Knepley 
1271d123abd9SMatthew G. Knepley   Level: intermediate
1272d123abd9SMatthew G. Knepley 
127320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1274d123abd9SMatthew G. Knepley @*/
1275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1276d71ae5a4SJacob Faibussowitsch {
1277d123abd9SMatthew G. Knepley   PetscInt v;
1278d123abd9SMatthew G. Knepley 
1279d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1280d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12814f572ea9SToby Isaac   PetscAssertPointer(index, 3);
1282d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
12839371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
12849371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1285d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1286d123abd9SMatthew G. Knepley   else *index = v;
12873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1288d123abd9SMatthew G. Knepley }
1289d123abd9SMatthew G. Knepley 
1290d123abd9SMatthew G. Knepley /*@
129184f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
129284f0b6dfSMatthew G. Knepley 
129320f4b53cSBarry Smith   Not Collective
12945b5e7992SMatthew G. Knepley 
129584f0b6dfSMatthew G. Knepley   Input Parameters:
129620f4b53cSBarry Smith + label - the `DMLabel`
129784f0b6dfSMatthew G. Knepley - value - the stratum value
129884f0b6dfSMatthew G. Knepley 
129901d2d390SJose E. Roman   Output Parameter:
130084f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
130184f0b6dfSMatthew G. Knepley 
130284f0b6dfSMatthew G. Knepley   Level: intermediate
130384f0b6dfSMatthew G. Knepley 
130420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
130584f0b6dfSMatthew G. Knepley @*/
1306d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1307d71ae5a4SJacob Faibussowitsch {
1308fada774cSMatthew G. Knepley   PetscInt v;
1309fada774cSMatthew G. Knepley 
1310fada774cSMatthew G. Knepley   PetscFunctionBegin;
1311d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13124f572ea9SToby Isaac   PetscAssertPointer(exists, 3);
13139566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13140c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
13153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1316fada774cSMatthew G. Knepley }
1317fada774cSMatthew G. Knepley 
131884f0b6dfSMatthew G. Knepley /*@
131984f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
132084f0b6dfSMatthew G. Knepley 
132120f4b53cSBarry Smith   Not Collective
13225b5e7992SMatthew G. Knepley 
132384f0b6dfSMatthew G. Knepley   Input Parameters:
132420f4b53cSBarry Smith + label - the `DMLabel`
132584f0b6dfSMatthew G. Knepley - value - the stratum value
132684f0b6dfSMatthew G. Knepley 
132701d2d390SJose E. Roman   Output Parameter:
132884f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
132984f0b6dfSMatthew G. Knepley 
133084f0b6dfSMatthew G. Knepley   Level: intermediate
133184f0b6dfSMatthew G. Knepley 
133220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
133384f0b6dfSMatthew G. Knepley @*/
1334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1335d71ae5a4SJacob Faibussowitsch {
1336c58f1c22SToby Isaac   PetscInt v;
1337c58f1c22SToby Isaac 
1338c58f1c22SToby Isaac   PetscFunctionBegin;
1339d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13404f572ea9SToby Isaac   PetscAssertPointer(size, 3);
13419566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13429566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
13433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1344c58f1c22SToby Isaac }
1345c58f1c22SToby Isaac 
134684f0b6dfSMatthew G. Knepley /*@
134784f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
134884f0b6dfSMatthew G. Knepley 
134920f4b53cSBarry Smith   Not Collective
13505b5e7992SMatthew G. Knepley 
135184f0b6dfSMatthew G. Knepley   Input Parameters:
135220f4b53cSBarry Smith + label - the `DMLabel`
135384f0b6dfSMatthew G. Knepley - value - the stratum value
135484f0b6dfSMatthew G. Knepley 
135501d2d390SJose E. Roman   Output Parameters:
135684f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
135784f0b6dfSMatthew G. Knepley - end   - the largest point in the stratum
135884f0b6dfSMatthew G. Knepley 
135984f0b6dfSMatthew G. Knepley   Level: intermediate
136084f0b6dfSMatthew G. Knepley 
136120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
136284f0b6dfSMatthew G. Knepley @*/
1363d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1364d71ae5a4SJacob Faibussowitsch {
13659f6c5813SMatthew G. Knepley   IS       is;
13660c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1367c58f1c22SToby Isaac 
1368c58f1c22SToby Isaac   PetscFunctionBegin;
1369d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13709371c9d4SSatish Balay   if (start) {
13714f572ea9SToby Isaac     PetscAssertPointer(start, 3);
13729371c9d4SSatish Balay     *start = -1;
13739371c9d4SSatish Balay   }
13749371c9d4SSatish Balay   if (end) {
13754f572ea9SToby Isaac     PetscAssertPointer(end, 4);
13769371c9d4SSatish Balay     *end = -1;
13779371c9d4SSatish Balay   }
13789566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13793ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
13809566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13813ba16761SJacob Faibussowitsch   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
13829f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &is);
13839f6c5813SMatthew G. Knepley   PetscCall(ISGetMinMax(is, &min, &max));
13849f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&is));
1385d6cb179aSToby Isaac   if (start) *start = min;
1386d6cb179aSToby Isaac   if (end) *end = max + 1;
13873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1388c58f1c22SToby Isaac }
1389c58f1c22SToby Isaac 
139066976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
13919f6c5813SMatthew G. Knepley {
13929f6c5813SMatthew G. Knepley   PetscFunctionBegin;
13939f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
13949f6c5813SMatthew G. Knepley   *pointIS = label->points[v];
13953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13969f6c5813SMatthew G. Knepley }
13979f6c5813SMatthew G. Knepley 
139884f0b6dfSMatthew G. Knepley /*@
139920f4b53cSBarry Smith   DMLabelGetStratumIS - Get an `IS` with the stratum points
140084f0b6dfSMatthew G. Knepley 
140120f4b53cSBarry Smith   Not Collective
14025b5e7992SMatthew G. Knepley 
140384f0b6dfSMatthew G. Knepley   Input Parameters:
140420f4b53cSBarry Smith + label - the `DMLabel`
140584f0b6dfSMatthew G. Knepley - value - the stratum value
140684f0b6dfSMatthew G. Knepley 
140701d2d390SJose E. Roman   Output Parameter:
140884f0b6dfSMatthew G. Knepley . points - The stratum points
140984f0b6dfSMatthew G. Knepley 
141084f0b6dfSMatthew G. Knepley   Level: intermediate
141184f0b6dfSMatthew G. Knepley 
1412593ce467SVaclav Hapla   Notes:
141320f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
141420f4b53cSBarry Smith   Returns `NULL` if the stratum is empty.
1415593ce467SVaclav Hapla 
141620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
141784f0b6dfSMatthew G. Knepley @*/
1418d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1419d71ae5a4SJacob Faibussowitsch {
1420c58f1c22SToby Isaac   PetscInt v;
1421c58f1c22SToby Isaac 
1422c58f1c22SToby Isaac   PetscFunctionBegin;
1423d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14244f572ea9SToby Isaac   PetscAssertPointer(points, 3);
1425c58f1c22SToby Isaac   *points = NULL;
14269566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14273ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14289566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14299f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, points);
14303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1431c58f1c22SToby Isaac }
1432c58f1c22SToby Isaac 
143384f0b6dfSMatthew G. Knepley /*@
143420f4b53cSBarry Smith   DMLabelSetStratumIS - Set the stratum points using an `IS`
143584f0b6dfSMatthew G. Knepley 
143620f4b53cSBarry Smith   Not Collective
14375b5e7992SMatthew G. Knepley 
143884f0b6dfSMatthew G. Knepley   Input Parameters:
143920f4b53cSBarry Smith + label - the `DMLabel`
144084f0b6dfSMatthew G. Knepley . value - the stratum value
144160225df5SJacob Faibussowitsch - is    - The stratum points
144284f0b6dfSMatthew G. Knepley 
144384f0b6dfSMatthew G. Knepley   Level: intermediate
144484f0b6dfSMatthew G. Knepley 
144520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
144684f0b6dfSMatthew G. Knepley @*/
1447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1448d71ae5a4SJacob Faibussowitsch {
14490c3c4a36SLisandro Dalcin   PetscInt v;
14504de306b1SToby Isaac 
14514de306b1SToby Isaac   PetscFunctionBegin;
1452d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1453d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
14549f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
14559566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
14563ba16761SJacob Faibussowitsch   if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
14579566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
1458*f4f49eeaSPierre Jolivet   PetscCall(ISGetLocalSize(is, &label->stratumSizes[v]));
14599566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
1460*f4f49eeaSPierre Jolivet   PetscCall(ISDestroy(&label->points[v]));
14610c3c4a36SLisandro Dalcin   label->points[v]  = is;
14620c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
14639566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
14644de306b1SToby Isaac   if (label->bt) {
14654de306b1SToby Isaac     const PetscInt *points;
14664de306b1SToby Isaac     PetscInt        p;
14674de306b1SToby Isaac 
14689566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
14694de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
14704de306b1SToby Isaac       const PetscInt point = points[p];
14714de306b1SToby Isaac 
147263a3b9bcSJacob 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);
14739566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
14744de306b1SToby Isaac     }
14754de306b1SToby Isaac   }
14763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14774de306b1SToby Isaac }
14784de306b1SToby Isaac 
147984f0b6dfSMatthew G. Knepley /*@
148084f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14814de306b1SToby Isaac 
148220f4b53cSBarry Smith   Not Collective
14835b5e7992SMatthew G. Knepley 
148484f0b6dfSMatthew G. Knepley   Input Parameters:
148520f4b53cSBarry Smith + label - the `DMLabel`
148684f0b6dfSMatthew G. Knepley - value - the stratum value
148784f0b6dfSMatthew G. Knepley 
148884f0b6dfSMatthew G. Knepley   Level: intermediate
148984f0b6dfSMatthew G. Knepley 
149020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
149184f0b6dfSMatthew G. Knepley @*/
1492d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1493d71ae5a4SJacob Faibussowitsch {
1494c58f1c22SToby Isaac   PetscInt v;
1495c58f1c22SToby Isaac 
1496c58f1c22SToby Isaac   PetscFunctionBegin;
1497d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14989f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
14999566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15003ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15014de306b1SToby Isaac   if (label->validIS[v]) {
15024de306b1SToby Isaac     if (label->bt) {
1503c58f1c22SToby Isaac       PetscInt        i;
1504ad8374ffSToby Isaac       const PetscInt *points;
1505c58f1c22SToby Isaac 
15069566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1507c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1508ad8374ffSToby Isaac         const PetscInt point = points[i];
1509c58f1c22SToby Isaac 
151063a3b9bcSJacob 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);
15119566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1512c58f1c22SToby Isaac       }
15139566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1514c58f1c22SToby Isaac     }
1515c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
15169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
15179566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
15189566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
15199566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1520c58f1c22SToby Isaac   } else {
15219566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1522c58f1c22SToby Isaac   }
15233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1524c58f1c22SToby Isaac }
1525c58f1c22SToby Isaac 
152684f0b6dfSMatthew G. Knepley /*@
1527412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1528412e9a14SMatthew G. Knepley 
152920f4b53cSBarry Smith   Not Collective
1530412e9a14SMatthew G. Knepley 
1531412e9a14SMatthew G. Knepley   Input Parameters:
153220f4b53cSBarry Smith + label  - The `DMLabel`
1533412e9a14SMatthew G. Knepley . value  - The label value for all points
1534412e9a14SMatthew G. Knepley . pStart - The first point
1535412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1536412e9a14SMatthew G. Knepley 
1537412e9a14SMatthew G. Knepley   Level: intermediate
1538412e9a14SMatthew G. Knepley 
153920f4b53cSBarry Smith   Note:
154020f4b53cSBarry Smith   The marks points are [`pStart`, `pEnd`), and only the bounds are stored.
154120f4b53cSBarry Smith 
154220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1543412e9a14SMatthew G. Knepley @*/
1544d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1545d71ae5a4SJacob Faibussowitsch {
1546412e9a14SMatthew G. Knepley   IS pIS;
1547412e9a14SMatthew G. Knepley 
1548412e9a14SMatthew G. Knepley   PetscFunctionBegin;
15499566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
15509566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
15519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
15523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1553412e9a14SMatthew G. Knepley }
1554412e9a14SMatthew G. Knepley 
1555412e9a14SMatthew G. Knepley /*@
1556d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1557d123abd9SMatthew G. Knepley 
155820f4b53cSBarry Smith   Not Collective
1559d123abd9SMatthew G. Knepley 
1560d123abd9SMatthew G. Knepley   Input Parameters:
156120f4b53cSBarry Smith + label - The `DMLabel`
1562d123abd9SMatthew G. Knepley . value - The label value
1563d123abd9SMatthew G. Knepley - p     - A point with this value
1564d123abd9SMatthew G. Knepley 
1565d123abd9SMatthew G. Knepley   Output Parameter:
1566d123abd9SMatthew 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
1567d123abd9SMatthew G. Knepley 
1568d123abd9SMatthew G. Knepley   Level: intermediate
1569d123abd9SMatthew G. Knepley 
157020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1571d123abd9SMatthew G. Knepley @*/
1572d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1573d71ae5a4SJacob Faibussowitsch {
15749f6c5813SMatthew G. Knepley   IS              pointIS;
1575d123abd9SMatthew G. Knepley   const PetscInt *indices;
1576d123abd9SMatthew G. Knepley   PetscInt        v;
1577d123abd9SMatthew G. Knepley 
1578d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1579d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15804f572ea9SToby Isaac   PetscAssertPointer(index, 4);
1581d123abd9SMatthew G. Knepley   *index = -1;
15829566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15833ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15849566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
15859f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &pointIS);
15869f6c5813SMatthew G. Knepley   PetscCall(ISGetIndices(pointIS, &indices));
15879566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
15889f6c5813SMatthew G. Knepley   PetscCall(ISRestoreIndices(pointIS, &indices));
15899f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&pointIS));
15903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1591d123abd9SMatthew G. Knepley }
1592d123abd9SMatthew G. Knepley 
1593d123abd9SMatthew G. Knepley /*@
159420f4b53cSBarry Smith   DMLabelFilter - Remove all points outside of [`start`, `end`)
159584f0b6dfSMatthew G. Knepley 
159620f4b53cSBarry Smith   Not Collective
15975b5e7992SMatthew G. Knepley 
159884f0b6dfSMatthew G. Knepley   Input Parameters:
159920f4b53cSBarry Smith + label - the `DMLabel`
160022cd2cdaSVaclav Hapla . start - the first point kept
160122cd2cdaSVaclav Hapla - end   - one more than the last point kept
160284f0b6dfSMatthew G. Knepley 
160384f0b6dfSMatthew G. Knepley   Level: intermediate
160484f0b6dfSMatthew G. Knepley 
160520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
160684f0b6dfSMatthew G. Knepley @*/
1607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1608d71ae5a4SJacob Faibussowitsch {
1609c58f1c22SToby Isaac   PetscInt v;
1610c58f1c22SToby Isaac 
1611c58f1c22SToby Isaac   PetscFunctionBegin;
1612d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16139f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16149566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
16159566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16169f6c5813SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
16179f6c5813SMatthew G. Knepley     PetscCall(ISGeneralFilter(label->points[v], start, end));
16189f6c5813SMatthew G. Knepley     PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
16199f6c5813SMatthew G. Knepley   }
16209566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
16213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1622c58f1c22SToby Isaac }
1623c58f1c22SToby Isaac 
162484f0b6dfSMatthew G. Knepley /*@
162584f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
162684f0b6dfSMatthew G. Knepley 
162720f4b53cSBarry Smith   Not Collective
16285b5e7992SMatthew G. Knepley 
162984f0b6dfSMatthew G. Knepley   Input Parameters:
163020f4b53cSBarry Smith + label       - the `DMLabel`
163184f0b6dfSMatthew G. Knepley - permutation - the point permutation
163284f0b6dfSMatthew G. Knepley 
163384f0b6dfSMatthew G. Knepley   Output Parameter:
163460225df5SJacob Faibussowitsch . labelNew - the new label containing the permuted points
163584f0b6dfSMatthew G. Knepley 
163684f0b6dfSMatthew G. Knepley   Level: intermediate
163784f0b6dfSMatthew G. Knepley 
163820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
163984f0b6dfSMatthew G. Knepley @*/
1640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1641d71ae5a4SJacob Faibussowitsch {
1642c58f1c22SToby Isaac   const PetscInt *perm;
1643c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1644c58f1c22SToby Isaac 
1645c58f1c22SToby Isaac   PetscFunctionBegin;
1646d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1647d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
16489f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16499566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16509566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
16519566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
16529566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
16539566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1654c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1655c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1656ad8374ffSToby Isaac     const PetscInt *points;
1657ad8374ffSToby Isaac     PetscInt       *pointsNew;
1658c58f1c22SToby Isaac 
16599566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
16609f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(size, &pointsNew));
1661c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1662ad8374ffSToby Isaac       const PetscInt point = points[q];
1663c58f1c22SToby Isaac 
166463a3b9bcSJacob 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);
1665ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1666c58f1c22SToby Isaac     }
16679566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
16689566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
16699566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1670fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
16719566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
16729566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1673fa8e8ae5SToby Isaac     } else {
16749566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1675fa8e8ae5SToby Isaac     }
16769566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1677c58f1c22SToby Isaac   }
16789566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1679c58f1c22SToby Isaac   if (label->bt) {
16809566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
16819566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1682c58f1c22SToby Isaac   }
16833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1684c58f1c22SToby Isaac }
1685c58f1c22SToby Isaac 
168666976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1687d71ae5a4SJacob Faibussowitsch {
168826c55118SMichael Lange   MPI_Comm     comm;
1689eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
169026c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
169126c55118SMichael Lange   PetscSection rootSection;
169226c55118SMichael Lange   PetscSF      labelSF;
169326c55118SMichael Lange 
169426c55118SMichael Lange   PetscFunctionBegin;
16959566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
16969566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
169726c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
169826c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
16999566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
17009566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
17019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
170226c55118SMichael Lange   if (label) {
170326c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1704ad8374ffSToby Isaac       const PetscInt *points;
1705ad8374ffSToby Isaac 
17069566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
170748a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
17089566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
170926c55118SMichael Lange     }
171026c55118SMichael Lange   }
17119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
171226c55118SMichael Lange   /* Create a point-wise array of stratum values */
17139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
17149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
17159566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
171626c55118SMichael Lange   if (label) {
171726c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1718ad8374ffSToby Isaac       const PetscInt *points;
1719ad8374ffSToby Isaac 
17209566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
172126c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1722ad8374ffSToby Isaac         const PetscInt p = points[l];
17239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
172426c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
172526c55118SMichael Lange       }
17269566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
172726c55118SMichael Lange     }
172826c55118SMichael Lange   }
172926c55118SMichael Lange   /* Build SF that maps label points to remote processes */
17309566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
17319566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
17329566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
17339566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
173426c55118SMichael Lange   /* Send the strata for each point over the derived SF */
17359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
17369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
17379566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
17389566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
173926c55118SMichael Lange   /* Clean up */
17409566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
17419566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
17429566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
17439566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
17443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
174526c55118SMichael Lange }
174626c55118SMichael Lange 
174784f0b6dfSMatthew G. Knepley /*@
174820f4b53cSBarry Smith   DMLabelDistribute - Create a new label pushed forward over the `PetscSF`
174984f0b6dfSMatthew G. Knepley 
175020f4b53cSBarry Smith   Collective
17515b5e7992SMatthew G. Knepley 
175284f0b6dfSMatthew G. Knepley   Input Parameters:
175320f4b53cSBarry Smith + label - the `DMLabel`
175484f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
175584f0b6dfSMatthew G. Knepley 
175684f0b6dfSMatthew G. Knepley   Output Parameter:
175760225df5SJacob Faibussowitsch . labelNew - the new redistributed label
175884f0b6dfSMatthew G. Knepley 
175984f0b6dfSMatthew G. Knepley   Level: intermediate
176084f0b6dfSMatthew G. Knepley 
176120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
176284f0b6dfSMatthew G. Knepley @*/
1763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1764d71ae5a4SJacob Faibussowitsch {
1765c58f1c22SToby Isaac   MPI_Comm     comm;
176626c55118SMichael Lange   PetscSection leafSection;
176726c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
176826c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1769ad8374ffSToby Isaac   PetscInt   **points;
1770d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1771c58f1c22SToby Isaac   char        *name;
1772c58f1c22SToby Isaac   PetscInt     nameSize;
1773e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1774c58f1c22SToby Isaac   size_t       len = 0;
177526c55118SMichael Lange   PetscMPIInt  rank;
1776c58f1c22SToby Isaac 
1777c58f1c22SToby Isaac   PetscFunctionBegin;
1778d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1779f018e600SMatthew G. Knepley   if (label) {
1780f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17819f6c5813SMatthew G. Knepley     PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
17829566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1783f018e600SMatthew G. Knepley   }
17849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1786c58f1c22SToby Isaac   /* Bcast name */
1787dd400576SPatrick Sanan   if (rank == 0) {
17889566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
17899566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1790d67d17b1SMatthew G. Knepley   }
1791c58f1c22SToby Isaac   nameSize = len;
17929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
17949566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
17959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
17969566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17979566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
179877d236dfSMichael Lange   /* Bcast defaultValue */
1799dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
18009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
180126c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
18029566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
18035cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
18049566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
18059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
18069566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
18079566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
18089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1809ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
18109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
18115cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
18125cbdf6fcSMichael Lange   offset = 0;
18139566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
18149566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
181548a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
18165cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1817231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
18189371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
18199371c9d4SSatish Balay         leafStrata[p] = s;
18209371c9d4SSatish Balay         break;
18219371c9d4SSatish Balay       }
18225cbdf6fcSMichael Lange     }
18235cbdf6fcSMichael Lange   }
1824c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
18259566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
18269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1827c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
18289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
18299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1830ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1831c58f1c22SToby Isaac   }
18329566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
18339f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
18349f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1835c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
18369566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
1837*f4f49eeaSPierre Jolivet     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &points[s]));
1838c58f1c22SToby Isaac   }
1839c58f1c22SToby Isaac   /* Insert points into new strata */
18409566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
18419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1842c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
18439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
18449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1845c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1846c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1847ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1848c58f1c22SToby Isaac     }
1849c58f1c22SToby Isaac   }
1850ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1851*f4f49eeaSPierre Jolivet     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &points[s][0], PETSC_OWN_POINTER, &((*labelNew)->points[s])));
18529566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1853ad8374ffSToby Isaac   }
18549566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
18559566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
18569566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
18579566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
18589566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
18593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1860c58f1c22SToby Isaac }
1861c58f1c22SToby Isaac 
18627937d9ceSMichael Lange /*@
18637937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
18647937d9ceSMichael Lange 
186520f4b53cSBarry Smith   Collective
18665b5e7992SMatthew G. Knepley 
18677937d9ceSMichael Lange   Input Parameters:
186820f4b53cSBarry Smith + label - the `DMLabel`
186920f4b53cSBarry Smith - sf    - the `PetscSF` communication map
18707937d9ceSMichael Lange 
18712fe279fdSBarry Smith   Output Parameter:
187220f4b53cSBarry Smith . labelNew - the new `DMLabel` with localised leaf values
18737937d9ceSMichael Lange 
18747937d9ceSMichael Lange   Level: developer
18757937d9ceSMichael Lange 
187620f4b53cSBarry Smith   Note:
187720f4b53cSBarry Smith   This is the inverse operation to `DMLabelDistribute()`.
18787937d9ceSMichael Lange 
187920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
18807937d9ceSMichael Lange @*/
1881d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
1882d71ae5a4SJacob Faibussowitsch {
18837937d9ceSMichael Lange   MPI_Comm        comm;
18847937d9ceSMichael Lange   PetscSection    rootSection;
18857937d9ceSMichael Lange   PetscSF         sfLabel;
18867937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
18877937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18887937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18897937d9ceSMichael Lange   PetscInt       *rootStrata;
1890d67d17b1SMatthew G. Knepley   const char     *lname;
18917937d9ceSMichael Lange   char           *name;
18927937d9ceSMichael Lange   PetscInt        nameSize;
18937937d9ceSMichael Lange   size_t          len = 0;
18949852e123SBarry Smith   PetscMPIInt     rank, size;
18957937d9ceSMichael Lange 
18967937d9ceSMichael Lange   PetscFunctionBegin;
1897d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1898d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
18999f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
19009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
19019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
19029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
19037937d9ceSMichael Lange   /* Bcast name */
1904dd400576SPatrick Sanan   if (rank == 0) {
19059566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
19069566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1907d67d17b1SMatthew G. Knepley   }
19087937d9ceSMichael Lange   nameSize = len;
19099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
19109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
19119566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
19129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
19139566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
19149566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
19157937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
19167937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
19177937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
19189566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
19199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1920dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
19217937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
19228212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
19238212dd46SStefano Zampini 
19248212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
19258212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
19267937d9ceSMichael Lange   }
19279566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
19289566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
19297937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
19309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
19319566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
19329566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
19339566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
19349566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
19357937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
19369566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
19377937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
19387937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
19397937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
19409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
19419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
19429566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
19437937d9ceSMichael Lange     }
19447937d9ceSMichael Lange     idx += rootDegree[p];
19457937d9ceSMichael Lange   }
19469566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
19479566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
19489566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
19499566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
19503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19517937d9ceSMichael Lange }
19527937d9ceSMichael Lange 
1953d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1954d71ae5a4SJacob Faibussowitsch {
1955d42890abSMatthew G. Knepley   const PetscInt *degree;
1956d42890abSMatthew G. Knepley   const PetscInt *points;
1957d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1958d42890abSMatthew G. Knepley 
1959d42890abSMatthew G. Knepley   PetscFunctionBegin;
1960d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1961d42890abSMatthew G. Knepley   /* Add in leaves */
1962d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1963d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1964d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1965d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1966d42890abSMatthew G. Knepley   }
1967d42890abSMatthew G. Knepley   /* Add in shared roots */
1968d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1969d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1970d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1971d42890abSMatthew G. Knepley     if (degree[r]) {
1972d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1973d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1974d42890abSMatthew G. Knepley     }
1975d42890abSMatthew G. Knepley   }
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1977d42890abSMatthew G. Knepley }
1978d42890abSMatthew G. Knepley 
1979d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1980d71ae5a4SJacob Faibussowitsch {
1981d42890abSMatthew G. Knepley   const PetscInt *degree;
1982d42890abSMatthew G. Knepley   const PetscInt *points;
1983d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1984d42890abSMatthew G. Knepley 
1985d42890abSMatthew G. Knepley   PetscFunctionBegin;
1986d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1987d42890abSMatthew G. Knepley   /* Read out leaves */
1988d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1989d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1990d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1991d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1992d42890abSMatthew G. Knepley 
1993d42890abSMatthew G. Knepley     if (cval != defVal) {
1994d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1995d42890abSMatthew G. Knepley       if (val == defVal) {
1996d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
199748a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
1998d42890abSMatthew G. Knepley       }
1999d42890abSMatthew G. Knepley     }
2000d42890abSMatthew G. Knepley   }
2001d42890abSMatthew G. Knepley   /* Read out shared roots */
2002d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2003d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2004d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2005d42890abSMatthew G. Knepley     if (degree[r]) {
2006d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
2007d42890abSMatthew G. Knepley 
2008d42890abSMatthew G. Knepley       if (cval != defVal) {
2009d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
2010d42890abSMatthew G. Knepley         if (val == defVal) {
2011d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
201248a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2013d42890abSMatthew G. Knepley         }
2014d42890abSMatthew G. Knepley       }
2015d42890abSMatthew G. Knepley     }
2016d42890abSMatthew G. Knepley   }
20173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2018d42890abSMatthew G. Knepley }
2019d42890abSMatthew G. Knepley 
2020d42890abSMatthew G. Knepley /*@
2021d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
2022d42890abSMatthew G. Knepley 
202320f4b53cSBarry Smith   Collective
2024d42890abSMatthew G. Knepley 
2025d42890abSMatthew G. Knepley   Input Parameters:
202620f4b53cSBarry Smith + label - The `DMLabel` to propagate across processes
202720f4b53cSBarry Smith - sf    - The `PetscSF` describing parallel layout of the label points
2028d42890abSMatthew G. Knepley 
2029d42890abSMatthew G. Knepley   Level: intermediate
2030d42890abSMatthew G. Knepley 
203120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2032d42890abSMatthew G. Knepley @*/
2033d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2034d71ae5a4SJacob Faibussowitsch {
2035d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
2036d42890abSMatthew G. Knepley   PetscMPIInt size;
2037d42890abSMatthew G. Knepley 
2038d42890abSMatthew G. Knepley   PetscFunctionBegin;
20399f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2040d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2041d42890abSMatthew G. Knepley   if (size > 1) {
2042d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
2043d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2044d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2045d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2046d42890abSMatthew G. Knepley   }
20473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2048d42890abSMatthew G. Knepley }
2049d42890abSMatthew G. Knepley 
2050d42890abSMatthew G. Knepley /*@
2051d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
2052d42890abSMatthew G. Knepley 
205320f4b53cSBarry Smith   Collective
2054d42890abSMatthew G. Knepley 
2055d42890abSMatthew G. Knepley   Input Parameters:
205620f4b53cSBarry Smith + label   - The `DMLabel` to propagate across processes
205760225df5SJacob Faibussowitsch - pointSF - The `PetscSF` describing parallel layout of the label points
2058d42890abSMatthew G. Knepley 
2059d42890abSMatthew G. Knepley   Level: intermediate
2060d42890abSMatthew G. Knepley 
206120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2062d42890abSMatthew G. Knepley @*/
2063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2064d71ae5a4SJacob Faibussowitsch {
2065d42890abSMatthew G. Knepley   PetscFunctionBegin;
20669f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2067d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
2068d42890abSMatthew G. Knepley   label->propArray = NULL;
20693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2070d42890abSMatthew G. Knepley }
2071d42890abSMatthew G. Knepley 
2072d42890abSMatthew G. Knepley /*@C
2073d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2074d42890abSMatthew G. Knepley 
207520f4b53cSBarry Smith   Collective
2076d42890abSMatthew G. Knepley 
2077d42890abSMatthew G. Knepley   Input Parameters:
207820f4b53cSBarry Smith + label     - The `DMLabel` to propagate across processes
2079a4e35b19SJacob Faibussowitsch . pointSF   - The `PetscSF` describing parallel layout of the label points
208020f4b53cSBarry Smith . markPoint - An optional callback that is called when a point is marked, or `NULL`
208120f4b53cSBarry Smith - ctx       - An optional user context for the callback, or `NULL`
2082d42890abSMatthew G. Knepley 
208320f4b53cSBarry Smith   Calling sequence of `markPoint`:
208420f4b53cSBarry Smith + label - The `DMLabel`
2085d42890abSMatthew G. Knepley . p     - The point being marked
2086a4e35b19SJacob Faibussowitsch . val   - The label value for `p`
2087d42890abSMatthew G. Knepley - ctx   - An optional user context
2088d42890abSMatthew G. Knepley 
2089d42890abSMatthew G. Knepley   Level: intermediate
2090d42890abSMatthew G. Knepley 
209120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2092d42890abSMatthew G. Knepley @*/
2093a4e35b19SJacob Faibussowitsch PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel label, PetscInt p, PetscInt val, void *ctx), void *ctx)
2094d71ae5a4SJacob Faibussowitsch {
2095c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2096d42890abSMatthew G. Knepley   PetscMPIInt size;
2097d42890abSMatthew G. Knepley 
2098d42890abSMatthew G. Knepley   PetscFunctionBegin;
20999f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2100d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2101c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2102c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2103d42890abSMatthew G. Knepley     /* Communicate marked edges
2104d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2105d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2106d42890abSMatthew G. Knepley 
2107d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2108d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2109d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2110d42890abSMatthew G. Knepley 
2111d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2112d42890abSMatthew 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
2113d42890abSMatthew G. Knepley        edge to the queue.
2114d42890abSMatthew G. Knepley     */
2115d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2116d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2117d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2118d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2119d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2120d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2121d42890abSMatthew G. Knepley   }
21223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2123d42890abSMatthew G. Knepley }
2124d42890abSMatthew G. Knepley 
212584f0b6dfSMatthew G. Knepley /*@
212620f4b53cSBarry Smith   DMLabelConvertToSection - Make a `PetscSection`/`IS` pair that encodes the label
212784f0b6dfSMatthew G. Knepley 
212820f4b53cSBarry Smith   Not Collective
21295b5e7992SMatthew G. Knepley 
213084f0b6dfSMatthew G. Knepley   Input Parameter:
213120f4b53cSBarry Smith . label - the `DMLabel`
213284f0b6dfSMatthew G. Knepley 
213384f0b6dfSMatthew G. Knepley   Output Parameters:
213484f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
213520f4b53cSBarry Smith - is      - An `IS` containing all the label points
213684f0b6dfSMatthew G. Knepley 
213784f0b6dfSMatthew G. Knepley   Level: developer
213884f0b6dfSMatthew G. Knepley 
213920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
214084f0b6dfSMatthew G. Knepley @*/
2141d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2142d71ae5a4SJacob Faibussowitsch {
2143c58f1c22SToby Isaac   IS              vIS;
2144c58f1c22SToby Isaac   const PetscInt *values;
2145c58f1c22SToby Isaac   PetscInt       *points;
2146c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2147c58f1c22SToby Isaac 
2148c58f1c22SToby Isaac   PetscFunctionBegin;
2149d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
21509566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
21519566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
21529566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
21539371c9d4SSatish Balay   if (nV) {
21549371c9d4SSatish Balay     vS = values[0];
21559371c9d4SSatish Balay     vE = values[0] + 1;
21569371c9d4SSatish Balay   }
2157c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2158c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2159c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2160c58f1c22SToby Isaac   }
21619566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
21629566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2163c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2164c58f1c22SToby Isaac     PetscInt n;
2165c58f1c22SToby Isaac 
21669566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
21679566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2168c58f1c22SToby Isaac   }
21699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
21709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
21719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2172c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2173c58f1c22SToby Isaac     IS              is;
2174c58f1c22SToby Isaac     const PetscInt *spoints;
2175c58f1c22SToby Isaac     PetscInt        dof, off, p;
2176c58f1c22SToby Isaac 
21779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
21789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
21799566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
21809566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2181c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
21829566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
21839566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2184c58f1c22SToby Isaac   }
21859566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
21869566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
21879566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
21883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2189c58f1c22SToby Isaac }
2190c58f1c22SToby Isaac 
21919f6c5813SMatthew G. Knepley /*@C
21929f6c5813SMatthew G. Knepley   DMLabelRegister - Adds a new label component implementation
21939f6c5813SMatthew G. Knepley 
21949f6c5813SMatthew G. Knepley   Not Collective
21959f6c5813SMatthew G. Knepley 
21969f6c5813SMatthew G. Knepley   Input Parameters:
21979f6c5813SMatthew G. Knepley + name        - The name of a new user-defined creation routine
21989f6c5813SMatthew G. Knepley - create_func - The creation routine itself
21999f6c5813SMatthew G. Knepley 
22009f6c5813SMatthew G. Knepley   Notes:
22019f6c5813SMatthew G. Knepley   `DMLabelRegister()` may be called multiple times to add several user-defined labels
22029f6c5813SMatthew G. Knepley 
220360225df5SJacob Faibussowitsch   Example Usage:
22049f6c5813SMatthew G. Knepley .vb
22059f6c5813SMatthew G. Knepley   DMLabelRegister("my_label", MyLabelCreate);
22069f6c5813SMatthew G. Knepley .ve
22079f6c5813SMatthew G. Knepley 
22089f6c5813SMatthew G. Knepley   Then, your label type can be chosen with the procedural interface via
22099f6c5813SMatthew G. Knepley .vb
22109f6c5813SMatthew G. Knepley   DMLabelCreate(MPI_Comm, DMLabel *);
22119f6c5813SMatthew G. Knepley   DMLabelSetType(DMLabel, "my_label");
22129f6c5813SMatthew G. Knepley .ve
22139f6c5813SMatthew G. Knepley   or at runtime via the option
22149f6c5813SMatthew G. Knepley .vb
22159f6c5813SMatthew G. Knepley   -dm_label_type my_label
22169f6c5813SMatthew G. Knepley .ve
22179f6c5813SMatthew G. Knepley 
22189f6c5813SMatthew G. Knepley   Level: advanced
22199f6c5813SMatthew G. Knepley 
222060225df5SJacob Faibussowitsch .seealso: `DMLabel`, `DM`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
22219f6c5813SMatthew G. Knepley @*/
22229f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
22239f6c5813SMatthew G. Knepley {
22249f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22259f6c5813SMatthew G. Knepley   PetscCall(DMInitializePackage());
22269f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
22273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22289f6c5813SMatthew G. Knepley }
22299f6c5813SMatthew G. Knepley 
22309f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
22319f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
22329f6c5813SMatthew G. Knepley 
22339f6c5813SMatthew G. Knepley /*@C
22349f6c5813SMatthew G. Knepley   DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
22359f6c5813SMatthew G. Knepley 
22369f6c5813SMatthew G. Knepley   Not Collective
22379f6c5813SMatthew G. Knepley 
22389f6c5813SMatthew G. Knepley   Level: advanced
22399f6c5813SMatthew G. Knepley 
224020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMRegisterAll()`, `DMLabelRegisterDestroy()`
22419f6c5813SMatthew G. Knepley @*/
22429f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterAll(void)
22439f6c5813SMatthew G. Knepley {
22449f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22453ba16761SJacob Faibussowitsch   if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
22469f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_TRUE;
22479f6c5813SMatthew G. Knepley 
22489f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
22499f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
22503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22519f6c5813SMatthew G. Knepley }
22529f6c5813SMatthew G. Knepley 
22539f6c5813SMatthew G. Knepley /*@C
22549f6c5813SMatthew G. Knepley   DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
22559f6c5813SMatthew G. Knepley 
22569f6c5813SMatthew G. Knepley   Level: developer
22579f6c5813SMatthew G. Knepley 
225820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscInitialize()`
22599f6c5813SMatthew G. Knepley @*/
22609f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterDestroy(void)
22619f6c5813SMatthew G. Knepley {
22629f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22639f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListDestroy(&DMLabelList));
22649f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_FALSE;
22653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22669f6c5813SMatthew G. Knepley }
22679f6c5813SMatthew G. Knepley 
22689f6c5813SMatthew G. Knepley /*@C
22699f6c5813SMatthew G. Knepley   DMLabelSetType - Sets the particular implementation for a label.
22709f6c5813SMatthew G. Knepley 
227120f4b53cSBarry Smith   Collective
22729f6c5813SMatthew G. Knepley 
22739f6c5813SMatthew G. Knepley   Input Parameters:
22749f6c5813SMatthew G. Knepley + label  - The label
22759f6c5813SMatthew G. Knepley - method - The name of the label type
22769f6c5813SMatthew G. Knepley 
22779f6c5813SMatthew G. Knepley   Options Database Key:
227820f4b53cSBarry Smith . -dm_label_type <type> - Sets the label type; use -help for a list of available types or see `DMLabelType`
22799f6c5813SMatthew G. Knepley 
22809f6c5813SMatthew G. Knepley   Level: intermediate
22819f6c5813SMatthew G. Knepley 
228220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetType()`, `DMLabelCreate()`
22839f6c5813SMatthew G. Knepley @*/
22849f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
22859f6c5813SMatthew G. Knepley {
22869f6c5813SMatthew G. Knepley   PetscErrorCode (*r)(DMLabel);
22879f6c5813SMatthew G. Knepley   PetscBool match;
22889f6c5813SMatthew G. Knepley 
22899f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22909f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
22919f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
22923ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
22939f6c5813SMatthew G. Knepley 
22949f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
22959f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
22969f6c5813SMatthew G. Knepley   PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
22979f6c5813SMatthew G. Knepley 
22989f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, destroy);
22999f6c5813SMatthew G. Knepley   PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
23009f6c5813SMatthew G. Knepley   PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
23019f6c5813SMatthew G. Knepley   PetscCall((*r)(label));
23023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23039f6c5813SMatthew G. Knepley }
23049f6c5813SMatthew G. Knepley 
23059f6c5813SMatthew G. Knepley /*@C
23069f6c5813SMatthew G. Knepley   DMLabelGetType - Gets the type name (as a string) from the label.
23079f6c5813SMatthew G. Knepley 
23089f6c5813SMatthew G. Knepley   Not Collective
23099f6c5813SMatthew G. Knepley 
23109f6c5813SMatthew G. Knepley   Input Parameter:
231120f4b53cSBarry Smith . label - The `DMLabel`
23129f6c5813SMatthew G. Knepley 
23139f6c5813SMatthew G. Knepley   Output Parameter:
231420f4b53cSBarry Smith . type - The `DMLabel` type name
23159f6c5813SMatthew G. Knepley 
23169f6c5813SMatthew G. Knepley   Level: intermediate
23179f6c5813SMatthew G. Knepley 
231820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetType()`, `DMLabelCreate()`
23199f6c5813SMatthew G. Knepley @*/
23209f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
23219f6c5813SMatthew G. Knepley {
23229f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23239f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
23244f572ea9SToby Isaac   PetscAssertPointer(type, 2);
23259f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
23269f6c5813SMatthew G. Knepley   *type = ((PetscObject)label)->type_name;
23273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23289f6c5813SMatthew G. Knepley }
23299f6c5813SMatthew G. Knepley 
23309f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
23319f6c5813SMatthew G. Knepley {
23329f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23339f6c5813SMatthew G. Knepley   label->ops->view         = DMLabelView_Concrete;
23349f6c5813SMatthew G. Knepley   label->ops->setup        = NULL;
23359f6c5813SMatthew G. Knepley   label->ops->duplicate    = DMLabelDuplicate_Concrete;
23369f6c5813SMatthew G. Knepley   label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
23373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23389f6c5813SMatthew G. Knepley }
23399f6c5813SMatthew G. Knepley 
23409f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
23419f6c5813SMatthew G. Knepley {
23429f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23439f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
23449f6c5813SMatthew G. Knepley   PetscCall(DMLabelInitialize_Concrete(label));
23453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23469f6c5813SMatthew G. Knepley }
23479f6c5813SMatthew G. Knepley 
234884f0b6dfSMatthew G. Knepley /*@
2349c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
235020f4b53cSBarry Smith   the local section and an `PetscSF` describing the section point overlap.
2351c58f1c22SToby Isaac 
235220f4b53cSBarry Smith   Collective
23535b5e7992SMatthew G. Knepley 
2354c58f1c22SToby Isaac   Input Parameters:
235520f4b53cSBarry Smith + s                  - The `PetscSection` for the local field layout
235620f4b53cSBarry Smith . sf                 - The `PetscSF` describing parallel layout of the section points
235720f4b53cSBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
2358c58f1c22SToby Isaac . label              - The label specifying the points
2359c58f1c22SToby Isaac - labelValue         - The label stratum specifying the points
2360c58f1c22SToby Isaac 
2361c58f1c22SToby Isaac   Output Parameter:
236220f4b53cSBarry Smith . gsection - The `PetscSection` for the global field layout
2363c58f1c22SToby Isaac 
2364c58f1c22SToby Isaac   Level: developer
2365c58f1c22SToby Isaac 
236620f4b53cSBarry Smith   Note:
236720f4b53cSBarry Smith   This gives negative sizes and offsets to points not owned by this process
236820f4b53cSBarry Smith 
236920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionCreate()`
2370c58f1c22SToby Isaac @*/
2371d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2372d71ae5a4SJacob Faibussowitsch {
2373c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2374c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2375c58f1c22SToby Isaac 
2376c58f1c22SToby Isaac   PetscFunctionBegin;
2377d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2378d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2379d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
23809566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
23819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
23829566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
23839566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2384c58f1c22SToby Isaac   if (nroots >= 0) {
238563a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
23869566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2387c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
23889566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2389c58f1c22SToby Isaac     } else {
2390c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2391c58f1c22SToby Isaac     }
2392c58f1c22SToby Isaac   }
2393c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2394c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2395c58f1c22SToby Isaac     PetscInt value;
2396c58f1c22SToby Isaac 
23979566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2398c58f1c22SToby Isaac     if (value != labelValue) continue;
23999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
24009566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
24019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
24029566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2403c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2404c58f1c22SToby Isaac   }
24059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2406c58f1c22SToby Isaac   if (nroots >= 0) {
24079566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
24089566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2409c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
24109371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
24119371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
24129371c9d4SSatish Balay       }
2413c58f1c22SToby Isaac     }
2414c58f1c22SToby Isaac   }
241535cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
2416c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2417c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2418c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2419c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2420c58f1c22SToby Isaac   }
24219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2422c58f1c22SToby Isaac   globalOff -= off;
2423c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2424c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2425c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2426c58f1c22SToby Isaac   }
2427c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2428c58f1c22SToby Isaac   if (nroots >= 0) {
24299566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
24309566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2431c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
24329371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
24339371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
24349371c9d4SSatish Balay       }
2435c58f1c22SToby Isaac     }
2436c58f1c22SToby Isaac   }
24379566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
24389566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
24393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2440c58f1c22SToby Isaac }
2441c58f1c22SToby Isaac 
24429371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
24435fdea053SToby Isaac   DMLabel              label;
24445fdea053SToby Isaac   PetscCopyMode       *modes;
24455fdea053SToby Isaac   PetscInt            *sizes;
24465fdea053SToby Isaac   const PetscInt    ***perms;
24475fdea053SToby Isaac   const PetscScalar ***rots;
24485fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
24495fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
24505fdea053SToby Isaac } PetscSectionSym_Label;
24515fdea053SToby Isaac 
2452d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2453d71ae5a4SJacob Faibussowitsch {
24545fdea053SToby Isaac   PetscInt               i, j;
24555fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
24565fdea053SToby Isaac 
24575fdea053SToby Isaac   PetscFunctionBegin;
24585fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
24595fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
24605fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
24619566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
24629566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
24635fdea053SToby Isaac       }
24645fdea053SToby Isaac       if (sl->perms[i]) {
24655fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
24665fdea053SToby Isaac 
24679566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
24685fdea053SToby Isaac       }
24695fdea053SToby Isaac       if (sl->rots[i]) {
24705fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
24715fdea053SToby Isaac 
24729566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
24735fdea053SToby Isaac       }
24745fdea053SToby Isaac     }
24755fdea053SToby Isaac   }
24769566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
24779566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
24785fdea053SToby Isaac   sl->numStrata = 0;
24793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24805fdea053SToby Isaac }
24815fdea053SToby Isaac 
2482d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2483d71ae5a4SJacob Faibussowitsch {
24845fdea053SToby Isaac   PetscFunctionBegin;
24859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
24869566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
24873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24885fdea053SToby Isaac }
24895fdea053SToby Isaac 
2490d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2491d71ae5a4SJacob Faibussowitsch {
24925fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
24935fdea053SToby Isaac   PetscBool              isAscii;
24945fdea053SToby Isaac   DMLabel                label = sl->label;
2495d67d17b1SMatthew G. Knepley   const char            *name;
24965fdea053SToby Isaac 
24975fdea053SToby Isaac   PetscFunctionBegin;
24989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
24995fdea053SToby Isaac   if (isAscii) {
25005fdea053SToby Isaac     PetscInt          i, j, k;
25015fdea053SToby Isaac     PetscViewerFormat format;
25025fdea053SToby Isaac 
25039566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
25045fdea053SToby Isaac     if (label) {
25059566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
25065fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
25079566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
25089566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
25099566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
25105fdea053SToby Isaac       } else {
25119566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
25129566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
25135fdea053SToby Isaac       }
25145fdea053SToby Isaac     } else {
25159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
25165fdea053SToby Isaac     }
25179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
25185fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
25195fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
25205fdea053SToby Isaac 
25215fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
252263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
25235fdea053SToby Isaac       } else {
252463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
25259566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
252663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
25275fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
25289566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
25295fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
25305fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
253163a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
25325fdea053SToby Isaac             } else {
25335fdea053SToby Isaac               PetscInt tab;
25345fdea053SToby Isaac 
253563a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
25369566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
25379566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
25385fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
25399566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
25409566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
254163a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
25429566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
25439566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
25445fdea053SToby Isaac               }
25455fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
25469566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
25479566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
25485fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
254963a3b9bcSJacob 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])));
25505fdea053SToby Isaac #else
255163a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
25525fdea053SToby Isaac #endif
25539566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
25549566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
25555fdea053SToby Isaac               }
25569566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
25575fdea053SToby Isaac             }
25585fdea053SToby Isaac           }
25599566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
25605fdea053SToby Isaac         }
25619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
25625fdea053SToby Isaac       }
25635fdea053SToby Isaac     }
25649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
25655fdea053SToby Isaac   }
25663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25675fdea053SToby Isaac }
25685fdea053SToby Isaac 
25695fdea053SToby Isaac /*@
25705fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
25715fdea053SToby Isaac 
257220f4b53cSBarry Smith   Logically
25735fdea053SToby Isaac 
257460225df5SJacob Faibussowitsch   Input Parameters:
25755fdea053SToby Isaac + sym   - the section symmetries
257620f4b53cSBarry Smith - label - the `DMLabel` describing the types of points
25775fdea053SToby Isaac 
25785fdea053SToby Isaac   Level: developer:
25795fdea053SToby Isaac 
258020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
25815fdea053SToby Isaac @*/
2582d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2583d71ae5a4SJacob Faibussowitsch {
25845fdea053SToby Isaac   PetscSectionSym_Label *sl;
25855fdea053SToby Isaac 
25865fdea053SToby Isaac   PetscFunctionBegin;
25875fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
25885fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
25899566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
25905fdea053SToby Isaac   if (label) {
25915fdea053SToby Isaac     sl->label = label;
25929566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
25939566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
25949566063dSJacob 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));
25959566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
25969566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
25979566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
25989566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
25999566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
26005fdea053SToby Isaac   }
26013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26025fdea053SToby Isaac }
26035fdea053SToby Isaac 
26045fdea053SToby Isaac /*@C
2605b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2606b004864fSMatthew G. Knepley 
260720f4b53cSBarry Smith   Logically Collective
2608b004864fSMatthew G. Knepley 
2609b004864fSMatthew G. Knepley   Input Parameters:
2610b004864fSMatthew G. Knepley + sym     - the section symmetries
2611b004864fSMatthew G. Knepley - stratum - the stratum value in the label that we are assigning symmetries for
2612b004864fSMatthew G. Knepley 
2613b004864fSMatthew G. Knepley   Output Parameters:
261420f4b53cSBarry Smith + size      - the number of dofs for points in the `stratum` of the label
261520f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
261620f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a ppoint in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
261720f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
261820f4b53cSBarry 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
2619b004864fSMatthew G. Knepley 
2620b004864fSMatthew G. Knepley   Level: developer
2621b004864fSMatthew G. Knepley 
262220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2623b004864fSMatthew G. Knepley @*/
2624d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2625d71ae5a4SJacob Faibussowitsch {
2626b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2627b004864fSMatthew G. Knepley   const char            *name;
2628b004864fSMatthew G. Knepley   PetscInt               i;
2629b004864fSMatthew G. Knepley 
2630b004864fSMatthew G. Knepley   PetscFunctionBegin;
2631b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2632b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2633b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2634b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2635b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2636b004864fSMatthew G. Knepley 
2637b004864fSMatthew G. Knepley     if (stratum == value) break;
2638b004864fSMatthew G. Knepley   }
26399566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2640b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
26419371c9d4SSatish Balay   if (size) {
26424f572ea9SToby Isaac     PetscAssertPointer(size, 3);
26439371c9d4SSatish Balay     *size = sl->sizes[i];
26449371c9d4SSatish Balay   }
26459371c9d4SSatish Balay   if (minOrient) {
26464f572ea9SToby Isaac     PetscAssertPointer(minOrient, 4);
26479371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
26489371c9d4SSatish Balay   }
26499371c9d4SSatish Balay   if (maxOrient) {
26504f572ea9SToby Isaac     PetscAssertPointer(maxOrient, 5);
26519371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
26529371c9d4SSatish Balay   }
26539371c9d4SSatish Balay   if (perms) {
26544f572ea9SToby Isaac     PetscAssertPointer(perms, 6);
26558e3a54c0SPierre Jolivet     *perms = PetscSafePointerPlusOffset(sl->perms[i], sl->minMaxOrients[i][0]);
26569371c9d4SSatish Balay   }
26579371c9d4SSatish Balay   if (rots) {
26584f572ea9SToby Isaac     PetscAssertPointer(rots, 7);
26598e3a54c0SPierre Jolivet     *rots = PetscSafePointerPlusOffset(sl->rots[i], sl->minMaxOrients[i][0]);
26609371c9d4SSatish Balay   }
26613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2662b004864fSMatthew G. Knepley }
2663b004864fSMatthew G. Knepley 
2664b004864fSMatthew G. Knepley /*@C
26655fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
26665fdea053SToby Isaac 
266720f4b53cSBarry Smith   Logically
26685fdea053SToby Isaac 
26695fdea053SToby Isaac   Input Parameters:
26705b5e7992SMatthew G. Knepley + sym       - the section symmetries
26715fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
267220f4b53cSBarry Smith . size      - the number of dofs for points in the `stratum` of the label
267320f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
267420f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a point in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
267520f4b53cSBarry Smith . mode      - how `sym` should copy the `perms` and `rots` arrays
267620f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
267720f4b53cSBarry 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
26785fdea053SToby Isaac 
26795fdea053SToby Isaac   Level: developer
26805fdea053SToby Isaac 
268120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
26825fdea053SToby Isaac @*/
2683d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2684d71ae5a4SJacob Faibussowitsch {
26855fdea053SToby Isaac   PetscSectionSym_Label *sl;
2686d67d17b1SMatthew G. Knepley   const char            *name;
2687d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
26885fdea053SToby Isaac 
26895fdea053SToby Isaac   PetscFunctionBegin;
26905fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
26915fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2692b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
26935fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
26945fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
26955fdea053SToby Isaac 
26965fdea053SToby Isaac     if (stratum == value) break;
26975fdea053SToby Isaac   }
26989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
269963a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
27005fdea053SToby Isaac   sl->sizes[i]            = size;
27015fdea053SToby Isaac   sl->modes[i]            = mode;
27025fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
27035fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
27045fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
27055fdea053SToby Isaac     if (perms) {
27065fdea053SToby Isaac       PetscInt **ownPerms;
27075fdea053SToby Isaac 
27089566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
27095fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
27105fdea053SToby Isaac         if (perms[j]) {
27119566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2712ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
27135fdea053SToby Isaac         }
27145fdea053SToby Isaac       }
27155fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
27165fdea053SToby Isaac     }
27175fdea053SToby Isaac     if (rots) {
27185fdea053SToby Isaac       PetscScalar **ownRots;
27195fdea053SToby Isaac 
27209566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
27215fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
27225fdea053SToby Isaac         if (rots[j]) {
27239566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2724ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
27255fdea053SToby Isaac         }
27265fdea053SToby Isaac       }
27275fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
27285fdea053SToby Isaac     }
27295fdea053SToby Isaac   } else {
27308e3a54c0SPierre Jolivet     sl->perms[i] = PetscSafePointerPlusOffset(perms, -minOrient);
27318e3a54c0SPierre Jolivet     sl->rots[i]  = PetscSafePointerPlusOffset(rots, -minOrient);
27325fdea053SToby Isaac   }
27333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27345fdea053SToby Isaac }
27355fdea053SToby Isaac 
2736d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2737d71ae5a4SJacob Faibussowitsch {
27385fdea053SToby Isaac   PetscInt               i, j, numStrata;
27395fdea053SToby Isaac   PetscSectionSym_Label *sl;
27405fdea053SToby Isaac   DMLabel                label;
27415fdea053SToby Isaac 
27425fdea053SToby Isaac   PetscFunctionBegin;
27435fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
27445fdea053SToby Isaac   numStrata = sl->numStrata;
27455fdea053SToby Isaac   label     = sl->label;
27465fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
27475fdea053SToby Isaac     PetscInt point = points[2 * i];
27485fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
27495fdea053SToby Isaac 
27505fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
27515fdea053SToby Isaac       if (label->validIS[j]) {
27525fdea053SToby Isaac         PetscInt k;
27535fdea053SToby Isaac 
27549566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j], point, &k));
27555fdea053SToby Isaac         if (k >= 0) break;
27565fdea053SToby Isaac       } else {
27575fdea053SToby Isaac         PetscBool has;
27585fdea053SToby Isaac 
27599566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
27605fdea053SToby Isaac         if (has) break;
27615fdea053SToby Isaac       }
27625fdea053SToby Isaac     }
27639371c9d4SSatish 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],
27649371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2765ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2766ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
27675fdea053SToby Isaac   }
27683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27695fdea053SToby Isaac }
27705fdea053SToby Isaac 
2771d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2772d71ae5a4SJacob Faibussowitsch {
2773b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2774b004864fSMatthew G. Knepley   IS                     valIS;
2775b004864fSMatthew G. Knepley   const PetscInt        *values;
2776b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2777b004864fSMatthew G. Knepley 
2778b004864fSMatthew G. Knepley   PetscFunctionBegin;
27799566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
27809566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
27819566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2782b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2783b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2784b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2785b004864fSMatthew G. Knepley     const PetscInt    **perms;
2786b004864fSMatthew G. Knepley     const PetscScalar **rots;
2787b004864fSMatthew G. Knepley 
27889566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
27899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2790b004864fSMatthew G. Knepley   }
27919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
27923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2793b004864fSMatthew G. Knepley }
2794b004864fSMatthew G. Knepley 
2795d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2796d71ae5a4SJacob Faibussowitsch {
2797b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2798b004864fSMatthew G. Knepley   DMLabel                dlabel;
2799b004864fSMatthew G. Knepley 
2800b004864fSMatthew G. Knepley   PetscFunctionBegin;
28019566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
28029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
28039566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
28049566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
28053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2806b004864fSMatthew G. Knepley }
2807b004864fSMatthew G. Knepley 
2808d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2809d71ae5a4SJacob Faibussowitsch {
28105fdea053SToby Isaac   PetscSectionSym_Label *sl;
28115fdea053SToby Isaac 
28125fdea053SToby Isaac   PetscFunctionBegin;
28134dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
28145fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2815b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2816b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
28175fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
28185fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
28195fdea053SToby Isaac   sym->data            = (void *)sl;
28203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28215fdea053SToby Isaac }
28225fdea053SToby Isaac 
28235fdea053SToby Isaac /*@
28245fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
28255fdea053SToby Isaac 
28265fdea053SToby Isaac   Collective
28275fdea053SToby Isaac 
28285fdea053SToby Isaac   Input Parameters:
28295fdea053SToby Isaac + comm  - the MPI communicator for the new symmetry
28305fdea053SToby Isaac - label - the label defining the strata
28315fdea053SToby Isaac 
28322fe279fdSBarry Smith   Output Parameter:
28335fdea053SToby Isaac . sym - the section symmetries
28345fdea053SToby Isaac 
28355fdea053SToby Isaac   Level: developer
28365fdea053SToby Isaac 
283720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
28385fdea053SToby Isaac @*/
2839d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2840d71ae5a4SJacob Faibussowitsch {
28415fdea053SToby Isaac   PetscFunctionBegin;
28429566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
28439566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
28449566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
28459566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
28463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28475fdea053SToby Isaac }
2848