xref: /petsc/src/dm/label/dmlabel.c (revision 4b7935335f3cfb2b5487d3666b47f5e65593ac47)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I      "petscdmlabel.h"   I*/
3ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h> /*I      "petscsection.h"   I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5ea844a1aSMatthew Knepley #include <petscsection.h>
6c58f1c22SToby Isaac 
79f6c5813SMatthew G. Knepley PetscFunctionList DMLabelList              = NULL;
89f6c5813SMatthew G. Knepley PetscBool         DMLabelRegisterAllCalled = PETSC_FALSE;
99f6c5813SMatthew G. Knepley 
10cc4c1da9SBarry Smith /*@
1120f4b53cSBarry Smith   DMLabelCreate - Create a `DMLabel` object, which is a multimap
12c58f1c22SToby Isaac 
135b5e7992SMatthew G. Knepley   Collective
145b5e7992SMatthew G. Knepley 
1560225df5SJacob Faibussowitsch   Input Parameters:
1620f4b53cSBarry Smith + comm - The communicator, usually `PETSC_COMM_SELF`
17d67d17b1SMatthew G. Knepley - name - The label name
18c58f1c22SToby Isaac 
1960225df5SJacob Faibussowitsch   Output Parameter:
2020f4b53cSBarry Smith . label - The `DMLabel`
21c58f1c22SToby Isaac 
22c58f1c22SToby Isaac   Level: beginner
23c58f1c22SToby Isaac 
2405ab7a9fSVaclav Hapla   Notes:
2520f4b53cSBarry Smith   The label name is actually usually the `PetscObject` name.
2620f4b53cSBarry Smith   One can get/set it with `PetscObjectGetName()`/`PetscObjectSetName()`.
2705ab7a9fSVaclav Hapla 
2820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`
29c58f1c22SToby Isaac @*/
30d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
31d71ae5a4SJacob Faibussowitsch {
32c58f1c22SToby Isaac   PetscFunctionBegin;
334f572ea9SToby Isaac   PetscAssertPointer(label, 3);
349566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
35c58f1c22SToby Isaac 
369566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*label, DMLABEL_CLASSID, "DMLabel", "DMLabel", "DM", comm, DMLabelDestroy, DMLabelView));
37c58f1c22SToby Isaac   (*label)->numStrata     = 0;
385aa44df4SToby Isaac   (*label)->defaultValue  = -1;
39c58f1c22SToby Isaac   (*label)->stratumValues = NULL;
40ad8374ffSToby Isaac   (*label)->validIS       = NULL;
41c58f1c22SToby Isaac   (*label)->stratumSizes  = NULL;
42c58f1c22SToby Isaac   (*label)->points        = NULL;
43c58f1c22SToby Isaac   (*label)->ht            = NULL;
44c58f1c22SToby Isaac   (*label)->pStart        = -1;
45c58f1c22SToby Isaac   (*label)->pEnd          = -1;
46c58f1c22SToby Isaac   (*label)->bt            = NULL;
479566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*label, name));
499f6c5813SMatthew G. Knepley   PetscCall(DMLabelSetType(*label, DMLABELCONCRETE));
503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
519f6c5813SMatthew G. Knepley }
529f6c5813SMatthew G. Knepley 
53cc4c1da9SBarry Smith /*@
549f6c5813SMatthew G. Knepley   DMLabelSetUp - SetUp a `DMLabel` object
559f6c5813SMatthew G. Knepley 
569f6c5813SMatthew G. Knepley   Collective
579f6c5813SMatthew G. Knepley 
5860225df5SJacob Faibussowitsch   Input Parameters:
599f6c5813SMatthew G. Knepley . label - The `DMLabel`
609f6c5813SMatthew G. Knepley 
619f6c5813SMatthew G. Knepley   Level: intermediate
629f6c5813SMatthew G. Knepley 
6320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
649f6c5813SMatthew G. Knepley @*/
659f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetUp(DMLabel label)
669f6c5813SMatthew G. Knepley {
679f6c5813SMatthew G. Knepley   PetscFunctionBegin;
689f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
699f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, setup);
703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71c58f1c22SToby Isaac }
72c58f1c22SToby Isaac 
73c58f1c22SToby Isaac /*
74c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
75c58f1c22SToby Isaac 
765b5e7992SMatthew G. Knepley   Not collective
775b5e7992SMatthew G. Knepley 
78c58f1c22SToby Isaac   Input parameter:
7920f4b53cSBarry Smith + label - The `DMLabel`
80c58f1c22SToby Isaac - v - The stratum value
81c58f1c22SToby Isaac 
82c58f1c22SToby Isaac   Output parameter:
8320f4b53cSBarry Smith . label - The `DMLabel` with stratum in sorted list format
84c58f1c22SToby Isaac 
85c58f1c22SToby Isaac   Level: developer
86c58f1c22SToby Isaac 
8720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
88c58f1c22SToby Isaac */
89d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
90d71ae5a4SJacob Faibussowitsch {
91277ea44aSLisandro Dalcin   IS       is;
92b9907514SLisandro Dalcin   PetscInt off = 0, *pointArray, p;
93c58f1c22SToby Isaac 
94c58f1c22SToby Isaac   PetscFunctionBegin;
954d86920dSPierre Jolivet   if ((PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) || label->readonly) PetscFunctionReturn(PETSC_SUCCESS);
961dca8a05SBarry Smith   PetscCheck(v >= 0 && v < label->numStrata, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeValid_Private", v);
979566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
999566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
1009566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
1019566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
102c58f1c22SToby Isaac   if (label->bt) {
103c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
104ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
10563a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
1069566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
107c58f1c22SToby Isaac     }
108c58f1c22SToby Isaac   }
109ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v] - 1] == pointArray[0] + label->stratumSizes[v] - 1) {
1109566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
1119566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
112ba2698f1SMatthew G. Knepley   } else {
1139566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
114ba2698f1SMatthew G. Knepley   }
115f622de60SMatthew G. Knepley   PetscCall(ISSetInfo(is, IS_SORTED, IS_LOCAL, PETSC_TRUE, PETSC_TRUE));
1169566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)is, "indices"));
117277ea44aSLisandro Dalcin   label->points[v]  = is;
118ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
1199566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
1203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121c58f1c22SToby Isaac }
122c58f1c22SToby Isaac 
123c58f1c22SToby Isaac /*
124c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
125c58f1c22SToby Isaac 
12620f4b53cSBarry Smith   Not Collective
1275b5e7992SMatthew G. Knepley 
128c58f1c22SToby Isaac   Input parameter:
12920f4b53cSBarry Smith . label - The `DMLabel`
130c58f1c22SToby Isaac 
131c58f1c22SToby Isaac   Output parameter:
13220f4b53cSBarry Smith . label - The `DMLabel` with all strata in sorted list format
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Level: developer
135c58f1c22SToby Isaac 
13620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
137c58f1c22SToby Isaac */
138d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
139d71ae5a4SJacob Faibussowitsch {
140c58f1c22SToby Isaac   PetscInt v;
141c58f1c22SToby Isaac 
142c58f1c22SToby Isaac   PetscFunctionBegin;
14348a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeValid_Private(label, v));
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145c58f1c22SToby Isaac }
146c58f1c22SToby Isaac 
147c58f1c22SToby Isaac /*
148c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
149c58f1c22SToby Isaac 
15020f4b53cSBarry Smith   Not Collective
1515b5e7992SMatthew G. Knepley 
152c58f1c22SToby Isaac   Input parameter:
15320f4b53cSBarry Smith + label - The `DMLabel`
154c58f1c22SToby Isaac - v - The stratum value
155c58f1c22SToby Isaac 
156c58f1c22SToby Isaac   Output parameter:
15720f4b53cSBarry Smith . label - The `DMLabel` with stratum in hash format
158c58f1c22SToby Isaac 
159c58f1c22SToby Isaac   Level: developer
160c58f1c22SToby Isaac 
16120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
162c58f1c22SToby Isaac */
163d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
164d71ae5a4SJacob Faibussowitsch {
165c58f1c22SToby Isaac   PetscInt        p;
166ad8374ffSToby Isaac   const PetscInt *points;
167c58f1c22SToby Isaac 
168c58f1c22SToby Isaac   PetscFunctionBegin;
1694d86920dSPierre Jolivet   if ((PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) || label->readonly) PetscFunctionReturn(PETSC_SUCCESS);
1701dca8a05SBarry Smith   PetscCheck(v >= 0 && v < label->numStrata, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeInvalid_Private", v);
171ad8374ffSToby Isaac   if (label->points[v]) {
1729566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
17348a46eb9SPierre Jolivet     for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
1749566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
175f4f49eeaSPierre Jolivet     PetscCall(ISDestroy(&label->points[v]));
176ad8374ffSToby Isaac   }
177ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
1783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
179c58f1c22SToby Isaac }
180c58f1c22SToby Isaac 
181d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelMakeAllInvalid_Internal(DMLabel label)
182d71ae5a4SJacob Faibussowitsch {
183695799ffSMatthew G. Knepley   PetscInt v;
184695799ffSMatthew G. Knepley 
185695799ffSMatthew G. Knepley   PetscFunctionBegin;
18648a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeInvalid_Private(label, v));
1873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
188695799ffSMatthew G. Knepley }
189695799ffSMatthew G. Knepley 
190b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
191b9907514SLisandro Dalcin   #define DMLABEL_LOOKUP_THRESHOLD 16
192b9907514SLisandro Dalcin #endif
193b9907514SLisandro Dalcin 
1949f6c5813SMatthew G. Knepley PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
195d71ae5a4SJacob Faibussowitsch {
1960c3c4a36SLisandro Dalcin   PetscInt v;
1970e79e033SBarry Smith 
1980c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1990e79e033SBarry Smith   *index = -1;
2009f6c5813SMatthew G. Knepley   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD || label->readonly) {
201b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
2029371c9d4SSatish Balay       if (label->stratumValues[v] == value) {
2039371c9d4SSatish Balay         *index = v;
2049371c9d4SSatish Balay         break;
2059371c9d4SSatish Balay       }
206b9907514SLisandro Dalcin   } else {
2079566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(label->hmap, value, index));
2080e79e033SBarry Smith   }
2099f6c5813SMatthew G. Knepley   if (PetscDefined(USE_DEBUG) && !label->readonly) { /* Check strata hash map consistency */
21090e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
2119566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(label->hmap, &len));
21208401ef6SPierre Jolivet     PetscCheck(len == label->numStrata, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
21390e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
2149566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(label->hmap, value, &loc));
21590e9b2aeSLisandro Dalcin     } else {
21690e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
2179371c9d4SSatish Balay         if (label->stratumValues[v] == value) {
2189371c9d4SSatish Balay           loc = v;
2199371c9d4SSatish Balay           break;
2209371c9d4SSatish Balay         }
22190e9b2aeSLisandro Dalcin     }
22208401ef6SPierre Jolivet     PetscCheck(loc == *index, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
22390e9b2aeSLisandro Dalcin   }
2243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2250c3c4a36SLisandro Dalcin }
2260c3c4a36SLisandro Dalcin 
227d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
228d71ae5a4SJacob Faibussowitsch {
229b9907514SLisandro Dalcin   PetscInt    v;
230b9907514SLisandro Dalcin   PetscInt   *tmpV;
231b9907514SLisandro Dalcin   PetscInt   *tmpS;
232b9907514SLisandro Dalcin   PetscHSetI *tmpH, ht;
233b9907514SLisandro Dalcin   IS         *tmpP, is;
234c58f1c22SToby Isaac   PetscBool  *tmpB;
235b9907514SLisandro Dalcin   PetscHMapI  hmap = label->hmap;
236c58f1c22SToby Isaac 
237c58f1c22SToby Isaac   PetscFunctionBegin;
238b9907514SLisandro Dalcin   v    = label->numStrata;
239b9907514SLisandro Dalcin   tmpV = label->stratumValues;
240b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
241b9907514SLisandro Dalcin   tmpH = label->ht;
242b9907514SLisandro Dalcin   tmpP = label->points;
243b9907514SLisandro Dalcin   tmpB = label->validIS;
2448e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2458e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2468e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2478e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2488e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2498e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpV), &tmpV));
2519566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpS), &tmpS));
2529f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc((v + 1) * sizeof(*tmpH), &tmpH));
2539f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc((v + 1) * sizeof(*tmpP), &tmpP));
2549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpB), &tmpB));
2559566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpV, oldV, v));
2569566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpS, oldS, v));
2579566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpH, oldH, v));
2589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpP, oldP, v));
2599566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpB, oldB, v));
2609566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldV));
2619566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldS));
2629566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldH));
2639566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldP));
2649566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldB));
2658e1f8cf0SLisandro Dalcin   }
266b9907514SLisandro Dalcin   label->numStrata     = v + 1;
267c58f1c22SToby Isaac   label->stratumValues = tmpV;
268c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
269c58f1c22SToby Isaac   label->ht            = tmpH;
270c58f1c22SToby Isaac   label->points        = tmpP;
271ad8374ffSToby Isaac   label->validIS       = tmpB;
2729566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
2739566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
2749566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(hmap, value, v));
275b9907514SLisandro Dalcin   tmpV[v] = value;
276b9907514SLisandro Dalcin   tmpS[v] = 0;
277b9907514SLisandro Dalcin   tmpH[v] = ht;
278b9907514SLisandro Dalcin   tmpP[v] = is;
279b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
2809566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
2810c3c4a36SLisandro Dalcin   *index = v;
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2830c3c4a36SLisandro Dalcin }
2840c3c4a36SLisandro Dalcin 
285d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
286d71ae5a4SJacob Faibussowitsch {
287b9907514SLisandro Dalcin   PetscFunctionBegin;
2889566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, index));
2899566063dSJacob Faibussowitsch   if (*index < 0) PetscCall(DMLabelNewStratum(label, value, index));
2903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
291b9907514SLisandro Dalcin }
292b9907514SLisandro Dalcin 
2939f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
294d71ae5a4SJacob Faibussowitsch {
2959e63cc69SVaclav Hapla   PetscFunctionBegin;
2969e63cc69SVaclav Hapla   *size = 0;
2973ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
2989f6c5813SMatthew G. Knepley   if (label->readonly || label->validIS[v]) {
2999e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
3009e63cc69SVaclav Hapla   } else {
3019566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(label->ht[v], size));
3029e63cc69SVaclav Hapla   }
3033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3049e63cc69SVaclav Hapla }
3059e63cc69SVaclav Hapla 
306b9907514SLisandro Dalcin /*@
30720f4b53cSBarry Smith   DMLabelAddStratum - Adds a new stratum value in a `DMLabel`
308b9907514SLisandro Dalcin 
309d8d19677SJose E. Roman   Input Parameters:
31020f4b53cSBarry Smith + label - The `DMLabel`
311b9907514SLisandro Dalcin - value - The stratum value
312b9907514SLisandro Dalcin 
313b9907514SLisandro Dalcin   Level: beginner
314b9907514SLisandro Dalcin 
31520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
316b9907514SLisandro Dalcin @*/
317d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
318d71ae5a4SJacob Faibussowitsch {
3190c3c4a36SLisandro Dalcin   PetscInt v;
3200c3c4a36SLisandro Dalcin 
3210c3c4a36SLisandro Dalcin   PetscFunctionBegin;
322d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
3239f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
3249566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
3253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326b9907514SLisandro Dalcin }
327b9907514SLisandro Dalcin 
328b9907514SLisandro Dalcin /*@
32920f4b53cSBarry Smith   DMLabelAddStrata - Adds new stratum values in a `DMLabel`
330b9907514SLisandro Dalcin 
33120f4b53cSBarry Smith   Not Collective
3325b5e7992SMatthew G. Knepley 
333d8d19677SJose E. Roman   Input Parameters:
33420f4b53cSBarry Smith + label         - The `DMLabel`
335b9907514SLisandro Dalcin . numStrata     - The number of stratum values
336b9907514SLisandro Dalcin - stratumValues - The stratum values
337b9907514SLisandro Dalcin 
338b9907514SLisandro Dalcin   Level: beginner
339b9907514SLisandro Dalcin 
34020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
341b9907514SLisandro Dalcin @*/
342d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
343d71ae5a4SJacob Faibussowitsch {
344b9907514SLisandro Dalcin   PetscInt *values, v;
345b9907514SLisandro Dalcin 
346b9907514SLisandro Dalcin   PetscFunctionBegin;
347b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
3484f572ea9SToby Isaac   if (numStrata) PetscAssertPointer(stratumValues, 3);
3499f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
3509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numStrata, &values));
3519566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(values, stratumValues, numStrata));
3529566063dSJacob Faibussowitsch   PetscCall(PetscSortRemoveDupsInt(&numStrata, values));
353b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
354b9907514SLisandro Dalcin     PetscInt   *tmpV;
355b9907514SLisandro Dalcin     PetscInt   *tmpS;
356b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
357b9907514SLisandro Dalcin     IS         *tmpP, is;
358b9907514SLisandro Dalcin     PetscBool  *tmpB;
359b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
360b9907514SLisandro Dalcin 
3619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpV));
3629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpS));
3639f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(numStrata, &tmpH));
3649f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(numStrata, &tmpP));
3659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpB));
366b9907514SLisandro Dalcin     label->numStrata     = numStrata;
367b9907514SLisandro Dalcin     label->stratumValues = tmpV;
368b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
369b9907514SLisandro Dalcin     label->ht            = tmpH;
370b9907514SLisandro Dalcin     label->points        = tmpP;
371b9907514SLisandro Dalcin     label->validIS       = tmpB;
372b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3739566063dSJacob Faibussowitsch       PetscCall(PetscHSetICreate(&ht));
3749566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
3759566063dSJacob Faibussowitsch       PetscCall(PetscHMapISet(hmap, values[v], v));
376b9907514SLisandro Dalcin       tmpV[v] = values[v];
377b9907514SLisandro Dalcin       tmpS[v] = 0;
378b9907514SLisandro Dalcin       tmpH[v] = ht;
379b9907514SLisandro Dalcin       tmpP[v] = is;
380b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
381b9907514SLisandro Dalcin     }
3829566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
383b9907514SLisandro Dalcin   } else {
38448a46eb9SPierre Jolivet     for (v = 0; v < numStrata; ++v) PetscCall(DMLabelAddStratum(label, values[v]));
385b9907514SLisandro Dalcin   }
3869566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
3873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388b9907514SLisandro Dalcin }
389b9907514SLisandro Dalcin 
390b9907514SLisandro Dalcin /*@
39120f4b53cSBarry Smith   DMLabelAddStrataIS - Adds new stratum values in a `DMLabel`
392b9907514SLisandro Dalcin 
39320f4b53cSBarry Smith   Not Collective
3945b5e7992SMatthew G. Knepley 
395d8d19677SJose E. Roman   Input Parameters:
39620f4b53cSBarry Smith + label   - The `DMLabel`
397b9907514SLisandro Dalcin - valueIS - Index set with stratum values
398b9907514SLisandro Dalcin 
399b9907514SLisandro Dalcin   Level: beginner
400b9907514SLisandro Dalcin 
40120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
402b9907514SLisandro Dalcin @*/
403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
404d71ae5a4SJacob Faibussowitsch {
405b9907514SLisandro Dalcin   PetscInt        numStrata;
406b9907514SLisandro Dalcin   const PetscInt *stratumValues;
407b9907514SLisandro Dalcin 
408b9907514SLisandro Dalcin   PetscFunctionBegin;
409b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
410b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
4119f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
4129566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(valueIS, &numStrata));
4139566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valueIS, &stratumValues));
4149566063dSJacob Faibussowitsch   PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
4153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
416c58f1c22SToby Isaac }
417c58f1c22SToby Isaac 
4189f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelView_Concrete_Ascii(DMLabel label, PetscViewer viewer)
419d71ae5a4SJacob Faibussowitsch {
420c58f1c22SToby Isaac   PetscInt    v;
421c58f1c22SToby Isaac   PetscMPIInt rank;
422c58f1c22SToby Isaac 
423c58f1c22SToby Isaac   PetscFunctionBegin;
4249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
4259566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
426c58f1c22SToby Isaac   if (label) {
427d67d17b1SMatthew G. Knepley     const char *name;
428d67d17b1SMatthew G. Knepley 
4299566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
4309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
43163a3b9bcSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", label->pStart, label->pEnd));
432c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
433c58f1c22SToby Isaac       const PetscInt  value = label->stratumValues[v];
434ad8374ffSToby Isaac       const PetscInt *points;
435c58f1c22SToby Isaac       PetscInt        p;
436c58f1c22SToby Isaac 
4379566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
43848a46eb9SPierre Jolivet       for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, points[p], value));
4399566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
440c58f1c22SToby Isaac     }
441c58f1c22SToby Isaac   }
4429566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4439566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445c58f1c22SToby Isaac }
446c58f1c22SToby Isaac 
44766976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelView_Concrete(DMLabel label, PetscViewer viewer)
4489f6c5813SMatthew G. Knepley {
4499f196a02SMartin Diehl   PetscBool isascii;
4509f6c5813SMatthew G. Knepley 
4519f6c5813SMatthew G. Knepley   PetscFunctionBegin;
4529f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4539f196a02SMartin Diehl   if (isascii) PetscCall(DMLabelView_Concrete_Ascii(label, viewer));
4543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4559f6c5813SMatthew G. Knepley }
4569f6c5813SMatthew G. Knepley 
457ffeef943SBarry Smith /*@
458c58f1c22SToby Isaac   DMLabelView - View the label
459c58f1c22SToby Isaac 
46020f4b53cSBarry Smith   Collective
4615b5e7992SMatthew G. Knepley 
462c58f1c22SToby Isaac   Input Parameters:
46320f4b53cSBarry Smith + label  - The `DMLabel`
46420f4b53cSBarry Smith - viewer - The `PetscViewer`
465c58f1c22SToby Isaac 
466c58f1c22SToby Isaac   Level: intermediate
467c58f1c22SToby Isaac 
46820f4b53cSBarry Smith .seealso: `DMLabel`, `PetscViewer`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
469c58f1c22SToby Isaac @*/
470d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
471d71ae5a4SJacob Faibussowitsch {
472c58f1c22SToby Isaac   PetscFunctionBegin;
473d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4749566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
475c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4769f6c5813SMatthew G. Knepley   PetscCall(DMLabelMakeAllValid_Private(label));
4779f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, view, viewer);
4783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
479c58f1c22SToby Isaac }
480c58f1c22SToby Isaac 
48184f0b6dfSMatthew G. Knepley /*@
482*4b793533SStefano Zampini   DMLabelViewFromOptions - View a `DMLabel` in a particular way based on a request in the options database
483*4b793533SStefano Zampini 
484*4b793533SStefano Zampini   Collective
485*4b793533SStefano Zampini 
486*4b793533SStefano Zampini   Input Parameters:
487*4b793533SStefano Zampini + label - the `DMLabel` object
488*4b793533SStefano Zampini . obj   - optional object that provides the prefix for the options database (if `NULL` then the prefix in `obj` is used)
489*4b793533SStefano Zampini - name  - option string that is used to activate viewing
490*4b793533SStefano Zampini 
491*4b793533SStefano Zampini   Level: intermediate
492*4b793533SStefano Zampini 
493*4b793533SStefano Zampini   Note:
494*4b793533SStefano Zampini   See `PetscObjectViewFromOptions()` for a list of values that can be provided in the options database to determine how the `DMLabel` is viewed
495*4b793533SStefano Zampini 
496*4b793533SStefano Zampini .seealso: [](ch_dmbase), `DMLabel`, `DMLabelView()`, `PetscObjectViewFromOptions()`, `DMLabelCreate()`
497*4b793533SStefano Zampini @*/
498*4b793533SStefano Zampini PetscErrorCode DMLabelViewFromOptions(DMLabel label, PeOp PetscObject obj, const char name[])
499*4b793533SStefano Zampini {
500*4b793533SStefano Zampini   PetscFunctionBegin;
501*4b793533SStefano Zampini   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
502*4b793533SStefano Zampini   PetscCall(PetscObjectViewFromOptions((PetscObject)label, obj, name));
503*4b793533SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
504*4b793533SStefano Zampini }
505*4b793533SStefano Zampini 
506*4b793533SStefano Zampini /*@
50720f4b53cSBarry Smith   DMLabelReset - Destroys internal data structures in a `DMLabel`
508d67d17b1SMatthew G. Knepley 
50920f4b53cSBarry Smith   Not Collective
5105b5e7992SMatthew G. Knepley 
511d67d17b1SMatthew G. Knepley   Input Parameter:
51220f4b53cSBarry Smith . label - The `DMLabel`
513d67d17b1SMatthew G. Knepley 
514d67d17b1SMatthew G. Knepley   Level: beginner
515d67d17b1SMatthew G. Knepley 
51620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`, `DMLabelCreate()`
517d67d17b1SMatthew G. Knepley @*/
518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelReset(DMLabel label)
519d71ae5a4SJacob Faibussowitsch {
520d67d17b1SMatthew G. Knepley   PetscInt v;
521d67d17b1SMatthew G. Knepley 
522d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
523d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
524d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
5259f6c5813SMatthew G. Knepley     if (label->ht[v]) PetscCall(PetscHSetIDestroy(&label->ht[v]));
5269566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
527d67d17b1SMatthew G. Knepley   }
528b9907514SLisandro Dalcin   label->numStrata = 0;
5299566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
5309566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
5319566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
5329566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
5339566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
5349566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
535b9907514SLisandro Dalcin   label->pStart = -1;
536b9907514SLisandro Dalcin   label->pEnd   = -1;
5379566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
5383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
539d67d17b1SMatthew G. Knepley }
540d67d17b1SMatthew G. Knepley 
541d67d17b1SMatthew G. Knepley /*@
54220f4b53cSBarry Smith   DMLabelDestroy - Destroys a `DMLabel`
54384f0b6dfSMatthew G. Knepley 
54420f4b53cSBarry Smith   Collective
5455b5e7992SMatthew G. Knepley 
54684f0b6dfSMatthew G. Knepley   Input Parameter:
54720f4b53cSBarry Smith . label - The `DMLabel`
54884f0b6dfSMatthew G. Knepley 
54984f0b6dfSMatthew G. Knepley   Level: beginner
55084f0b6dfSMatthew G. Knepley 
55120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelReset()`, `DMLabelCreate()`
55284f0b6dfSMatthew G. Knepley @*/
553d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
554d71ae5a4SJacob Faibussowitsch {
555c58f1c22SToby Isaac   PetscFunctionBegin;
5563ba16761SJacob Faibussowitsch   if (!*label) PetscFunctionReturn(PETSC_SUCCESS);
557f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 1);
558f4f49eeaSPierre Jolivet   if (--((PetscObject)*label)->refct > 0) {
5599371c9d4SSatish Balay     *label = NULL;
5603ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5619371c9d4SSatish Balay   }
5629566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5639566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5649566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
5653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
566c58f1c22SToby Isaac }
567c58f1c22SToby Isaac 
56866976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDuplicate_Concrete(DMLabel label, DMLabel *labelnew)
5699f6c5813SMatthew G. Knepley {
5709f6c5813SMatthew G. Knepley   PetscFunctionBegin;
5719f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
5729f6c5813SMatthew G. Knepley     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
573f4f49eeaSPierre Jolivet     PetscCall(PetscObjectReference((PetscObject)label->points[v]));
5749f6c5813SMatthew G. Knepley     (*labelnew)->points[v] = label->points[v];
5759f6c5813SMatthew G. Knepley   }
5769f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5779f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5799f6c5813SMatthew G. Knepley }
5809f6c5813SMatthew G. Knepley 
58184f0b6dfSMatthew G. Knepley /*@
58220f4b53cSBarry Smith   DMLabelDuplicate - Duplicates a `DMLabel`
58384f0b6dfSMatthew G. Knepley 
58420f4b53cSBarry Smith   Collective
5855b5e7992SMatthew G. Knepley 
58684f0b6dfSMatthew G. Knepley   Input Parameter:
58720f4b53cSBarry Smith . label - The `DMLabel`
58884f0b6dfSMatthew G. Knepley 
58984f0b6dfSMatthew G. Knepley   Output Parameter:
59020f4b53cSBarry Smith . labelnew - new label
59184f0b6dfSMatthew G. Knepley 
59284f0b6dfSMatthew G. Knepley   Level: intermediate
59384f0b6dfSMatthew G. Knepley 
59420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
59584f0b6dfSMatthew G. Knepley @*/
596d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
597d71ae5a4SJacob Faibussowitsch {
598d67d17b1SMatthew G. Knepley   const char *name;
599c58f1c22SToby Isaac 
600c58f1c22SToby Isaac   PetscFunctionBegin;
601d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6029566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
6039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
6049566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
605c58f1c22SToby Isaac 
606c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
6075aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
6088dcf10e8SMatthew G. Knepley   (*labelnew)->readonly     = label->readonly;
6099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
6109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
6119f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->ht));
6129f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->points));
6139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
6149f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
615c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
616c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
617b9907514SLisandro Dalcin     (*labelnew)->validIS[v]       = PETSC_TRUE;
618c58f1c22SToby Isaac   }
619c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
620c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
621c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
6229f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, duplicate, labelnew);
6233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
624c58f1c22SToby Isaac }
625c58f1c22SToby Isaac 
626609dae6eSVaclav Hapla /*@C
62720f4b53cSBarry Smith   DMLabelCompare - Compare two `DMLabel` objects
628609dae6eSVaclav Hapla 
62920f4b53cSBarry Smith   Collective; No Fortran Support
630609dae6eSVaclav Hapla 
631609dae6eSVaclav Hapla   Input Parameters:
632f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
63320f4b53cSBarry Smith . l0   - First `DMLabel`
63420f4b53cSBarry Smith - l1   - Second `DMLabel`
635609dae6eSVaclav Hapla 
636a4e35b19SJacob Faibussowitsch   Output Parameters:
6375efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
6385efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
639609dae6eSVaclav Hapla 
640609dae6eSVaclav Hapla   Level: intermediate
641609dae6eSVaclav Hapla 
642609dae6eSVaclav Hapla   Notes:
6435efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
64420f4b53cSBarry Smith   If it is passed as `NULL` and difference is found, an error is thrown on all processes.
64520f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
646609dae6eSVaclav Hapla 
6475efe38ccSVaclav Hapla   The output message is set independently on each rank.
64820f4b53cSBarry Smith   It is set to `NULL` if no difference was found on the current rank. It must be freed by user.
64920f4b53cSBarry Smith   If message is passed as `NULL` and difference is found, the difference description is printed to stderr in synchronized manner.
65020f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
651609dae6eSVaclav Hapla 
652609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
653609dae6eSVaclav Hapla 
65420f4b53cSBarry Smith   The communicator needs to be specified because currently `DMLabel` can live on `PETSC_COMM_SELF` even if the underlying `DM` is parallel.
6555efe38ccSVaclav Hapla 
656a3b724e8SBarry Smith   Developer Note:
657a3b724e8SBarry Smith   Fortran stub cannot be generated automatically because `message` must be freed with `PetscFree()`
658a3b724e8SBarry Smith 
65920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
660609dae6eSVaclav Hapla @*/
661d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
662d71ae5a4SJacob Faibussowitsch {
663609dae6eSVaclav Hapla   const char *name0, *name1;
664609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6655efe38ccSVaclav Hapla   PetscBool   eq;
6665efe38ccSVaclav Hapla   PetscMPIInt rank;
667609dae6eSVaclav Hapla 
668609dae6eSVaclav Hapla   PetscFunctionBegin;
6695efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6705efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6714f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 4);
6724f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 5);
6739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6749566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6759566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
676609dae6eSVaclav Hapla   {
677609dae6eSVaclav Hapla     PetscInt v0, v1;
678609dae6eSVaclav Hapla 
6799566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6809566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6815efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
68248a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Default value of DMLabel l0 \"%s\" = %" PetscInt_FMT " != %" PetscInt_FMT " = Default value of DMLabel l1 \"%s\"", name0, v0, v1, name1));
6835440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPI_C_BOOL, MPI_LAND, comm));
6845efe38ccSVaclav Hapla     if (!eq) goto finish;
685609dae6eSVaclav Hapla   }
686609dae6eSVaclav Hapla   {
687609dae6eSVaclav Hapla     IS is0, is1;
688609dae6eSVaclav Hapla 
6899566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6909566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6919566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6939566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
69448a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
6955440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPI_C_BOOL, MPI_LAND, comm));
6965efe38ccSVaclav Hapla     if (!eq) goto finish;
697609dae6eSVaclav Hapla   }
698609dae6eSVaclav Hapla   {
699609dae6eSVaclav Hapla     PetscInt i, nValues;
700609dae6eSVaclav Hapla 
7019566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
702609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
703609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
704609dae6eSVaclav Hapla       PetscInt       n;
705609dae6eSVaclav Hapla       IS             is0, is1;
706609dae6eSVaclav Hapla 
7079566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
708609dae6eSVaclav Hapla       if (!n) continue;
7099566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
7109566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
7119566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
7129566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
7139566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
7145efe38ccSVaclav Hapla       if (!eq) {
71563a3b9bcSJacob Faibussowitsch         PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum #%" PetscInt_FMT " with value %" PetscInt_FMT " contains different points in DMLabel l0 \"%s\" and DMLabel l1 \"%s\"", i, v, name0, name1));
7165efe38ccSVaclav Hapla         break;
717609dae6eSVaclav Hapla       }
718609dae6eSVaclav Hapla     }
7195440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPI_C_BOOL, MPI_LAND, comm));
720609dae6eSVaclav Hapla   }
721609dae6eSVaclav Hapla finish:
7225efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
723609dae6eSVaclav Hapla   if (message) {
724609dae6eSVaclav Hapla     *message = NULL;
72548a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
7265efe38ccSVaclav Hapla   } else {
72748a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
7289566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
7295efe38ccSVaclav Hapla   }
7305efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
7315efe38ccSVaclav Hapla   if (equal) *equal = eq;
73263a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
7333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
734609dae6eSVaclav Hapla }
735609dae6eSVaclav Hapla 
736c6a43d28SMatthew G. Knepley /*@
737c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
738c6a43d28SMatthew G. Knepley 
73920f4b53cSBarry Smith   Not Collective
7405b5e7992SMatthew G. Knepley 
741c6a43d28SMatthew G. Knepley   Input Parameter:
74220f4b53cSBarry Smith . label - The `DMLabel`
743c6a43d28SMatthew G. Knepley 
744c6a43d28SMatthew G. Knepley   Level: intermediate
745c6a43d28SMatthew G. Knepley 
74620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
747c6a43d28SMatthew G. Knepley @*/
748d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
749d71ae5a4SJacob Faibussowitsch {
7501690c2aeSBarry Smith   PetscInt pStart = PETSC_INT_MAX, pEnd = -1, v;
751c6a43d28SMatthew G. Knepley 
752c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
753c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7549566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
755c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
756c6a43d28SMatthew G. Knepley     const PetscInt *points;
757c6a43d28SMatthew G. Knepley     PetscInt        i;
758c6a43d28SMatthew G. Knepley 
7599566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
760c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
761c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
762c6a43d28SMatthew G. Knepley 
763c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
764c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
765c6a43d28SMatthew G. Knepley     }
7669566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
767c6a43d28SMatthew G. Knepley   }
7681690c2aeSBarry Smith   label->pStart = pStart == PETSC_INT_MAX ? -1 : pStart;
769c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7709566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
7713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
772c6a43d28SMatthew G. Knepley }
773c6a43d28SMatthew G. Knepley 
774c6a43d28SMatthew G. Knepley /*@
775c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
776c6a43d28SMatthew G. Knepley 
77720f4b53cSBarry Smith   Not Collective
7785b5e7992SMatthew G. Knepley 
779c6a43d28SMatthew G. Knepley   Input Parameters:
78020f4b53cSBarry Smith + label  - The `DMLabel`
781c6a43d28SMatthew G. Knepley . pStart - The smallest point
782c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
783c6a43d28SMatthew G. Knepley 
784c6a43d28SMatthew G. Knepley   Level: intermediate
785c6a43d28SMatthew G. Knepley 
78620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
787c6a43d28SMatthew G. Knepley @*/
788d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
789d71ae5a4SJacob Faibussowitsch {
790c58f1c22SToby Isaac   PetscInt v;
791c58f1c22SToby Isaac 
792c58f1c22SToby Isaac   PetscFunctionBegin;
793d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7949566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7959566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
796c58f1c22SToby Isaac   label->pStart = pStart;
797c58f1c22SToby Isaac   label->pEnd   = pEnd;
798c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7999566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
800c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
8019f6c5813SMatthew G. Knepley     IS              pointIS;
802ad8374ffSToby Isaac     const PetscInt *points;
803c58f1c22SToby Isaac     PetscInt        i;
804c58f1c22SToby Isaac 
8059f6c5813SMatthew G. Knepley     PetscUseTypeMethod(label, getstratumis, v, &pointIS);
8069f6c5813SMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
807c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
808ad8374ffSToby Isaac       const PetscInt point = points[i];
809c58f1c22SToby Isaac 
8109f6c5813SMatthew G. Knepley       PetscCheck(!(point < pStart) && !(point >= pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " in stratum %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->stratumValues[v], pStart, pEnd);
8119566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
812c58f1c22SToby Isaac     }
8139566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
8149f6c5813SMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
815c58f1c22SToby Isaac   }
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817c58f1c22SToby Isaac }
818c58f1c22SToby Isaac 
819c6a43d28SMatthew G. Knepley /*@
820c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
821c6a43d28SMatthew G. Knepley 
82220f4b53cSBarry Smith   Not Collective
8235b5e7992SMatthew G. Knepley 
824c6a43d28SMatthew G. Knepley   Input Parameter:
82520f4b53cSBarry Smith . label - the `DMLabel`
826c6a43d28SMatthew G. Knepley 
827c6a43d28SMatthew G. Knepley   Level: intermediate
828c6a43d28SMatthew G. Knepley 
82920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
830c6a43d28SMatthew G. Knepley @*/
831d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
832d71ae5a4SJacob Faibussowitsch {
833c58f1c22SToby Isaac   PetscFunctionBegin;
834d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
835c58f1c22SToby Isaac   label->pStart = -1;
836c58f1c22SToby Isaac   label->pEnd   = -1;
8379566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
8383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
839c58f1c22SToby Isaac }
840c58f1c22SToby Isaac 
841c58f1c22SToby Isaac /*@
842c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
843c6a43d28SMatthew G. Knepley 
84420f4b53cSBarry Smith   Not Collective
8455b5e7992SMatthew G. Knepley 
846c6a43d28SMatthew G. Knepley   Input Parameter:
84720f4b53cSBarry Smith . label - the `DMLabel`
848c6a43d28SMatthew G. Knepley 
849c6a43d28SMatthew G. Knepley   Output Parameters:
850c6a43d28SMatthew G. Knepley + pStart - The smallest point
851c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
852c6a43d28SMatthew G. Knepley 
853c6a43d28SMatthew G. Knepley   Level: intermediate
854c6a43d28SMatthew G. Knepley 
85520f4b53cSBarry Smith   Note:
85620f4b53cSBarry Smith   This will compute an index for the label if one does not exist.
85720f4b53cSBarry Smith 
85820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
859c6a43d28SMatthew G. Knepley @*/
860d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
861d71ae5a4SJacob Faibussowitsch {
862c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
863c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8649566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
865c6a43d28SMatthew G. Knepley   if (pStart) {
8664f572ea9SToby Isaac     PetscAssertPointer(pStart, 2);
867c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
868c6a43d28SMatthew G. Knepley   }
869c6a43d28SMatthew G. Knepley   if (pEnd) {
8704f572ea9SToby Isaac     PetscAssertPointer(pEnd, 3);
871c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
872c6a43d28SMatthew G. Knepley   }
8733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
874c6a43d28SMatthew G. Knepley }
875c6a43d28SMatthew G. Knepley 
876c6a43d28SMatthew G. Knepley /*@
877c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
878c58f1c22SToby Isaac 
87920f4b53cSBarry Smith   Not Collective
8805b5e7992SMatthew G. Knepley 
881c58f1c22SToby Isaac   Input Parameters:
88220f4b53cSBarry Smith + label - the `DMLabel`
883c58f1c22SToby Isaac - value - the value
884c58f1c22SToby Isaac 
885c58f1c22SToby Isaac   Output Parameter:
886c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
887c58f1c22SToby Isaac 
888c58f1c22SToby Isaac   Level: developer
889c58f1c22SToby Isaac 
89020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
891c58f1c22SToby Isaac @*/
892d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
893d71ae5a4SJacob Faibussowitsch {
894c58f1c22SToby Isaac   PetscInt v;
895c58f1c22SToby Isaac 
896c58f1c22SToby Isaac   PetscFunctionBegin;
897d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8984f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
8999566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
9000c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
9013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
902c58f1c22SToby Isaac }
903c58f1c22SToby Isaac 
904c58f1c22SToby Isaac /*@
905c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
906c58f1c22SToby Isaac 
90720f4b53cSBarry Smith   Not Collective
9085b5e7992SMatthew G. Knepley 
909c58f1c22SToby Isaac   Input Parameters:
91020f4b53cSBarry Smith + label - the `DMLabel`
911c58f1c22SToby Isaac - point - the point
912c58f1c22SToby Isaac 
913c58f1c22SToby Isaac   Output Parameter:
914c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
915c58f1c22SToby Isaac 
916c58f1c22SToby Isaac   Level: developer
917c58f1c22SToby Isaac 
91820f4b53cSBarry Smith   Note:
91920f4b53cSBarry Smith   The user must call `DMLabelCreateIndex()` before this function.
92020f4b53cSBarry Smith 
92120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
922c58f1c22SToby Isaac @*/
923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
924d71ae5a4SJacob Faibussowitsch {
925c58f1c22SToby Isaac   PetscFunctionBeginHot;
926d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9274f572ea9SToby Isaac   PetscAssertPointer(contains, 3);
9289566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
92976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
93028b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
93163a3b9bcSJacob 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);
93276bd3646SJed Brown   }
933c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
9343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
935c58f1c22SToby Isaac }
936c58f1c22SToby Isaac 
937c58f1c22SToby Isaac /*@
938c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
939c58f1c22SToby Isaac 
94020f4b53cSBarry Smith   Not Collective
9415b5e7992SMatthew G. Knepley 
942c58f1c22SToby Isaac   Input Parameters:
94320f4b53cSBarry Smith + label - the `DMLabel`
944c58f1c22SToby Isaac . value - the stratum value
945c58f1c22SToby Isaac - point - the point
946c58f1c22SToby Isaac 
947c58f1c22SToby Isaac   Output Parameter:
948c58f1c22SToby Isaac . contains - true if the stratum contains the point
949c58f1c22SToby Isaac 
950c58f1c22SToby Isaac   Level: intermediate
951c58f1c22SToby Isaac 
95220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
953c58f1c22SToby Isaac @*/
954d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
955d71ae5a4SJacob Faibussowitsch {
9560c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
957d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9584f572ea9SToby Isaac   PetscAssertPointer(contains, 4);
959cffad2c9SToby Isaac   if (value == label->defaultValue) {
960cffad2c9SToby Isaac     PetscInt pointVal;
9610c3c4a36SLisandro Dalcin 
962cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
963cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
964cffad2c9SToby Isaac   } else {
965cffad2c9SToby Isaac     PetscInt v;
966cffad2c9SToby Isaac 
967cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
968cffad2c9SToby Isaac     if (v >= 0) {
9699f6c5813SMatthew G. Knepley       if (label->validIS[v] || label->readonly) {
9709f6c5813SMatthew G. Knepley         IS       is;
971c58f1c22SToby Isaac         PetscInt i;
972c58f1c22SToby Isaac 
9739f6c5813SMatthew G. Knepley         PetscUseTypeMethod(label, getstratumis, v, &is);
9742b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(is, point, &i));
9759f6c5813SMatthew G. Knepley         PetscCall(ISDestroy(&is));
976cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
977c58f1c22SToby Isaac       } else {
978cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
979cffad2c9SToby Isaac       }
980cffad2c9SToby Isaac     } else { // value is not present
981cffad2c9SToby Isaac       *contains = PETSC_FALSE;
982cffad2c9SToby Isaac     }
983c58f1c22SToby Isaac   }
9843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
985c58f1c22SToby Isaac }
986c58f1c22SToby Isaac 
98784f0b6dfSMatthew G. Knepley /*@
98820f4b53cSBarry Smith   DMLabelGetDefaultValue - Get the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9895aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9905aa44df4SToby Isaac 
99120f4b53cSBarry Smith   Not Collective
9925b5e7992SMatthew G. Knepley 
99360225df5SJacob Faibussowitsch   Input Parameter:
99420f4b53cSBarry Smith . label - a `DMLabel` object
9955aa44df4SToby Isaac 
99660225df5SJacob Faibussowitsch   Output Parameter:
9975aa44df4SToby Isaac . defaultValue - the default value
9985aa44df4SToby Isaac 
9995aa44df4SToby Isaac   Level: beginner
10005aa44df4SToby Isaac 
100120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
100284f0b6dfSMatthew G. Knepley @*/
1003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
1004d71ae5a4SJacob Faibussowitsch {
10055aa44df4SToby Isaac   PetscFunctionBegin;
1006d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10075aa44df4SToby Isaac   *defaultValue = label->defaultValue;
10083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10095aa44df4SToby Isaac }
10105aa44df4SToby Isaac 
101184f0b6dfSMatthew G. Knepley /*@
101220f4b53cSBarry Smith   DMLabelSetDefaultValue - Set the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
10135aa44df4SToby Isaac   When a label is created, it is initialized to -1.
10145aa44df4SToby Isaac 
101520f4b53cSBarry Smith   Not Collective
10165b5e7992SMatthew G. Knepley 
101760225df5SJacob Faibussowitsch   Input Parameter:
101820f4b53cSBarry Smith . label - a `DMLabel` object
10195aa44df4SToby Isaac 
102060225df5SJacob Faibussowitsch   Output Parameter:
10215aa44df4SToby Isaac . defaultValue - the default value
10225aa44df4SToby Isaac 
10235aa44df4SToby Isaac   Level: beginner
10245aa44df4SToby Isaac 
102520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
102684f0b6dfSMatthew G. Knepley @*/
1027d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1028d71ae5a4SJacob Faibussowitsch {
10295aa44df4SToby Isaac   PetscFunctionBegin;
1030d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10315aa44df4SToby Isaac   label->defaultValue = defaultValue;
10323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10335aa44df4SToby Isaac }
10345aa44df4SToby Isaac 
1035c58f1c22SToby Isaac /*@
103620f4b53cSBarry Smith   DMLabelGetValue - Return the value a label assigns to a point, or the label's default value (which is initially -1, and can be changed with
103720f4b53cSBarry Smith   `DMLabelSetDefaultValue()`)
1038c58f1c22SToby Isaac 
103920f4b53cSBarry Smith   Not Collective
10405b5e7992SMatthew G. Knepley 
1041c58f1c22SToby Isaac   Input Parameters:
104220f4b53cSBarry Smith + label - the `DMLabel`
1043c58f1c22SToby Isaac - point - the point
1044c58f1c22SToby Isaac 
1045c58f1c22SToby Isaac   Output Parameter:
10468e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
1047c58f1c22SToby Isaac 
1048c58f1c22SToby Isaac   Level: intermediate
1049c58f1c22SToby Isaac 
105020f4b53cSBarry Smith   Note:
105120f4b53cSBarry Smith   A label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.
105220f4b53cSBarry Smith   Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
105320f4b53cSBarry Smith 
105420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1055c58f1c22SToby Isaac @*/
1056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1057d71ae5a4SJacob Faibussowitsch {
1058c58f1c22SToby Isaac   PetscInt v;
1059c58f1c22SToby Isaac 
10600c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
1061d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10624f572ea9SToby Isaac   PetscAssertPointer(value, 3);
10635aa44df4SToby Isaac   *value = label->defaultValue;
1064c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
10659f6c5813SMatthew G. Knepley     if (label->validIS[v] || label->readonly) {
10669f6c5813SMatthew G. Knepley       IS       is;
1067c58f1c22SToby Isaac       PetscInt i;
1068c58f1c22SToby Isaac 
10699f6c5813SMatthew G. Knepley       PetscUseTypeMethod(label, getstratumis, v, &is);
10702b4d18a0SMatthew G. Knepley       PetscCall(ISLocate(label->points[v], point, &i));
10719f6c5813SMatthew G. Knepley       PetscCall(ISDestroy(&is));
1072c58f1c22SToby Isaac       if (i >= 0) {
1073c58f1c22SToby Isaac         *value = label->stratumValues[v];
1074c58f1c22SToby Isaac         break;
1075c58f1c22SToby Isaac       }
1076c58f1c22SToby Isaac     } else {
1077c58f1c22SToby Isaac       PetscBool has;
1078c58f1c22SToby Isaac 
10799566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1080c58f1c22SToby Isaac       if (has) {
1081c58f1c22SToby Isaac         *value = label->stratumValues[v];
1082c58f1c22SToby Isaac         break;
1083c58f1c22SToby Isaac       }
1084c58f1c22SToby Isaac     }
1085c58f1c22SToby Isaac   }
10863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1087c58f1c22SToby Isaac }
1088c58f1c22SToby Isaac 
1089c58f1c22SToby Isaac /*@
109020f4b53cSBarry Smith   DMLabelSetValue - Set the value a label assigns to a point.  If the value is the same as the label's default value (which is initially -1, and can
109120f4b53cSBarry Smith   be changed with `DMLabelSetDefaultValue()` to something different), then this function will do nothing.
1092c58f1c22SToby Isaac 
109320f4b53cSBarry Smith   Not Collective
10945b5e7992SMatthew G. Knepley 
1095c58f1c22SToby Isaac   Input Parameters:
109620f4b53cSBarry Smith + label - the `DMLabel`
1097c58f1c22SToby Isaac . point - the point
1098c58f1c22SToby Isaac - value - The point value
1099c58f1c22SToby Isaac 
1100c58f1c22SToby Isaac   Level: intermediate
1101c58f1c22SToby Isaac 
110220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1103c58f1c22SToby Isaac @*/
1104d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1105d71ae5a4SJacob Faibussowitsch {
1106c58f1c22SToby Isaac   PetscInt v;
1107c58f1c22SToby Isaac 
1108c58f1c22SToby Isaac   PetscFunctionBegin;
1109d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11100c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11113ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11129f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11139566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1114c58f1c22SToby Isaac   /* Set key */
11159566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11169566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
11173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1118c58f1c22SToby Isaac }
1119c58f1c22SToby Isaac 
1120c58f1c22SToby Isaac /*@
1121c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1122c58f1c22SToby Isaac 
112320f4b53cSBarry Smith   Not Collective
11245b5e7992SMatthew G. Knepley 
1125c58f1c22SToby Isaac   Input Parameters:
112620f4b53cSBarry Smith + label - the `DMLabel`
1127c58f1c22SToby Isaac . point - the point
1128c58f1c22SToby Isaac - value - The point value
1129c58f1c22SToby Isaac 
1130c58f1c22SToby Isaac   Level: intermediate
1131c58f1c22SToby Isaac 
113220f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1133c58f1c22SToby Isaac @*/
1134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1135d71ae5a4SJacob Faibussowitsch {
1136ad8374ffSToby Isaac   PetscInt v;
1137c58f1c22SToby Isaac 
1138c58f1c22SToby Isaac   PetscFunctionBegin;
1139d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11409f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1141c58f1c22SToby Isaac   /* Find label value */
11429566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
11433ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
11440c3c4a36SLisandro Dalcin 
1145eeed21e7SToby Isaac   if (label->bt) {
114663a3b9bcSJacob 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);
11479566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1148eeed21e7SToby Isaac   }
11490c3c4a36SLisandro Dalcin 
11500c3c4a36SLisandro Dalcin   /* Delete key */
11519566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11529566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
11533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1154c58f1c22SToby Isaac }
1155c58f1c22SToby Isaac 
1156c58f1c22SToby Isaac /*@
115720f4b53cSBarry Smith   DMLabelInsertIS - Set all points in the `IS` to a value
1158c58f1c22SToby Isaac 
115920f4b53cSBarry Smith   Not Collective
11605b5e7992SMatthew G. Knepley 
1161c58f1c22SToby Isaac   Input Parameters:
116220f4b53cSBarry Smith + label - the `DMLabel`
11632fe279fdSBarry Smith . is    - the point `IS`
1164c58f1c22SToby Isaac - value - The point value
1165c58f1c22SToby Isaac 
1166c58f1c22SToby Isaac   Level: intermediate
1167c58f1c22SToby Isaac 
116820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1169c58f1c22SToby Isaac @*/
1170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1171d71ae5a4SJacob Faibussowitsch {
11720c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1173c58f1c22SToby Isaac   const PetscInt *points;
1174c58f1c22SToby Isaac 
1175c58f1c22SToby Isaac   PetscFunctionBegin;
1176d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1177c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11780c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11793ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11809f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11819566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11820c3c4a36SLisandro Dalcin   /* Set keys */
11839566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11849566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11859566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11869566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11879566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
11883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1189c58f1c22SToby Isaac }
1190c58f1c22SToby Isaac 
119184f0b6dfSMatthew G. Knepley /*@
119220f4b53cSBarry Smith   DMLabelGetNumValues - Get the number of values that the `DMLabel` takes
119384f0b6dfSMatthew G. Knepley 
119420f4b53cSBarry Smith   Not Collective
11955b5e7992SMatthew G. Knepley 
119684f0b6dfSMatthew G. Knepley   Input Parameter:
119720f4b53cSBarry Smith . label - the `DMLabel`
119884f0b6dfSMatthew G. Knepley 
119901d2d390SJose E. Roman   Output Parameter:
120084f0b6dfSMatthew G. Knepley . numValues - the number of values
120184f0b6dfSMatthew G. Knepley 
120284f0b6dfSMatthew G. Knepley   Level: intermediate
120384f0b6dfSMatthew G. Knepley 
120420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
120584f0b6dfSMatthew G. Knepley @*/
1206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1207d71ae5a4SJacob Faibussowitsch {
1208c58f1c22SToby Isaac   PetscFunctionBegin;
1209d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12104f572ea9SToby Isaac   PetscAssertPointer(numValues, 2);
1211c58f1c22SToby Isaac   *numValues = label->numStrata;
12123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1213c58f1c22SToby Isaac }
1214c58f1c22SToby Isaac 
121584f0b6dfSMatthew G. Knepley /*@
121620f4b53cSBarry Smith   DMLabelGetValueIS - Get an `IS` of all values that the `DMlabel` takes
121784f0b6dfSMatthew G. Knepley 
121820f4b53cSBarry Smith   Not Collective
12195b5e7992SMatthew G. Knepley 
122084f0b6dfSMatthew G. Knepley   Input Parameter:
122120f4b53cSBarry Smith . label - the `DMLabel`
122284f0b6dfSMatthew G. Knepley 
122301d2d390SJose E. Roman   Output Parameter:
122460225df5SJacob Faibussowitsch . values - the value `IS`
122584f0b6dfSMatthew G. Knepley 
122684f0b6dfSMatthew G. Knepley   Level: intermediate
122784f0b6dfSMatthew G. Knepley 
12281d04cbbeSVaclav Hapla   Notes:
122920f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
123020f4b53cSBarry Smith   Strata which are allocated but empty [`DMLabelGetStratumSize()` yields 0] are counted.
123120f4b53cSBarry Smith   If you need to count only nonempty strata, use `DMLabelGetNonEmptyStratumValuesIS()`.
12321d04cbbeSVaclav Hapla 
123320f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
123484f0b6dfSMatthew G. Knepley @*/
1235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1236d71ae5a4SJacob Faibussowitsch {
1237c58f1c22SToby Isaac   PetscFunctionBegin;
1238d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12394f572ea9SToby Isaac   PetscAssertPointer(values, 2);
12409566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1242c58f1c22SToby Isaac }
1243c58f1c22SToby Isaac 
124484f0b6dfSMatthew G. Knepley /*@
12458696263dSMatthew G. Knepley   DMLabelGetValueBounds - Return the smallest and largest value in the label
12468696263dSMatthew G. Knepley 
12478696263dSMatthew G. Knepley   Not Collective
12488696263dSMatthew G. Knepley 
12498696263dSMatthew G. Knepley   Input Parameter:
12508696263dSMatthew G. Knepley . label - the `DMLabel`
12518696263dSMatthew G. Knepley 
12528696263dSMatthew G. Knepley   Output Parameters:
12538696263dSMatthew G. Knepley + minValue - The smallest value
12548696263dSMatthew G. Knepley - maxValue - The largest value
12558696263dSMatthew G. Knepley 
12568696263dSMatthew G. Knepley   Level: intermediate
12578696263dSMatthew G. Knepley 
12588696263dSMatthew G. Knepley .seealso: `DMLabel`, `DM`, `DMLabelGetBounds()`, `DMLabelGetValue()`, `DMLabelSetValue()`
12598696263dSMatthew G. Knepley @*/
12608696263dSMatthew G. Knepley PetscErrorCode DMLabelGetValueBounds(DMLabel label, PetscInt *minValue, PetscInt *maxValue)
12618696263dSMatthew G. Knepley {
12621690c2aeSBarry Smith   PetscInt min = PETSC_INT_MAX, max = PETSC_INT_MIN;
12638696263dSMatthew G. Knepley 
12648696263dSMatthew G. Knepley   PetscFunctionBegin;
12658696263dSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12668696263dSMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
12678696263dSMatthew G. Knepley     min = PetscMin(min, label->stratumValues[v]);
12688696263dSMatthew G. Knepley     max = PetscMax(max, label->stratumValues[v]);
12698696263dSMatthew G. Knepley   }
12708696263dSMatthew G. Knepley   if (minValue) {
12718696263dSMatthew G. Knepley     PetscAssertPointer(minValue, 2);
12728696263dSMatthew G. Knepley     *minValue = min;
12738696263dSMatthew G. Knepley   }
12748696263dSMatthew G. Knepley   if (maxValue) {
12758696263dSMatthew G. Knepley     PetscAssertPointer(maxValue, 3);
12768696263dSMatthew G. Knepley     *maxValue = max;
12778696263dSMatthew G. Knepley   }
12788696263dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
12798696263dSMatthew G. Knepley }
12808696263dSMatthew G. Knepley 
12818696263dSMatthew G. Knepley /*@
128220f4b53cSBarry Smith   DMLabelGetNonEmptyStratumValuesIS - Get an `IS` of all values that the `DMlabel` takes
12831d04cbbeSVaclav Hapla 
128420f4b53cSBarry Smith   Not Collective
12851d04cbbeSVaclav Hapla 
12861d04cbbeSVaclav Hapla   Input Parameter:
128720f4b53cSBarry Smith . label - the `DMLabel`
12881d04cbbeSVaclav Hapla 
1289d5b43468SJose E. Roman   Output Parameter:
129060225df5SJacob Faibussowitsch . values - the value `IS`
12911d04cbbeSVaclav Hapla 
12921d04cbbeSVaclav Hapla   Level: intermediate
12931d04cbbeSVaclav Hapla 
12941d04cbbeSVaclav Hapla   Notes:
129520f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
129620f4b53cSBarry Smith   This is similar to `DMLabelGetValueIS()` but counts only nonempty strata.
12971d04cbbeSVaclav Hapla 
129820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
12991d04cbbeSVaclav Hapla @*/
1300d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1301d71ae5a4SJacob Faibussowitsch {
13021d04cbbeSVaclav Hapla   PetscInt  i, j;
13031d04cbbeSVaclav Hapla   PetscInt *valuesArr;
13041d04cbbeSVaclav Hapla 
13051d04cbbeSVaclav Hapla   PetscFunctionBegin;
13061d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13074f572ea9SToby Isaac   PetscAssertPointer(values, 2);
13089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
13091d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
13101d04cbbeSVaclav Hapla     PetscInt n;
13111d04cbbeSVaclav Hapla 
13129566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
13131d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
13141d04cbbeSVaclav Hapla   }
13151d04cbbeSVaclav Hapla   if (j == label->numStrata) {
13169566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
13171d04cbbeSVaclav Hapla   } else {
13189566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
13191d04cbbeSVaclav Hapla   }
13209566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
13213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13221d04cbbeSVaclav Hapla }
13231d04cbbeSVaclav Hapla 
13241d04cbbeSVaclav Hapla /*@
132520f4b53cSBarry Smith   DMLabelGetValueIndex - Get the index of a given value in the list of values for the `DMlabel`, or -1 if it is not present
1326d123abd9SMatthew G. Knepley 
132720f4b53cSBarry Smith   Not Collective
1328d123abd9SMatthew G. Knepley 
1329d123abd9SMatthew G. Knepley   Input Parameters:
133020f4b53cSBarry Smith + label - the `DMLabel`
133197bb3fdcSJose E. Roman - value - the value
1332d123abd9SMatthew G. Knepley 
133301d2d390SJose E. Roman   Output Parameter:
1334d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1335d123abd9SMatthew G. Knepley 
1336d123abd9SMatthew G. Knepley   Level: intermediate
1337d123abd9SMatthew G. Knepley 
133820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1339d123abd9SMatthew G. Knepley @*/
1340d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1341d71ae5a4SJacob Faibussowitsch {
1342d123abd9SMatthew G. Knepley   PetscInt v;
1343d123abd9SMatthew G. Knepley 
1344d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1345d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13464f572ea9SToby Isaac   PetscAssertPointer(index, 3);
1347d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
13489371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
13499371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1350d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1351d123abd9SMatthew G. Knepley   else *index = v;
13523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1353d123abd9SMatthew G. Knepley }
1354d123abd9SMatthew G. Knepley 
1355d123abd9SMatthew G. Knepley /*@
135684f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
135784f0b6dfSMatthew G. Knepley 
135820f4b53cSBarry Smith   Not Collective
13595b5e7992SMatthew G. Knepley 
136084f0b6dfSMatthew G. Knepley   Input Parameters:
136120f4b53cSBarry Smith + label - the `DMLabel`
136284f0b6dfSMatthew G. Knepley - value - the stratum value
136384f0b6dfSMatthew G. Knepley 
136401d2d390SJose E. Roman   Output Parameter:
136584f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
136684f0b6dfSMatthew G. Knepley 
136784f0b6dfSMatthew G. Knepley   Level: intermediate
136884f0b6dfSMatthew G. Knepley 
136920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
137084f0b6dfSMatthew G. Knepley @*/
1371d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1372d71ae5a4SJacob Faibussowitsch {
1373fada774cSMatthew G. Knepley   PetscInt v;
1374fada774cSMatthew G. Knepley 
1375fada774cSMatthew G. Knepley   PetscFunctionBegin;
1376d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13774f572ea9SToby Isaac   PetscAssertPointer(exists, 3);
13789566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13790c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
13803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1381fada774cSMatthew G. Knepley }
1382fada774cSMatthew G. Knepley 
138384f0b6dfSMatthew G. Knepley /*@
138484f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
138584f0b6dfSMatthew G. Knepley 
138620f4b53cSBarry Smith   Not Collective
13875b5e7992SMatthew G. Knepley 
138884f0b6dfSMatthew G. Knepley   Input Parameters:
138920f4b53cSBarry Smith + label - the `DMLabel`
139084f0b6dfSMatthew G. Knepley - value - the stratum value
139184f0b6dfSMatthew G. Knepley 
139201d2d390SJose E. Roman   Output Parameter:
139384f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
139484f0b6dfSMatthew G. Knepley 
139584f0b6dfSMatthew G. Knepley   Level: intermediate
139684f0b6dfSMatthew G. Knepley 
139720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
139884f0b6dfSMatthew G. Knepley @*/
1399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1400d71ae5a4SJacob Faibussowitsch {
1401c58f1c22SToby Isaac   PetscInt v;
1402c58f1c22SToby Isaac 
1403c58f1c22SToby Isaac   PetscFunctionBegin;
1404d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14054f572ea9SToby Isaac   PetscAssertPointer(size, 3);
14069566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14079566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
14083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1409c58f1c22SToby Isaac }
1410c58f1c22SToby Isaac 
141184f0b6dfSMatthew G. Knepley /*@
141284f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
141384f0b6dfSMatthew G. Knepley 
141420f4b53cSBarry Smith   Not Collective
14155b5e7992SMatthew G. Knepley 
141684f0b6dfSMatthew G. Knepley   Input Parameters:
141720f4b53cSBarry Smith + label - the `DMLabel`
141884f0b6dfSMatthew G. Knepley - value - the stratum value
141984f0b6dfSMatthew G. Knepley 
142001d2d390SJose E. Roman   Output Parameters:
142184f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
142284f0b6dfSMatthew G. Knepley - end   - the largest point in the stratum
142384f0b6dfSMatthew G. Knepley 
142484f0b6dfSMatthew G. Knepley   Level: intermediate
142584f0b6dfSMatthew G. Knepley 
142620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
142784f0b6dfSMatthew G. Knepley @*/
1428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1429d71ae5a4SJacob Faibussowitsch {
14309f6c5813SMatthew G. Knepley   IS       is;
14310c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1432c58f1c22SToby Isaac 
1433c58f1c22SToby Isaac   PetscFunctionBegin;
1434d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14359371c9d4SSatish Balay   if (start) {
14364f572ea9SToby Isaac     PetscAssertPointer(start, 3);
14379371c9d4SSatish Balay     *start = -1;
14389371c9d4SSatish Balay   }
14399371c9d4SSatish Balay   if (end) {
14404f572ea9SToby Isaac     PetscAssertPointer(end, 4);
14419371c9d4SSatish Balay     *end = -1;
14429371c9d4SSatish Balay   }
14439566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14443ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14459566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14463ba16761SJacob Faibussowitsch   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
14479f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &is);
14489f6c5813SMatthew G. Knepley   PetscCall(ISGetMinMax(is, &min, &max));
14499f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&is));
1450d6cb179aSToby Isaac   if (start) *start = min;
1451d6cb179aSToby Isaac   if (end) *end = max + 1;
14523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1453c58f1c22SToby Isaac }
1454c58f1c22SToby Isaac 
145566976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
14569f6c5813SMatthew G. Knepley {
14579f6c5813SMatthew G. Knepley   PetscFunctionBegin;
14589f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
14599f6c5813SMatthew G. Knepley   *pointIS = label->points[v];
14603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14619f6c5813SMatthew G. Knepley }
14629f6c5813SMatthew G. Knepley 
146384f0b6dfSMatthew G. Knepley /*@
146420f4b53cSBarry Smith   DMLabelGetStratumIS - Get an `IS` with the stratum points
146584f0b6dfSMatthew G. Knepley 
146620f4b53cSBarry Smith   Not Collective
14675b5e7992SMatthew G. Knepley 
146884f0b6dfSMatthew G. Knepley   Input Parameters:
146920f4b53cSBarry Smith + label - the `DMLabel`
147084f0b6dfSMatthew G. Knepley - value - the stratum value
147184f0b6dfSMatthew G. Knepley 
147201d2d390SJose E. Roman   Output Parameter:
147384f0b6dfSMatthew G. Knepley . points - The stratum points
147484f0b6dfSMatthew G. Knepley 
147584f0b6dfSMatthew G. Knepley   Level: intermediate
147684f0b6dfSMatthew G. Knepley 
1477593ce467SVaclav Hapla   Notes:
147820f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
147920f4b53cSBarry Smith   Returns `NULL` if the stratum is empty.
1480593ce467SVaclav Hapla 
148120f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
148284f0b6dfSMatthew G. Knepley @*/
1483d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1484d71ae5a4SJacob Faibussowitsch {
1485c58f1c22SToby Isaac   PetscInt v;
1486c58f1c22SToby Isaac 
1487c58f1c22SToby Isaac   PetscFunctionBegin;
1488d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14894f572ea9SToby Isaac   PetscAssertPointer(points, 3);
1490c58f1c22SToby Isaac   *points = NULL;
14919566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14923ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14939566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14949f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, points);
14953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1496c58f1c22SToby Isaac }
1497c58f1c22SToby Isaac 
149884f0b6dfSMatthew G. Knepley /*@
149920f4b53cSBarry Smith   DMLabelSetStratumIS - Set the stratum points using an `IS`
150084f0b6dfSMatthew G. Knepley 
150120f4b53cSBarry Smith   Not Collective
15025b5e7992SMatthew G. Knepley 
150384f0b6dfSMatthew G. Knepley   Input Parameters:
150420f4b53cSBarry Smith + label - the `DMLabel`
150584f0b6dfSMatthew G. Knepley . value - the stratum value
150660225df5SJacob Faibussowitsch - is    - The stratum points
150784f0b6dfSMatthew G. Knepley 
150884f0b6dfSMatthew G. Knepley   Level: intermediate
150984f0b6dfSMatthew G. Knepley 
151020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
151184f0b6dfSMatthew G. Knepley @*/
1512d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1513d71ae5a4SJacob Faibussowitsch {
15140c3c4a36SLisandro Dalcin   PetscInt v;
15154de306b1SToby Isaac 
15164de306b1SToby Isaac   PetscFunctionBegin;
1517d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1518d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
15199f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15209566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
15213ba16761SJacob Faibussowitsch   if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
15229566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
1523f4f49eeaSPierre Jolivet   PetscCall(ISGetLocalSize(is, &label->stratumSizes[v]));
15249566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
1525f4f49eeaSPierre Jolivet   PetscCall(ISDestroy(&label->points[v]));
15260c3c4a36SLisandro Dalcin   label->points[v]  = is;
15270c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
15289566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
15294de306b1SToby Isaac   if (label->bt) {
15304de306b1SToby Isaac     const PetscInt *points;
15314de306b1SToby Isaac     PetscInt        p;
15324de306b1SToby Isaac 
15339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
15344de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
15354de306b1SToby Isaac       const PetscInt point = points[p];
15364de306b1SToby Isaac 
153763a3b9bcSJacob 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);
15389566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
15394de306b1SToby Isaac     }
15404de306b1SToby Isaac   }
15413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15424de306b1SToby Isaac }
15434de306b1SToby Isaac 
154484f0b6dfSMatthew G. Knepley /*@
154584f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
15464de306b1SToby Isaac 
154720f4b53cSBarry Smith   Not Collective
15485b5e7992SMatthew G. Knepley 
154984f0b6dfSMatthew G. Knepley   Input Parameters:
155020f4b53cSBarry Smith + label - the `DMLabel`
155184f0b6dfSMatthew G. Knepley - value - the stratum value
155284f0b6dfSMatthew G. Knepley 
155384f0b6dfSMatthew G. Knepley   Level: intermediate
155484f0b6dfSMatthew G. Knepley 
155520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
155684f0b6dfSMatthew G. Knepley @*/
1557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1558d71ae5a4SJacob Faibussowitsch {
1559c58f1c22SToby Isaac   PetscInt v;
1560c58f1c22SToby Isaac 
1561c58f1c22SToby Isaac   PetscFunctionBegin;
1562d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15639f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15649566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15653ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15664de306b1SToby Isaac   if (label->validIS[v]) {
15674de306b1SToby Isaac     if (label->bt) {
1568c58f1c22SToby Isaac       PetscInt        i;
1569ad8374ffSToby Isaac       const PetscInt *points;
1570c58f1c22SToby Isaac 
15719566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1572c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1573ad8374ffSToby Isaac         const PetscInt point = points[i];
1574c58f1c22SToby Isaac 
157563a3b9bcSJacob 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);
15769566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1577c58f1c22SToby Isaac       }
15789566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1579c58f1c22SToby Isaac     }
1580c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
15819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
15829566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
15839566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
15849566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1585c58f1c22SToby Isaac   } else {
15869566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1587c58f1c22SToby Isaac   }
15883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1589c58f1c22SToby Isaac }
1590c58f1c22SToby Isaac 
159184f0b6dfSMatthew G. Knepley /*@
1592412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1593412e9a14SMatthew G. Knepley 
159420f4b53cSBarry Smith   Not Collective
1595412e9a14SMatthew G. Knepley 
1596412e9a14SMatthew G. Knepley   Input Parameters:
159720f4b53cSBarry Smith + label  - The `DMLabel`
1598412e9a14SMatthew G. Knepley . value  - The label value for all points
1599412e9a14SMatthew G. Knepley . pStart - The first point
1600412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1601412e9a14SMatthew G. Knepley 
1602412e9a14SMatthew G. Knepley   Level: intermediate
1603412e9a14SMatthew G. Knepley 
160420f4b53cSBarry Smith   Note:
160520f4b53cSBarry Smith   The marks points are [`pStart`, `pEnd`), and only the bounds are stored.
160620f4b53cSBarry Smith 
160720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1608412e9a14SMatthew G. Knepley @*/
1609d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1610d71ae5a4SJacob Faibussowitsch {
1611412e9a14SMatthew G. Knepley   IS pIS;
1612412e9a14SMatthew G. Knepley 
1613412e9a14SMatthew G. Knepley   PetscFunctionBegin;
16149566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
16159566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
16169566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
16173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1618412e9a14SMatthew G. Knepley }
1619412e9a14SMatthew G. Knepley 
1620412e9a14SMatthew G. Knepley /*@
1621d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1622d123abd9SMatthew G. Knepley 
162320f4b53cSBarry Smith   Not Collective
1624d123abd9SMatthew G. Knepley 
1625d123abd9SMatthew G. Knepley   Input Parameters:
162620f4b53cSBarry Smith + label - The `DMLabel`
1627d123abd9SMatthew G. Knepley . value - The label value
1628d123abd9SMatthew G. Knepley - p     - A point with this value
1629d123abd9SMatthew G. Knepley 
1630d123abd9SMatthew G. Knepley   Output Parameter:
1631d123abd9SMatthew 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
1632d123abd9SMatthew G. Knepley 
1633d123abd9SMatthew G. Knepley   Level: intermediate
1634d123abd9SMatthew G. Knepley 
163520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1636d123abd9SMatthew G. Knepley @*/
1637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1638d71ae5a4SJacob Faibussowitsch {
16399f6c5813SMatthew G. Knepley   IS       pointIS;
1640d123abd9SMatthew G. Knepley   PetscInt v;
1641d123abd9SMatthew G. Knepley 
1642d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1643d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16444f572ea9SToby Isaac   PetscAssertPointer(index, 4);
1645d123abd9SMatthew G. Knepley   *index = -1;
16469566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
16473ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
16489566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
16499f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &pointIS);
1650f622de60SMatthew G. Knepley   PetscCall(ISLocate(pointIS, p, index));
16519f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&pointIS));
16523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1653d123abd9SMatthew G. Knepley }
1654d123abd9SMatthew G. Knepley 
1655d123abd9SMatthew G. Knepley /*@
165620f4b53cSBarry Smith   DMLabelFilter - Remove all points outside of [`start`, `end`)
165784f0b6dfSMatthew G. Knepley 
165820f4b53cSBarry Smith   Not Collective
16595b5e7992SMatthew G. Knepley 
166084f0b6dfSMatthew G. Knepley   Input Parameters:
166120f4b53cSBarry Smith + label - the `DMLabel`
166222cd2cdaSVaclav Hapla . start - the first point kept
166322cd2cdaSVaclav Hapla - end   - one more than the last point kept
166484f0b6dfSMatthew G. Knepley 
166584f0b6dfSMatthew G. Knepley   Level: intermediate
166684f0b6dfSMatthew G. Knepley 
166720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
166884f0b6dfSMatthew G. Knepley @*/
1669d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1670d71ae5a4SJacob Faibussowitsch {
1671c58f1c22SToby Isaac   PetscInt v;
1672c58f1c22SToby Isaac 
1673c58f1c22SToby Isaac   PetscFunctionBegin;
1674d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16759f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16769566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
16779566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16789f6c5813SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
16799f6c5813SMatthew G. Knepley     PetscCall(ISGeneralFilter(label->points[v], start, end));
16809f6c5813SMatthew G. Knepley     PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
16819f6c5813SMatthew G. Knepley   }
16829566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
16833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1684c58f1c22SToby Isaac }
1685c58f1c22SToby Isaac 
168684f0b6dfSMatthew G. Knepley /*@
168784f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
168884f0b6dfSMatthew G. Knepley 
168920f4b53cSBarry Smith   Not Collective
16905b5e7992SMatthew G. Knepley 
169184f0b6dfSMatthew G. Knepley   Input Parameters:
169220f4b53cSBarry Smith + label       - the `DMLabel`
169384f0b6dfSMatthew G. Knepley - permutation - the point permutation
169484f0b6dfSMatthew G. Knepley 
169584f0b6dfSMatthew G. Knepley   Output Parameter:
169660225df5SJacob Faibussowitsch . labelNew - the new label containing the permuted points
169784f0b6dfSMatthew G. Knepley 
169884f0b6dfSMatthew G. Knepley   Level: intermediate
169984f0b6dfSMatthew G. Knepley 
170020f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
170184f0b6dfSMatthew G. Knepley @*/
1702d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1703d71ae5a4SJacob Faibussowitsch {
1704c58f1c22SToby Isaac   const PetscInt *perm;
1705c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1706c58f1c22SToby Isaac 
1707c58f1c22SToby Isaac   PetscFunctionBegin;
1708d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1709d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
17109f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
17119566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
17129566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
17139566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
17149566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
17159566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1716c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1717c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1718ad8374ffSToby Isaac     const PetscInt *points;
1719ad8374ffSToby Isaac     PetscInt       *pointsNew;
1720c58f1c22SToby Isaac 
17219566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
17229f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(size, &pointsNew));
1723c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1724ad8374ffSToby Isaac       const PetscInt point = points[q];
1725c58f1c22SToby Isaac 
172663a3b9bcSJacob 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);
1727ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1728c58f1c22SToby Isaac     }
17299566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
17309566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
173157508eceSPierre Jolivet     PetscCall(ISDestroy(&(*labelNew)->points[v]));
1732fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
17339566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
17349566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1735fa8e8ae5SToby Isaac     } else {
17369566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1737fa8e8ae5SToby Isaac     }
17389566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1739c58f1c22SToby Isaac   }
17409566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1741c58f1c22SToby Isaac   if (label->bt) {
17429566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
17439566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1744c58f1c22SToby Isaac   }
17453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1746c58f1c22SToby Isaac }
1747c58f1c22SToby Isaac 
17485552b385SBrandon /*@
17495552b385SBrandon   DMLabelPermuteValues - Permute the values in a label
17505552b385SBrandon 
17515552b385SBrandon   Not collective
17525552b385SBrandon 
17535552b385SBrandon   Input Parameters:
17545552b385SBrandon + label       - the `DMLabel`
17555552b385SBrandon - permutation - the value permutation, permutation[old value] = new value
17565552b385SBrandon 
17575552b385SBrandon   Output Parameter:
17585552b385SBrandon . label - the `DMLabel` now with permuted values
17595552b385SBrandon 
17605552b385SBrandon   Note:
17615552b385SBrandon   The modification is done in-place
17625552b385SBrandon 
17635552b385SBrandon   Level: intermediate
17645552b385SBrandon 
17655552b385SBrandon .seealso: `DMLabelRewriteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
17665552b385SBrandon @*/
17675552b385SBrandon PetscErrorCode DMLabelPermuteValues(DMLabel label, IS permutation)
17685552b385SBrandon {
17695552b385SBrandon   PetscInt Nv, Np;
17705552b385SBrandon 
17715552b385SBrandon   PetscFunctionBegin;
17725552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17735552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
17745552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
17755552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
17765552b385SBrandon   PetscCheck(Np == Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " != %" PetscInt_FMT " number of label values", Np, Nv);
17775552b385SBrandon   if (PetscDefined(USE_DEBUG)) {
17785552b385SBrandon     PetscBool flg;
17795552b385SBrandon     PetscCall(ISGetInfo(permutation, IS_PERMUTATION, IS_LOCAL, PETSC_TRUE, &flg));
17805552b385SBrandon     PetscCheck(flg, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "IS is not a permutation");
17815552b385SBrandon   }
17825552b385SBrandon   PetscCall(DMLabelRewriteValues(label, permutation));
17835552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
17845552b385SBrandon }
17855552b385SBrandon 
17865552b385SBrandon /*@
17875552b385SBrandon   DMLabelRewriteValues - Permute the values in a label, but some may be omitted
17885552b385SBrandon 
17895552b385SBrandon   Not collective
17905552b385SBrandon 
17915552b385SBrandon   Input Parameters:
17925552b385SBrandon + label       - the `DMLabel`
17935552b385SBrandon - permutation - the value permutation, permutation[old value] = new value, but some maybe omitted
17945552b385SBrandon 
17955552b385SBrandon   Output Parameter:
17965552b385SBrandon . label - the `DMLabel` now with permuted values
17975552b385SBrandon 
17985552b385SBrandon   Note:
17995552b385SBrandon   The modification is done in-place
18005552b385SBrandon 
18015552b385SBrandon   Level: intermediate
18025552b385SBrandon 
18035552b385SBrandon .seealso: `DMLabelPermuteValues()`, `DMLabel`, `DM`, `DMLabelPermute()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
18045552b385SBrandon @*/
18055552b385SBrandon PetscErrorCode DMLabelRewriteValues(DMLabel label, IS permutation)
18065552b385SBrandon {
18075552b385SBrandon   const PetscInt *perm;
18085552b385SBrandon   PetscInt        Nv, Np;
18095552b385SBrandon 
18105552b385SBrandon   PetscFunctionBegin;
18115552b385SBrandon   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
18125552b385SBrandon   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
18135552b385SBrandon   PetscCall(DMLabelMakeAllValid_Private(label));
18145552b385SBrandon   PetscCall(DMLabelGetNumValues(label, &Nv));
18155552b385SBrandon   PetscCall(ISGetLocalSize(permutation, &Np));
18165552b385SBrandon   PetscCheck(Np >= Nv, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_SIZ, "Permutation has size %" PetscInt_FMT " < %" PetscInt_FMT " number of label values", Np, Nv);
18175552b385SBrandon   PetscCall(ISGetIndices(permutation, &perm));
18185552b385SBrandon   for (PetscInt v = 0; v < Nv; ++v) label->stratumValues[v] = perm[label->stratumValues[v]];
18195552b385SBrandon   PetscCall(ISRestoreIndices(permutation, &perm));
18205552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
18215552b385SBrandon }
18225552b385SBrandon 
182366976f2fSJacob Faibussowitsch static PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1824d71ae5a4SJacob Faibussowitsch {
182526c55118SMichael Lange   MPI_Comm     comm;
1826eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
182726c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
182826c55118SMichael Lange   PetscSection rootSection;
182926c55118SMichael Lange   PetscSF      labelSF;
183026c55118SMichael Lange 
183126c55118SMichael Lange   PetscFunctionBegin;
18329566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
18339566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
183426c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
183526c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
18369566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
18379566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
18389566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
183926c55118SMichael Lange   if (label) {
184026c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1841ad8374ffSToby Isaac       const PetscInt *points;
1842ad8374ffSToby Isaac 
18439566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
184448a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
18459566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
184626c55118SMichael Lange     }
184726c55118SMichael Lange   }
18489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
184926c55118SMichael Lange   /* Create a point-wise array of stratum values */
18509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
18519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
18529566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
185326c55118SMichael Lange   if (label) {
185426c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1855ad8374ffSToby Isaac       const PetscInt *points;
1856ad8374ffSToby Isaac 
18579566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
185826c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1859ad8374ffSToby Isaac         const PetscInt p = points[l];
18609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
186126c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
186226c55118SMichael Lange       }
18639566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
186426c55118SMichael Lange     }
186526c55118SMichael Lange   }
186626c55118SMichael Lange   /* Build SF that maps label points to remote processes */
18679566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
18689566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
18699566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
18709566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
187126c55118SMichael Lange   /* Send the strata for each point over the derived SF */
18729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
18739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
18749566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
18759566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
187626c55118SMichael Lange   /* Clean up */
18779566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18789566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
18799566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18809566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
18813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
188226c55118SMichael Lange }
188326c55118SMichael Lange 
188484f0b6dfSMatthew G. Knepley /*@
188520f4b53cSBarry Smith   DMLabelDistribute - Create a new label pushed forward over the `PetscSF`
188684f0b6dfSMatthew G. Knepley 
188720f4b53cSBarry Smith   Collective
18885b5e7992SMatthew G. Knepley 
188984f0b6dfSMatthew G. Knepley   Input Parameters:
189020f4b53cSBarry Smith + label - the `DMLabel`
189184f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
189284f0b6dfSMatthew G. Knepley 
189384f0b6dfSMatthew G. Knepley   Output Parameter:
189460225df5SJacob Faibussowitsch . labelNew - the new redistributed label
189584f0b6dfSMatthew G. Knepley 
189684f0b6dfSMatthew G. Knepley   Level: intermediate
189784f0b6dfSMatthew G. Knepley 
189820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
189984f0b6dfSMatthew G. Knepley @*/
1900d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1901d71ae5a4SJacob Faibussowitsch {
1902c58f1c22SToby Isaac   MPI_Comm     comm;
190326c55118SMichael Lange   PetscSection leafSection;
190426c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
190526c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1906ad8374ffSToby Isaac   PetscInt   **points;
1907d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1908c58f1c22SToby Isaac   char        *name;
1909835f2295SStefano Zampini   PetscMPIInt  nameSize;
1910e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1911c58f1c22SToby Isaac   size_t       len = 0;
191226c55118SMichael Lange   PetscMPIInt  rank;
1913c58f1c22SToby Isaac 
1914c58f1c22SToby Isaac   PetscFunctionBegin;
1915d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1916f018e600SMatthew G. Knepley   if (label) {
1917f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
19189f6c5813SMatthew G. Knepley     PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
19199566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1920f018e600SMatthew G. Knepley   }
19219566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
19229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1923c58f1c22SToby Isaac   /* Bcast name */
1924dd400576SPatrick Sanan   if (rank == 0) {
19259566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
19269566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1927d67d17b1SMatthew G. Knepley   }
1928835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
1929835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
19309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
19319566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
1932835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
19339566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
19349566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
193577d236dfSMichael Lange   /* Bcast defaultValue */
1936dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
19379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
193826c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
19399566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
19405cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
19419566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
19429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
19439566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
19449566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
19459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1946ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
19479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
19485cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
19495cbdf6fcSMichael Lange   offset = 0;
19509566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
19519566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
195248a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
19535cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1954231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
19559371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
19569371c9d4SSatish Balay         leafStrata[p] = s;
19579371c9d4SSatish Balay         break;
19589371c9d4SSatish Balay       }
19595cbdf6fcSMichael Lange     }
19605cbdf6fcSMichael Lange   }
1961c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
19629566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
19639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1964c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1967ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1968c58f1c22SToby Isaac   }
19699566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
19709f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
19719f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1972c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
19739566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
1974f4f49eeaSPierre Jolivet     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &points[s]));
1975c58f1c22SToby Isaac   }
1976c58f1c22SToby Isaac   /* Insert points into new strata */
19779566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
19789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1979c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
19809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
19819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1982c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1983c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1984ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1985c58f1c22SToby Isaac     }
1986c58f1c22SToby Isaac   }
1987ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1988f4f49eeaSPierre Jolivet     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &points[s][0], PETSC_OWN_POINTER, &((*labelNew)->points[s])));
19899566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1990ad8374ffSToby Isaac   }
19919566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
19929566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
19939566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
19949566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
19959566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
19963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1997c58f1c22SToby Isaac }
1998c58f1c22SToby Isaac 
19997937d9ceSMichael Lange /*@
20007937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
20017937d9ceSMichael Lange 
200220f4b53cSBarry Smith   Collective
20035b5e7992SMatthew G. Knepley 
20047937d9ceSMichael Lange   Input Parameters:
200520f4b53cSBarry Smith + label - the `DMLabel`
200620f4b53cSBarry Smith - sf    - the `PetscSF` communication map
20077937d9ceSMichael Lange 
20082fe279fdSBarry Smith   Output Parameter:
200920f4b53cSBarry Smith . labelNew - the new `DMLabel` with localised leaf values
20107937d9ceSMichael Lange 
20117937d9ceSMichael Lange   Level: developer
20127937d9ceSMichael Lange 
201320f4b53cSBarry Smith   Note:
201420f4b53cSBarry Smith   This is the inverse operation to `DMLabelDistribute()`.
20157937d9ceSMichael Lange 
201620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
20177937d9ceSMichael Lange @*/
2018d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
2019d71ae5a4SJacob Faibussowitsch {
20207937d9ceSMichael Lange   MPI_Comm        comm;
20217937d9ceSMichael Lange   PetscSection    rootSection;
20227937d9ceSMichael Lange   PetscSF         sfLabel;
20237937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
20247937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
20257937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
20267937d9ceSMichael Lange   PetscInt       *rootStrata;
2027d67d17b1SMatthew G. Knepley   const char     *lname;
20287937d9ceSMichael Lange   char           *name;
2029835f2295SStefano Zampini   PetscMPIInt     nameSize;
20307937d9ceSMichael Lange   size_t          len = 0;
20319852e123SBarry Smith   PetscMPIInt     rank, size;
20327937d9ceSMichael Lange 
20337937d9ceSMichael Lange   PetscFunctionBegin;
2034d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2035d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
20369f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
20379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
20389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
20399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
20407937d9ceSMichael Lange   /* Bcast name */
2041dd400576SPatrick Sanan   if (rank == 0) {
20429566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
20439566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
2044d67d17b1SMatthew G. Knepley   }
2045835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(len, &nameSize));
2046835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPI_INT, 0, comm));
20479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
20489566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
2049835f2295SStefano Zampini   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
20509566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
20519566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
20527937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
20537937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
20547937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
20559566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
20569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
2057dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
20587937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
20598212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
20608212dd46SStefano Zampini 
20618212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
20628212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
20637937d9ceSMichael Lange   }
20649566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
20659566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
20667937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
20679566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
20686497c311SBarry Smith   PetscCall(PetscSFGatherBegin(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20696497c311SBarry Smith   PetscCall(PetscSFGatherEnd(sf, MPIU_SF_NODE, leafPoints, rootPoints));
20709566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
20719566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
20727937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
20739566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
20747937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
20757937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
20767937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
20779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
20789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
20799566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
20807937d9ceSMichael Lange     }
20817937d9ceSMichael Lange     idx += rootDegree[p];
20827937d9ceSMichael Lange   }
20839566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
20849566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
20859566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
20869566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
20873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20887937d9ceSMichael Lange }
20897937d9ceSMichael Lange 
2090d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
2091d71ae5a4SJacob Faibussowitsch {
2092d42890abSMatthew G. Knepley   const PetscInt *degree;
2093d42890abSMatthew G. Knepley   const PetscInt *points;
2094d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2095d42890abSMatthew G. Knepley 
2096d42890abSMatthew G. Knepley   PetscFunctionBegin;
2097d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2098d42890abSMatthew G. Knepley   /* Add in leaves */
2099d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2100d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2101d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
2102d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
2103d42890abSMatthew G. Knepley   }
2104d42890abSMatthew G. Knepley   /* Add in shared roots */
2105d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2106d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2107d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2108d42890abSMatthew G. Knepley     if (degree[r]) {
2109d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
2110d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
2111d42890abSMatthew G. Knepley     }
2112d42890abSMatthew G. Knepley   }
21133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2114d42890abSMatthew G. Knepley }
2115d42890abSMatthew G. Knepley 
2116d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2117d71ae5a4SJacob Faibussowitsch {
2118d42890abSMatthew G. Knepley   const PetscInt *degree;
2119d42890abSMatthew G. Knepley   const PetscInt *points;
2120d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
2121d42890abSMatthew G. Knepley 
2122d42890abSMatthew G. Knepley   PetscFunctionBegin;
2123d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
2124d42890abSMatthew G. Knepley   /* Read out leaves */
2125d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
2126d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
2127d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
2128d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
2129d42890abSMatthew G. Knepley 
2130d42890abSMatthew G. Knepley     if (cval != defVal) {
2131d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
2132d42890abSMatthew G. Knepley       if (val == defVal) {
2133d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
213448a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
2135d42890abSMatthew G. Knepley       }
2136d42890abSMatthew G. Knepley     }
2137d42890abSMatthew G. Knepley   }
2138d42890abSMatthew G. Knepley   /* Read out shared roots */
2139d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2140d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2141d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2142d42890abSMatthew G. Knepley     if (degree[r]) {
2143d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
2144d42890abSMatthew G. Knepley 
2145d42890abSMatthew G. Knepley       if (cval != defVal) {
2146d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
2147d42890abSMatthew G. Knepley         if (val == defVal) {
2148d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
214948a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2150d42890abSMatthew G. Knepley         }
2151d42890abSMatthew G. Knepley       }
2152d42890abSMatthew G. Knepley     }
2153d42890abSMatthew G. Knepley   }
21543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2155d42890abSMatthew G. Knepley }
2156d42890abSMatthew G. Knepley 
2157d42890abSMatthew G. Knepley /*@
2158d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
2159d42890abSMatthew G. Knepley 
216020f4b53cSBarry Smith   Collective
2161d42890abSMatthew G. Knepley 
2162d42890abSMatthew G. Knepley   Input Parameters:
216320f4b53cSBarry Smith + label - The `DMLabel` to propagate across processes
216420f4b53cSBarry Smith - sf    - The `PetscSF` describing parallel layout of the label points
2165d42890abSMatthew G. Knepley 
2166d42890abSMatthew G. Knepley   Level: intermediate
2167d42890abSMatthew G. Knepley 
216820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2169d42890abSMatthew G. Knepley @*/
2170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2171d71ae5a4SJacob Faibussowitsch {
2172d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
2173d42890abSMatthew G. Knepley   PetscMPIInt size;
2174d42890abSMatthew G. Knepley 
2175d42890abSMatthew G. Knepley   PetscFunctionBegin;
21769f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2177d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2178d42890abSMatthew G. Knepley   if (size > 1) {
2179d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
2180d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2181d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2182d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2183d42890abSMatthew G. Knepley   }
21843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2185d42890abSMatthew G. Knepley }
2186d42890abSMatthew G. Knepley 
2187d42890abSMatthew G. Knepley /*@
2188d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
2189d42890abSMatthew G. Knepley 
219020f4b53cSBarry Smith   Collective
2191d42890abSMatthew G. Knepley 
2192d42890abSMatthew G. Knepley   Input Parameters:
219320f4b53cSBarry Smith + label   - The `DMLabel` to propagate across processes
219460225df5SJacob Faibussowitsch - pointSF - The `PetscSF` describing parallel layout of the label points
2195d42890abSMatthew G. Knepley 
2196d42890abSMatthew G. Knepley   Level: intermediate
2197d42890abSMatthew G. Knepley 
219820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2199d42890abSMatthew G. Knepley @*/
2200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2201d71ae5a4SJacob Faibussowitsch {
2202d42890abSMatthew G. Knepley   PetscFunctionBegin;
22039f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2204d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
2205d42890abSMatthew G. Knepley   label->propArray = NULL;
22063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2207d42890abSMatthew G. Knepley }
2208d42890abSMatthew G. Knepley 
2209d42890abSMatthew G. Knepley /*@C
2210d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2211d42890abSMatthew G. Knepley 
221220f4b53cSBarry Smith   Collective
2213d42890abSMatthew G. Knepley 
2214d42890abSMatthew G. Knepley   Input Parameters:
221520f4b53cSBarry Smith + label     - The `DMLabel` to propagate across processes
2216a4e35b19SJacob Faibussowitsch . pointSF   - The `PetscSF` describing parallel layout of the label points
221720f4b53cSBarry Smith . markPoint - An optional callback that is called when a point is marked, or `NULL`
221820f4b53cSBarry Smith - ctx       - An optional user context for the callback, or `NULL`
2219d42890abSMatthew G. Knepley 
222020f4b53cSBarry Smith   Calling sequence of `markPoint`:
222120f4b53cSBarry Smith + label - The `DMLabel`
2222d42890abSMatthew G. Knepley . p     - The point being marked
2223a4e35b19SJacob Faibussowitsch . val   - The label value for `p`
2224d42890abSMatthew G. Knepley - ctx   - An optional user context
2225d42890abSMatthew G. Knepley 
2226d42890abSMatthew G. Knepley   Level: intermediate
2227d42890abSMatthew G. Knepley 
222820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2229d42890abSMatthew G. Knepley @*/
2230a4e35b19SJacob Faibussowitsch PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel label, PetscInt p, PetscInt val, void *ctx), void *ctx)
2231d71ae5a4SJacob Faibussowitsch {
2232c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2233d42890abSMatthew G. Knepley   PetscMPIInt size;
2234d42890abSMatthew G. Knepley 
2235d42890abSMatthew G. Knepley   PetscFunctionBegin;
22369f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2237d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2238c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2239c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2240d42890abSMatthew G. Knepley     /* Communicate marked edges
2241d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2242d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2243d42890abSMatthew G. Knepley 
2244d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2245d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2246d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2247d42890abSMatthew G. Knepley 
2248d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2249d42890abSMatthew 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
2250d42890abSMatthew G. Knepley        edge to the queue.
2251d42890abSMatthew G. Knepley     */
2252d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2253d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2254d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2255d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2256d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2257d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2258d42890abSMatthew G. Knepley   }
22593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2260d42890abSMatthew G. Knepley }
2261d42890abSMatthew G. Knepley 
226284f0b6dfSMatthew G. Knepley /*@
226320f4b53cSBarry Smith   DMLabelConvertToSection - Make a `PetscSection`/`IS` pair that encodes the label
226484f0b6dfSMatthew G. Knepley 
226520f4b53cSBarry Smith   Not Collective
22665b5e7992SMatthew G. Knepley 
226784f0b6dfSMatthew G. Knepley   Input Parameter:
226820f4b53cSBarry Smith . label - the `DMLabel`
226984f0b6dfSMatthew G. Knepley 
227084f0b6dfSMatthew G. Knepley   Output Parameters:
227184f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
227220f4b53cSBarry Smith - is      - An `IS` containing all the label points
227384f0b6dfSMatthew G. Knepley 
227484f0b6dfSMatthew G. Knepley   Level: developer
227584f0b6dfSMatthew G. Knepley 
227620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
227784f0b6dfSMatthew G. Knepley @*/
2278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2279d71ae5a4SJacob Faibussowitsch {
2280c58f1c22SToby Isaac   IS              vIS;
2281c58f1c22SToby Isaac   const PetscInt *values;
2282c58f1c22SToby Isaac   PetscInt       *points;
2283c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2284c58f1c22SToby Isaac 
2285c58f1c22SToby Isaac   PetscFunctionBegin;
2286d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
22879566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
22889566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
22899566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
22909371c9d4SSatish Balay   if (nV) {
22919371c9d4SSatish Balay     vS = values[0];
22929371c9d4SSatish Balay     vE = values[0] + 1;
22939371c9d4SSatish Balay   }
2294c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2295c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2296c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2297c58f1c22SToby Isaac   }
22989566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
22999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2300c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2301c58f1c22SToby Isaac     PetscInt n;
2302c58f1c22SToby Isaac 
23039566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
23049566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2305c58f1c22SToby Isaac   }
23069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
23079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
23089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2309c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2310c58f1c22SToby Isaac     IS              is;
2311c58f1c22SToby Isaac     const PetscInt *spoints;
2312c58f1c22SToby Isaac     PetscInt        dof, off, p;
2313c58f1c22SToby Isaac 
23149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
23159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
23169566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
23179566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2318c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
23199566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
23209566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2321c58f1c22SToby Isaac   }
23229566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
23239566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
23249566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
23253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2326c58f1c22SToby Isaac }
2327c58f1c22SToby Isaac 
23289f6c5813SMatthew G. Knepley /*@C
23299f6c5813SMatthew G. Knepley   DMLabelRegister - Adds a new label component implementation
23309f6c5813SMatthew G. Knepley 
23319f6c5813SMatthew G. Knepley   Not Collective
23329f6c5813SMatthew G. Knepley 
23339f6c5813SMatthew G. Knepley   Input Parameters:
23349f6c5813SMatthew G. Knepley + name        - The name of a new user-defined creation routine
23359f6c5813SMatthew G. Knepley - create_func - The creation routine itself
23369f6c5813SMatthew G. Knepley 
23379f6c5813SMatthew G. Knepley   Notes:
23389f6c5813SMatthew G. Knepley   `DMLabelRegister()` may be called multiple times to add several user-defined labels
23399f6c5813SMatthew G. Knepley 
234060225df5SJacob Faibussowitsch   Example Usage:
23419f6c5813SMatthew G. Knepley .vb
23429f6c5813SMatthew G. Knepley   DMLabelRegister("my_label", MyLabelCreate);
23439f6c5813SMatthew G. Knepley .ve
23449f6c5813SMatthew G. Knepley 
23459f6c5813SMatthew G. Knepley   Then, your label type can be chosen with the procedural interface via
23469f6c5813SMatthew G. Knepley .vb
23479f6c5813SMatthew G. Knepley   DMLabelCreate(MPI_Comm, DMLabel *);
23489f6c5813SMatthew G. Knepley   DMLabelSetType(DMLabel, "my_label");
23499f6c5813SMatthew G. Knepley .ve
23509f6c5813SMatthew G. Knepley   or at runtime via the option
23519f6c5813SMatthew G. Knepley .vb
23529f6c5813SMatthew G. Knepley   -dm_label_type my_label
23539f6c5813SMatthew G. Knepley .ve
23549f6c5813SMatthew G. Knepley 
23559f6c5813SMatthew G. Knepley   Level: advanced
23569f6c5813SMatthew G. Knepley 
235760225df5SJacob Faibussowitsch .seealso: `DMLabel`, `DM`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
23589f6c5813SMatthew G. Knepley @*/
23599f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
23609f6c5813SMatthew G. Knepley {
23619f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23629f6c5813SMatthew G. Knepley   PetscCall(DMInitializePackage());
23639f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
23643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23659f6c5813SMatthew G. Knepley }
23669f6c5813SMatthew G. Knepley 
23679f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
23689f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
23699f6c5813SMatthew G. Knepley 
23709f6c5813SMatthew G. Knepley /*@C
23719f6c5813SMatthew G. Knepley   DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
23729f6c5813SMatthew G. Knepley 
23739f6c5813SMatthew G. Knepley   Not Collective
23749f6c5813SMatthew G. Knepley 
23759f6c5813SMatthew G. Knepley   Level: advanced
23769f6c5813SMatthew G. Knepley 
237720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMRegisterAll()`, `DMLabelRegisterDestroy()`
23789f6c5813SMatthew G. Knepley @*/
23799f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterAll(void)
23809f6c5813SMatthew G. Knepley {
23819f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23823ba16761SJacob Faibussowitsch   if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
23839f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_TRUE;
23849f6c5813SMatthew G. Knepley 
23859f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
23869f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
23873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23889f6c5813SMatthew G. Knepley }
23899f6c5813SMatthew G. Knepley 
23909f6c5813SMatthew G. Knepley /*@C
23919f6c5813SMatthew G. Knepley   DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
23929f6c5813SMatthew G. Knepley 
23939f6c5813SMatthew G. Knepley   Level: developer
23949f6c5813SMatthew G. Knepley 
239520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscInitialize()`
23969f6c5813SMatthew G. Knepley @*/
23979f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterDestroy(void)
23989f6c5813SMatthew G. Knepley {
23999f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24009f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListDestroy(&DMLabelList));
24019f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_FALSE;
24023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24039f6c5813SMatthew G. Knepley }
24049f6c5813SMatthew G. Knepley 
2405cc4c1da9SBarry Smith /*@
24069f6c5813SMatthew G. Knepley   DMLabelSetType - Sets the particular implementation for a label.
24079f6c5813SMatthew G. Knepley 
240820f4b53cSBarry Smith   Collective
24099f6c5813SMatthew G. Knepley 
24109f6c5813SMatthew G. Knepley   Input Parameters:
24119f6c5813SMatthew G. Knepley + label  - The label
24129f6c5813SMatthew G. Knepley - method - The name of the label type
24139f6c5813SMatthew G. Knepley 
24149f6c5813SMatthew G. Knepley   Options Database Key:
241520f4b53cSBarry Smith . -dm_label_type <type> - Sets the label type; use -help for a list of available types or see `DMLabelType`
24169f6c5813SMatthew G. Knepley 
24179f6c5813SMatthew G. Knepley   Level: intermediate
24189f6c5813SMatthew G. Knepley 
241920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetType()`, `DMLabelCreate()`
24209f6c5813SMatthew G. Knepley @*/
24219f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
24229f6c5813SMatthew G. Knepley {
24239f6c5813SMatthew G. Knepley   PetscErrorCode (*r)(DMLabel);
24249f6c5813SMatthew G. Knepley   PetscBool match;
24259f6c5813SMatthew G. Knepley 
24269f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24279f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24289f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
24293ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
24309f6c5813SMatthew G. Knepley 
24319f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24329f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
24339f6c5813SMatthew G. Knepley   PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
24349f6c5813SMatthew G. Knepley 
24359f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, destroy);
24369f6c5813SMatthew G. Knepley   PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
24379f6c5813SMatthew G. Knepley   PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
24389f6c5813SMatthew G. Knepley   PetscCall((*r)(label));
24393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24409f6c5813SMatthew G. Knepley }
24419f6c5813SMatthew G. Knepley 
2442cc4c1da9SBarry Smith /*@
24439f6c5813SMatthew G. Knepley   DMLabelGetType - Gets the type name (as a string) from the label.
24449f6c5813SMatthew G. Knepley 
24459f6c5813SMatthew G. Knepley   Not Collective
24469f6c5813SMatthew G. Knepley 
24479f6c5813SMatthew G. Knepley   Input Parameter:
244820f4b53cSBarry Smith . label - The `DMLabel`
24499f6c5813SMatthew G. Knepley 
24509f6c5813SMatthew G. Knepley   Output Parameter:
245120f4b53cSBarry Smith . type - The `DMLabel` type name
24529f6c5813SMatthew G. Knepley 
24539f6c5813SMatthew G. Knepley   Level: intermediate
24549f6c5813SMatthew G. Knepley 
245520f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetType()`, `DMLabelCreate()`
24569f6c5813SMatthew G. Knepley @*/
24579f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
24589f6c5813SMatthew G. Knepley {
24599f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24609f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24614f572ea9SToby Isaac   PetscAssertPointer(type, 2);
24629f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
24639f6c5813SMatthew G. Knepley   *type = ((PetscObject)label)->type_name;
24643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24659f6c5813SMatthew G. Knepley }
24669f6c5813SMatthew G. Knepley 
24679f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
24689f6c5813SMatthew G. Knepley {
24699f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24709f6c5813SMatthew G. Knepley   label->ops->view         = DMLabelView_Concrete;
24719f6c5813SMatthew G. Knepley   label->ops->setup        = NULL;
24729f6c5813SMatthew G. Knepley   label->ops->duplicate    = DMLabelDuplicate_Concrete;
24739f6c5813SMatthew G. Knepley   label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
24743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24759f6c5813SMatthew G. Knepley }
24769f6c5813SMatthew G. Knepley 
24779f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
24789f6c5813SMatthew G. Knepley {
24799f6c5813SMatthew G. Knepley   PetscFunctionBegin;
24809f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
24819f6c5813SMatthew G. Knepley   PetscCall(DMLabelInitialize_Concrete(label));
24823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24839f6c5813SMatthew G. Knepley }
24849f6c5813SMatthew G. Knepley 
248584f0b6dfSMatthew G. Knepley /*@
2486c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
248720f4b53cSBarry Smith   the local section and an `PetscSF` describing the section point overlap.
2488c58f1c22SToby Isaac 
248920f4b53cSBarry Smith   Collective
24905b5e7992SMatthew G. Knepley 
2491c58f1c22SToby Isaac   Input Parameters:
249220f4b53cSBarry Smith + s                  - The `PetscSection` for the local field layout
249320f4b53cSBarry Smith . sf                 - The `PetscSF` describing parallel layout of the section points
249420f4b53cSBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
2495c58f1c22SToby Isaac . label              - The label specifying the points
2496c58f1c22SToby Isaac - labelValue         - The label stratum specifying the points
2497c58f1c22SToby Isaac 
2498c58f1c22SToby Isaac   Output Parameter:
249920f4b53cSBarry Smith . gsection - The `PetscSection` for the global field layout
2500c58f1c22SToby Isaac 
2501c58f1c22SToby Isaac   Level: developer
2502c58f1c22SToby Isaac 
250320f4b53cSBarry Smith   Note:
250420f4b53cSBarry Smith   This gives negative sizes and offsets to points not owned by this process
250520f4b53cSBarry Smith 
250620f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionCreate()`
2507c58f1c22SToby Isaac @*/
2508d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2509d71ae5a4SJacob Faibussowitsch {
2510c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2511c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2512c58f1c22SToby Isaac 
2513c58f1c22SToby Isaac   PetscFunctionBegin;
2514d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2515d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2516d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
25179566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
25189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
25199566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
25209566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2521c58f1c22SToby Isaac   if (nroots >= 0) {
252263a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
25239566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2524c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25259566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2526c58f1c22SToby Isaac     } else {
2527c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2528c58f1c22SToby Isaac     }
2529c58f1c22SToby Isaac   }
2530c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2531c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2532c58f1c22SToby Isaac     PetscInt value;
2533c58f1c22SToby Isaac 
25349566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2535c58f1c22SToby Isaac     if (value != labelValue) continue;
25369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
25379566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
25389566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
25399566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2540c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2541c58f1c22SToby Isaac   }
25429566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2543c58f1c22SToby Isaac   if (nroots >= 0) {
25449566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25459566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2546c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25479371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25489371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
25499371c9d4SSatish Balay       }
2550c58f1c22SToby Isaac     }
2551c58f1c22SToby Isaac   }
255235cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
2553c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2554c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2555c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2556c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2557c58f1c22SToby Isaac   }
25589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2559c58f1c22SToby Isaac   globalOff -= off;
2560c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2561c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2562c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2563c58f1c22SToby Isaac   }
2564c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2565c58f1c22SToby Isaac   if (nroots >= 0) {
25669566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
25679566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2568c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
25699371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
25709371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
25719371c9d4SSatish Balay       }
2572c58f1c22SToby Isaac     }
2573c58f1c22SToby Isaac   }
25749566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
25759566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
25763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2577c58f1c22SToby Isaac }
2578c58f1c22SToby Isaac 
25799371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
25805fdea053SToby Isaac   DMLabel              label;
25815fdea053SToby Isaac   PetscCopyMode       *modes;
25825fdea053SToby Isaac   PetscInt            *sizes;
25835fdea053SToby Isaac   const PetscInt    ***perms;
25845fdea053SToby Isaac   const PetscScalar ***rots;
25855fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
25865fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
25875fdea053SToby Isaac } PetscSectionSym_Label;
25885fdea053SToby Isaac 
2589d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2590d71ae5a4SJacob Faibussowitsch {
25915fdea053SToby Isaac   PetscInt               i, j;
25925fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
25935fdea053SToby Isaac 
25945fdea053SToby Isaac   PetscFunctionBegin;
25955fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
25965fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
25975fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
25989566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
25999566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
26005fdea053SToby Isaac       }
26015fdea053SToby Isaac       if (sl->perms[i]) {
26025fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
26035fdea053SToby Isaac 
26049566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
26055fdea053SToby Isaac       }
26065fdea053SToby Isaac       if (sl->rots[i]) {
26075fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
26085fdea053SToby Isaac 
26099566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
26105fdea053SToby Isaac       }
26115fdea053SToby Isaac     }
26125fdea053SToby Isaac   }
26139566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
26149566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
26155fdea053SToby Isaac   sl->numStrata = 0;
26163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26175fdea053SToby Isaac }
26185fdea053SToby Isaac 
2619d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2620d71ae5a4SJacob Faibussowitsch {
26215fdea053SToby Isaac   PetscFunctionBegin;
26229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
26239566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
26243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26255fdea053SToby Isaac }
26265fdea053SToby Isaac 
2627d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2628d71ae5a4SJacob Faibussowitsch {
26295fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
26305fdea053SToby Isaac   PetscBool              isAscii;
26315fdea053SToby Isaac   DMLabel                label = sl->label;
2632d67d17b1SMatthew G. Knepley   const char            *name;
26335fdea053SToby Isaac 
26345fdea053SToby Isaac   PetscFunctionBegin;
26359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
26365fdea053SToby Isaac   if (isAscii) {
26375fdea053SToby Isaac     PetscInt          i, j, k;
26385fdea053SToby Isaac     PetscViewerFormat format;
26395fdea053SToby Isaac 
26409566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
26415fdea053SToby Isaac     if (label) {
26429566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
26435fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26449566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
26459566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
26469566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26475fdea053SToby Isaac       } else {
26489566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
26499566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
26505fdea053SToby Isaac       }
26515fdea053SToby Isaac     } else {
26529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
26535fdea053SToby Isaac     }
26549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
26555fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
26565fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
26575fdea053SToby Isaac 
26585fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
265963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
26605fdea053SToby Isaac       } else {
266163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
26629566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
266363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
26645fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
26659566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
26665fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
26675fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
266863a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
26695fdea053SToby Isaac             } else {
26705fdea053SToby Isaac               PetscInt tab;
26715fdea053SToby Isaac 
267263a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
26739566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
26749566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
26755fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
26769566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
26779566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
267863a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
26799566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26809566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26815fdea053SToby Isaac               }
26825fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
26839566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
26849566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
26855fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
268663a3b9bcSJacob 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])));
26875fdea053SToby Isaac #else
268863a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
26895fdea053SToby Isaac #endif
26909566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
26919566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
26925fdea053SToby Isaac               }
26939566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
26945fdea053SToby Isaac             }
26955fdea053SToby Isaac           }
26969566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
26975fdea053SToby Isaac         }
26989566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
26995fdea053SToby Isaac       }
27005fdea053SToby Isaac     }
27019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
27025fdea053SToby Isaac   }
27033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27045fdea053SToby Isaac }
27055fdea053SToby Isaac 
27065fdea053SToby Isaac /*@
27075fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
27085fdea053SToby Isaac 
270920f4b53cSBarry Smith   Logically
27105fdea053SToby Isaac 
271160225df5SJacob Faibussowitsch   Input Parameters:
27125fdea053SToby Isaac + sym   - the section symmetries
271320f4b53cSBarry Smith - label - the `DMLabel` describing the types of points
27145fdea053SToby Isaac 
27155fdea053SToby Isaac   Level: developer:
27165fdea053SToby Isaac 
271720f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
27185fdea053SToby Isaac @*/
2719d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2720d71ae5a4SJacob Faibussowitsch {
27215fdea053SToby Isaac   PetscSectionSym_Label *sl;
27225fdea053SToby Isaac 
27235fdea053SToby Isaac   PetscFunctionBegin;
27245fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
27255fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
27269566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
27275fdea053SToby Isaac   if (label) {
27285fdea053SToby Isaac     sl->label = label;
27299566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
27309566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
27319566063dSJacob 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));
27329566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
27339566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
27349566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
27359566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
27369566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
27375fdea053SToby Isaac   }
27383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27395fdea053SToby Isaac }
27405fdea053SToby Isaac 
27415fdea053SToby Isaac /*@C
2742b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2743b004864fSMatthew G. Knepley 
274420f4b53cSBarry Smith   Logically Collective
2745b004864fSMatthew G. Knepley 
2746b004864fSMatthew G. Knepley   Input Parameters:
2747b004864fSMatthew G. Knepley + sym     - the section symmetries
2748b004864fSMatthew G. Knepley - stratum - the stratum value in the label that we are assigning symmetries for
2749b004864fSMatthew G. Knepley 
2750b004864fSMatthew G. Knepley   Output Parameters:
275120f4b53cSBarry Smith + size      - the number of dofs for points in the `stratum` of the label
275220f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
275320f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a ppoint in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
275420f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
275520f4b53cSBarry 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
2756b004864fSMatthew G. Knepley 
2757b004864fSMatthew G. Knepley   Level: developer
2758b004864fSMatthew G. Knepley 
275920f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2760b004864fSMatthew G. Knepley @*/
2761d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2762d71ae5a4SJacob Faibussowitsch {
2763b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2764b004864fSMatthew G. Knepley   const char            *name;
2765b004864fSMatthew G. Knepley   PetscInt               i;
2766b004864fSMatthew G. Knepley 
2767b004864fSMatthew G. Knepley   PetscFunctionBegin;
2768b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2769b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2770b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2771b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2772b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2773b004864fSMatthew G. Knepley 
2774b004864fSMatthew G. Knepley     if (stratum == value) break;
2775b004864fSMatthew G. Knepley   }
27769566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2777b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
27789371c9d4SSatish Balay   if (size) {
27794f572ea9SToby Isaac     PetscAssertPointer(size, 3);
27809371c9d4SSatish Balay     *size = sl->sizes[i];
27819371c9d4SSatish Balay   }
27829371c9d4SSatish Balay   if (minOrient) {
27834f572ea9SToby Isaac     PetscAssertPointer(minOrient, 4);
27849371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
27859371c9d4SSatish Balay   }
27869371c9d4SSatish Balay   if (maxOrient) {
27874f572ea9SToby Isaac     PetscAssertPointer(maxOrient, 5);
27889371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
27899371c9d4SSatish Balay   }
27909371c9d4SSatish Balay   if (perms) {
27914f572ea9SToby Isaac     PetscAssertPointer(perms, 6);
27928e3a54c0SPierre Jolivet     *perms = PetscSafePointerPlusOffset(sl->perms[i], sl->minMaxOrients[i][0]);
27939371c9d4SSatish Balay   }
27949371c9d4SSatish Balay   if (rots) {
27954f572ea9SToby Isaac     PetscAssertPointer(rots, 7);
27968e3a54c0SPierre Jolivet     *rots = PetscSafePointerPlusOffset(sl->rots[i], sl->minMaxOrients[i][0]);
27979371c9d4SSatish Balay   }
27983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2799b004864fSMatthew G. Knepley }
2800b004864fSMatthew G. Knepley 
2801b004864fSMatthew G. Knepley /*@C
28025fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
28035fdea053SToby Isaac 
280420f4b53cSBarry Smith   Logically
28055fdea053SToby Isaac 
28065fdea053SToby Isaac   Input Parameters:
28075b5e7992SMatthew G. Knepley + sym       - the section symmetries
28085fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
280920f4b53cSBarry Smith . size      - the number of dofs for points in the `stratum` of the label
281020f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
281120f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a point in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
281220f4b53cSBarry Smith . mode      - how `sym` should copy the `perms` and `rots` arrays
281320f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
281420f4b53cSBarry 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
28155fdea053SToby Isaac 
28165fdea053SToby Isaac   Level: developer
28175fdea053SToby Isaac 
281820f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
28195fdea053SToby Isaac @*/
2820d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2821d71ae5a4SJacob Faibussowitsch {
28225fdea053SToby Isaac   PetscSectionSym_Label *sl;
2823d67d17b1SMatthew G. Knepley   const char            *name;
2824d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
28255fdea053SToby Isaac 
28265fdea053SToby Isaac   PetscFunctionBegin;
28275fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
28285fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2829b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
28305fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
28315fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
28325fdea053SToby Isaac 
28335fdea053SToby Isaac     if (stratum == value) break;
28345fdea053SToby Isaac   }
28359566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
283663a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
28375fdea053SToby Isaac   sl->sizes[i]            = size;
28385fdea053SToby Isaac   sl->modes[i]            = mode;
28395fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
28405fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
28415fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
28425fdea053SToby Isaac     if (perms) {
28435fdea053SToby Isaac       PetscInt **ownPerms;
28445fdea053SToby Isaac 
28459566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
28465fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28475fdea053SToby Isaac         if (perms[j]) {
28489566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2849ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
28505fdea053SToby Isaac         }
28515fdea053SToby Isaac       }
28525fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
28535fdea053SToby Isaac     }
28545fdea053SToby Isaac     if (rots) {
28555fdea053SToby Isaac       PetscScalar **ownRots;
28565fdea053SToby Isaac 
28579566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
28585fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
28595fdea053SToby Isaac         if (rots[j]) {
28609566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2861ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
28625fdea053SToby Isaac         }
28635fdea053SToby Isaac       }
28645fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
28655fdea053SToby Isaac     }
28665fdea053SToby Isaac   } else {
28678e3a54c0SPierre Jolivet     sl->perms[i] = PetscSafePointerPlusOffset(perms, -minOrient);
28688e3a54c0SPierre Jolivet     sl->rots[i]  = PetscSafePointerPlusOffset(rots, -minOrient);
28695fdea053SToby Isaac   }
28703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28715fdea053SToby Isaac }
28725fdea053SToby Isaac 
2873d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2874d71ae5a4SJacob Faibussowitsch {
28755fdea053SToby Isaac   PetscInt               i, j, numStrata;
28765fdea053SToby Isaac   PetscSectionSym_Label *sl;
28775fdea053SToby Isaac   DMLabel                label;
28785fdea053SToby Isaac 
28795fdea053SToby Isaac   PetscFunctionBegin;
28805fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
28815fdea053SToby Isaac   numStrata = sl->numStrata;
28825fdea053SToby Isaac   label     = sl->label;
28835fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
28845fdea053SToby Isaac     PetscInt point = points[2 * i];
28855fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
28865fdea053SToby Isaac 
28875fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
28885fdea053SToby Isaac       if (label->validIS[j]) {
28895fdea053SToby Isaac         PetscInt k;
28905fdea053SToby Isaac 
28912b4d18a0SMatthew G. Knepley         PetscCall(ISLocate(label->points[j], point, &k));
28925fdea053SToby Isaac         if (k >= 0) break;
28935fdea053SToby Isaac       } else {
28945fdea053SToby Isaac         PetscBool has;
28955fdea053SToby Isaac 
28969566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
28975fdea053SToby Isaac         if (has) break;
28985fdea053SToby Isaac       }
28995fdea053SToby Isaac     }
29009371c9d4SSatish 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],
29019371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2902ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2903ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
29045fdea053SToby Isaac   }
29053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29065fdea053SToby Isaac }
29075fdea053SToby Isaac 
2908d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2909d71ae5a4SJacob Faibussowitsch {
2910b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2911b004864fSMatthew G. Knepley   IS                     valIS;
2912b004864fSMatthew G. Knepley   const PetscInt        *values;
2913b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2914b004864fSMatthew G. Knepley 
2915b004864fSMatthew G. Knepley   PetscFunctionBegin;
29169566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
29179566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
29189566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2919b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2920b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2921b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2922b004864fSMatthew G. Knepley     const PetscInt    **perms;
2923b004864fSMatthew G. Knepley     const PetscScalar **rots;
2924b004864fSMatthew G. Knepley 
29259566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
29269566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2927b004864fSMatthew G. Knepley   }
29289566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
29293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2930b004864fSMatthew G. Knepley }
2931b004864fSMatthew G. Knepley 
2932d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2933d71ae5a4SJacob Faibussowitsch {
2934b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2935b004864fSMatthew G. Knepley   DMLabel                dlabel;
2936b004864fSMatthew G. Knepley 
2937b004864fSMatthew G. Knepley   PetscFunctionBegin;
29389566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
29399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
29409566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
29419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
29423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2943b004864fSMatthew G. Knepley }
2944b004864fSMatthew G. Knepley 
2945d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2946d71ae5a4SJacob Faibussowitsch {
29475fdea053SToby Isaac   PetscSectionSym_Label *sl;
29485fdea053SToby Isaac 
29495fdea053SToby Isaac   PetscFunctionBegin;
29504dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
29515fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2952b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2953b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
29545fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
29555fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
29565fdea053SToby Isaac   sym->data            = (void *)sl;
29573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29585fdea053SToby Isaac }
29595fdea053SToby Isaac 
29605fdea053SToby Isaac /*@
29615fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
29625fdea053SToby Isaac 
29635fdea053SToby Isaac   Collective
29645fdea053SToby Isaac 
29655fdea053SToby Isaac   Input Parameters:
29665fdea053SToby Isaac + comm  - the MPI communicator for the new symmetry
29675fdea053SToby Isaac - label - the label defining the strata
29685fdea053SToby Isaac 
29692fe279fdSBarry Smith   Output Parameter:
29705fdea053SToby Isaac . sym - the section symmetries
29715fdea053SToby Isaac 
29725fdea053SToby Isaac   Level: developer
29735fdea053SToby Isaac 
297420f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
29755fdea053SToby Isaac @*/
2976d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2977d71ae5a4SJacob Faibussowitsch {
29785fdea053SToby Isaac   PetscFunctionBegin;
29799566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
29809566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
29819566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
29829566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
29833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29845fdea053SToby Isaac }
2985