xref: /petsc/src/dm/label/dmlabel.c (revision 20f4b53cbb5e9bd9ef12b76a8697d60d197cda17)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I      "petscdmlabel.h"   I*/
3ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h> /*I      "petscsection.h"   I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5ea844a1aSMatthew Knepley #include <petscsection.h>
6c58f1c22SToby Isaac 
79f6c5813SMatthew G. Knepley PetscFunctionList DMLabelList              = NULL;
89f6c5813SMatthew G. Knepley PetscBool         DMLabelRegisterAllCalled = PETSC_FALSE;
99f6c5813SMatthew G. Knepley 
10c58f1c22SToby Isaac /*@C
11*20f4b53cSBarry Smith   DMLabelCreate - Create a `DMLabel` object, which is a multimap
12c58f1c22SToby Isaac 
135b5e7992SMatthew G. Knepley   Collective
145b5e7992SMatthew G. Knepley 
15d67d17b1SMatthew G. Knepley   Input parameters:
16*20f4b53cSBarry Smith + comm - The communicator, usually `PETSC_COMM_SELF`
17d67d17b1SMatthew G. Knepley - name - The label name
18c58f1c22SToby Isaac 
19c58f1c22SToby Isaac   Output parameter:
20*20f4b53cSBarry Smith . label - The `DMLabel`
21c58f1c22SToby Isaac 
22c58f1c22SToby Isaac   Level: beginner
23c58f1c22SToby Isaac 
2405ab7a9fSVaclav Hapla   Notes:
25*20f4b53cSBarry Smith   The label name is actually usually the `PetscObject` name.
26*20f4b53cSBarry Smith   One can get/set it with `PetscObjectGetName()`/`PetscObjectSetName()`.
2705ab7a9fSVaclav Hapla 
28*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`
29c58f1c22SToby Isaac @*/
30d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
31d71ae5a4SJacob Faibussowitsch {
32c58f1c22SToby Isaac   PetscFunctionBegin;
33064a246eSJacob Faibussowitsch   PetscValidPointer(label, 3);
349566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
35c58f1c22SToby Isaac 
369566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*label, DMLABEL_CLASSID, "DMLabel", "DMLabel", "DM", comm, DMLabelDestroy, DMLabelView));
37d67d17b1SMatthew G. Knepley 
38c58f1c22SToby Isaac   (*label)->numStrata     = 0;
395aa44df4SToby Isaac   (*label)->defaultValue  = -1;
40c58f1c22SToby Isaac   (*label)->stratumValues = NULL;
41ad8374ffSToby Isaac   (*label)->validIS       = NULL;
42c58f1c22SToby Isaac   (*label)->stratumSizes  = NULL;
43c58f1c22SToby Isaac   (*label)->points        = NULL;
44c58f1c22SToby Isaac   (*label)->ht            = NULL;
45c58f1c22SToby Isaac   (*label)->pStart        = -1;
46c58f1c22SToby Isaac   (*label)->pEnd          = -1;
47c58f1c22SToby Isaac   (*label)->bt            = NULL;
489566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
499566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*label, name));
509f6c5813SMatthew G. Knepley   PetscCall(DMLabelSetType(*label, DMLABELCONCRETE));
513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
529f6c5813SMatthew G. Knepley }
539f6c5813SMatthew G. Knepley 
549f6c5813SMatthew G. Knepley /*@C
559f6c5813SMatthew G. Knepley   DMLabelSetUp - SetUp a `DMLabel` object
569f6c5813SMatthew G. Knepley 
579f6c5813SMatthew G. Knepley   Collective
589f6c5813SMatthew G. Knepley 
599f6c5813SMatthew G. Knepley   Input parameters:
609f6c5813SMatthew G. Knepley . label - The `DMLabel`
619f6c5813SMatthew G. Knepley 
629f6c5813SMatthew G. Knepley   Level: intermediate
639f6c5813SMatthew G. Knepley 
64*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
659f6c5813SMatthew G. Knepley @*/
669f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetUp(DMLabel label)
679f6c5813SMatthew G. Knepley {
689f6c5813SMatthew G. Knepley   PetscFunctionBegin;
699f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
709f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, setup);
713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72c58f1c22SToby Isaac }
73c58f1c22SToby Isaac 
74c58f1c22SToby Isaac /*
75c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
76c58f1c22SToby Isaac 
775b5e7992SMatthew G. Knepley   Not collective
785b5e7992SMatthew G. Knepley 
79c58f1c22SToby Isaac   Input parameter:
80*20f4b53cSBarry Smith + label - The `DMLabel`
81c58f1c22SToby Isaac - v - The stratum value
82c58f1c22SToby Isaac 
83c58f1c22SToby Isaac   Output parameter:
84*20f4b53cSBarry Smith . label - The `DMLabel` with stratum in sorted list format
85c58f1c22SToby Isaac 
86c58f1c22SToby Isaac   Level: developer
87c58f1c22SToby Isaac 
88*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`
89c58f1c22SToby Isaac */
90d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
91d71ae5a4SJacob Faibussowitsch {
92277ea44aSLisandro Dalcin   IS       is;
93b9907514SLisandro Dalcin   PetscInt off = 0, *pointArray, p;
94c58f1c22SToby Isaac 
953ba16761SJacob Faibussowitsch   if ((PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) || label->readonly) return PETSC_SUCCESS;
96c58f1c22SToby Isaac   PetscFunctionBegin;
971dca8a05SBarry Smith   PetscCheck(v >= 0 && v < label->numStrata, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeValid_Private", v);
989566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
1009566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
1019566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
1029566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
103c58f1c22SToby Isaac   if (label->bt) {
104c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
105ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
10663a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
1079566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
108c58f1c22SToby Isaac     }
109c58f1c22SToby Isaac   }
110ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v] - 1] == pointArray[0] + label->stratumSizes[v] - 1) {
1119566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
1129566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
113ba2698f1SMatthew G. Knepley   } else {
1149566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
115ba2698f1SMatthew G. Knepley   }
1169566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)is, "indices"));
117277ea44aSLisandro Dalcin   label->points[v]  = is;
118ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
1199566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
1203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121c58f1c22SToby Isaac }
122c58f1c22SToby Isaac 
123c58f1c22SToby Isaac /*
124c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
125c58f1c22SToby Isaac 
126*20f4b53cSBarry Smith   Not Collective
1275b5e7992SMatthew G. Knepley 
128c58f1c22SToby Isaac   Input parameter:
129*20f4b53cSBarry Smith . label - The `DMLabel`
130c58f1c22SToby Isaac 
131c58f1c22SToby Isaac   Output parameter:
132*20f4b53cSBarry Smith . label - The `DMLabel` with all strata in sorted list format
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Level: developer
135c58f1c22SToby Isaac 
136*20f4b53cSBarry 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 
150*20f4b53cSBarry Smith   Not Collective
1515b5e7992SMatthew G. Knepley 
152c58f1c22SToby Isaac   Input parameter:
153*20f4b53cSBarry Smith + label - The `DMLabel`
154c58f1c22SToby Isaac - v - The stratum value
155c58f1c22SToby Isaac 
156c58f1c22SToby Isaac   Output parameter:
157*20f4b53cSBarry Smith . label - The `DMLabel` with stratum in hash format
158c58f1c22SToby Isaac 
159c58f1c22SToby Isaac   Level: developer
160c58f1c22SToby Isaac 
161*20f4b53cSBarry 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 
1683ba16761SJacob Faibussowitsch   if ((PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) || label->readonly) return PETSC_SUCCESS;
169c58f1c22SToby Isaac   PetscFunctionBegin;
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));
1759566063dSJacob Faibussowitsch     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 /*@
307*20f4b53cSBarry Smith   DMLabelAddStratum - Adds a new stratum value in a `DMLabel`
308b9907514SLisandro Dalcin 
309d8d19677SJose E. Roman   Input Parameters:
310*20f4b53cSBarry Smith + label - The `DMLabel`
311b9907514SLisandro Dalcin - value - The stratum value
312b9907514SLisandro Dalcin 
313b9907514SLisandro Dalcin   Level: beginner
314b9907514SLisandro Dalcin 
315*20f4b53cSBarry 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 /*@
329*20f4b53cSBarry Smith   DMLabelAddStrata - Adds new stratum values in a `DMLabel`
330b9907514SLisandro Dalcin 
331*20f4b53cSBarry Smith   Not Collective
3325b5e7992SMatthew G. Knepley 
333d8d19677SJose E. Roman   Input Parameters:
334*20f4b53cSBarry 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 
340*20f4b53cSBarry 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);
348b9907514SLisandro Dalcin   if (numStrata) PetscValidIntPointer(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 /*@
391*20f4b53cSBarry Smith   DMLabelAddStrataIS - Adds new stratum values in a `DMLabel`
392b9907514SLisandro Dalcin 
393*20f4b53cSBarry Smith   Not Collective
3945b5e7992SMatthew G. Knepley 
395d8d19677SJose E. Roman   Input Parameters:
396*20f4b53cSBarry Smith + label - The `DMLabel`
397b9907514SLisandro Dalcin - valueIS - Index set with stratum values
398b9907514SLisandro Dalcin 
399b9907514SLisandro Dalcin   Level: beginner
400b9907514SLisandro Dalcin 
401*20f4b53cSBarry 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 
4479f6c5813SMatthew G. Knepley PetscErrorCode DMLabelView_Concrete(DMLabel label, PetscViewer viewer)
4489f6c5813SMatthew G. Knepley {
4499f6c5813SMatthew G. Knepley   PetscBool iascii;
4509f6c5813SMatthew G. Knepley 
4519f6c5813SMatthew G. Knepley   PetscFunctionBegin;
4529f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4539f6c5813SMatthew G. Knepley   if (iascii) PetscCall(DMLabelView_Concrete_Ascii(label, viewer));
4543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4559f6c5813SMatthew G. Knepley }
4569f6c5813SMatthew G. Knepley 
457c58f1c22SToby Isaac /*@C
458c58f1c22SToby Isaac   DMLabelView - View the label
459c58f1c22SToby Isaac 
460*20f4b53cSBarry Smith   Collective
4615b5e7992SMatthew G. Knepley 
462c58f1c22SToby Isaac   Input Parameters:
463*20f4b53cSBarry Smith + label - The `DMLabel`
464*20f4b53cSBarry Smith - viewer - The `PetscViewer`
465c58f1c22SToby Isaac 
466c58f1c22SToby Isaac   Level: intermediate
467c58f1c22SToby Isaac 
468*20f4b53cSBarry 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*20f4b53cSBarry Smith   DMLabelReset - Destroys internal data structures in a `DMLabel`
483d67d17b1SMatthew G. Knepley 
484*20f4b53cSBarry Smith   Not Collective
4855b5e7992SMatthew G. Knepley 
486d67d17b1SMatthew G. Knepley   Input Parameter:
487*20f4b53cSBarry Smith . label - The `DMLabel`
488d67d17b1SMatthew G. Knepley 
489d67d17b1SMatthew G. Knepley   Level: beginner
490d67d17b1SMatthew G. Knepley 
491*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDestroy()`, `DMLabelCreate()`
492d67d17b1SMatthew G. Knepley @*/
493d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelReset(DMLabel label)
494d71ae5a4SJacob Faibussowitsch {
495d67d17b1SMatthew G. Knepley   PetscInt v;
496d67d17b1SMatthew G. Knepley 
497d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
498d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
499d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
5009f6c5813SMatthew G. Knepley     if (label->ht[v]) PetscCall(PetscHSetIDestroy(&label->ht[v]));
5019566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
502d67d17b1SMatthew G. Knepley   }
503b9907514SLisandro Dalcin   label->numStrata = 0;
5049566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
5059566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
5069566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
5079566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
5089566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
509f9244615SMatthew G. Knepley   label->stratumValues = NULL;
510f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
511f9244615SMatthew G. Knepley   label->ht            = NULL;
512f9244615SMatthew G. Knepley   label->points        = NULL;
513f9244615SMatthew G. Knepley   label->validIS       = NULL;
5149566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
515b9907514SLisandro Dalcin   label->pStart = -1;
516b9907514SLisandro Dalcin   label->pEnd   = -1;
5179566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
5183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
519d67d17b1SMatthew G. Knepley }
520d67d17b1SMatthew G. Knepley 
521d67d17b1SMatthew G. Knepley /*@
522*20f4b53cSBarry Smith   DMLabelDestroy - Destroys a `DMLabel`
52384f0b6dfSMatthew G. Knepley 
524*20f4b53cSBarry Smith   Collective
5255b5e7992SMatthew G. Knepley 
52684f0b6dfSMatthew G. Knepley   Input Parameter:
527*20f4b53cSBarry Smith . label - The `DMLabel`
52884f0b6dfSMatthew G. Knepley 
52984f0b6dfSMatthew G. Knepley   Level: beginner
53084f0b6dfSMatthew G. Knepley 
531*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelReset()`, `DMLabelCreate()`
53284f0b6dfSMatthew G. Knepley @*/
533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
534d71ae5a4SJacob Faibussowitsch {
535c58f1c22SToby Isaac   PetscFunctionBegin;
5363ba16761SJacob Faibussowitsch   if (!*label) PetscFunctionReturn(PETSC_SUCCESS);
537d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label), DMLABEL_CLASSID, 1);
5389371c9d4SSatish Balay   if (--((PetscObject)(*label))->refct > 0) {
5399371c9d4SSatish Balay     *label = NULL;
5403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5419371c9d4SSatish Balay   }
5429566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5439566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5449566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
5453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546c58f1c22SToby Isaac }
547c58f1c22SToby Isaac 
5489f6c5813SMatthew G. Knepley PetscErrorCode DMLabelDuplicate_Concrete(DMLabel label, DMLabel *labelnew)
5499f6c5813SMatthew G. Knepley {
5509f6c5813SMatthew G. Knepley   PetscFunctionBegin;
5519f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
5529f6c5813SMatthew G. Knepley     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
5539f6c5813SMatthew G. Knepley     PetscCall(PetscObjectReference((PetscObject)(label->points[v])));
5549f6c5813SMatthew G. Knepley     (*labelnew)->points[v] = label->points[v];
5559f6c5813SMatthew G. Knepley   }
5569f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5579f6c5813SMatthew G. Knepley   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
5583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5599f6c5813SMatthew G. Knepley }
5609f6c5813SMatthew G. Knepley 
56184f0b6dfSMatthew G. Knepley /*@
562*20f4b53cSBarry Smith   DMLabelDuplicate - Duplicates a `DMLabel`
56384f0b6dfSMatthew G. Knepley 
564*20f4b53cSBarry Smith   Collective
5655b5e7992SMatthew G. Knepley 
56684f0b6dfSMatthew G. Knepley   Input Parameter:
567*20f4b53cSBarry Smith . label - The `DMLabel`
56884f0b6dfSMatthew G. Knepley 
56984f0b6dfSMatthew G. Knepley   Output Parameter:
570*20f4b53cSBarry Smith . labelnew - new label
57184f0b6dfSMatthew G. Knepley 
57284f0b6dfSMatthew G. Knepley   Level: intermediate
57384f0b6dfSMatthew G. Knepley 
574*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelDestroy()`
57584f0b6dfSMatthew G. Knepley @*/
576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
577d71ae5a4SJacob Faibussowitsch {
578d67d17b1SMatthew G. Knepley   const char *name;
579c58f1c22SToby Isaac 
580c58f1c22SToby Isaac   PetscFunctionBegin;
581d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5829566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5839566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
5849566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
585c58f1c22SToby Isaac 
586c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5875aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5909f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->ht));
5919f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1(label->numStrata, &(*labelnew)->points));
5929566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
5939f6c5813SMatthew G. Knepley   for (PetscInt v = 0; v < label->numStrata; ++v) {
594c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
595c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
596b9907514SLisandro Dalcin     (*labelnew)->validIS[v]       = PETSC_TRUE;
597c58f1c22SToby Isaac   }
598c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
599c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
600c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
6019f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, duplicate, labelnew);
6023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
603c58f1c22SToby Isaac }
604c58f1c22SToby Isaac 
605609dae6eSVaclav Hapla /*@C
606*20f4b53cSBarry Smith   DMLabelCompare - Compare two `DMLabel` objects
607609dae6eSVaclav Hapla 
608*20f4b53cSBarry Smith   Collective; No Fortran Support
609609dae6eSVaclav Hapla 
610609dae6eSVaclav Hapla   Input Parameters:
611f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
612*20f4b53cSBarry Smith . l0 - First `DMLabel`
613*20f4b53cSBarry Smith - l1 - Second `DMLabel`
614609dae6eSVaclav Hapla 
615609dae6eSVaclav Hapla   Output Parameters
6165efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
6175efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
618609dae6eSVaclav Hapla 
619609dae6eSVaclav Hapla   Level: intermediate
620609dae6eSVaclav Hapla 
621609dae6eSVaclav Hapla   Notes:
6225efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
623*20f4b53cSBarry Smith   If it is passed as `NULL` and difference is found, an error is thrown on all processes.
624*20f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
625609dae6eSVaclav Hapla 
6265efe38ccSVaclav Hapla   The output message is set independently on each rank.
627*20f4b53cSBarry Smith   It is set to `NULL` if no difference was found on the current rank. It must be freed by user.
628*20f4b53cSBarry Smith   If message is passed as `NULL` and difference is found, the difference description is printed to stderr in synchronized manner.
629*20f4b53cSBarry Smith   Make sure to pass `NULL` on all processes.
630609dae6eSVaclav Hapla 
631609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
632609dae6eSVaclav Hapla 
633*20f4b53cSBarry Smith   The communicator needs to be specified because currently `DMLabel` can live on `PETSC_COMM_SELF` even if the underlying `DM` is parallel.
6345efe38ccSVaclav Hapla 
635*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
636609dae6eSVaclav Hapla @*/
637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
638d71ae5a4SJacob Faibussowitsch {
639609dae6eSVaclav Hapla   const char *name0, *name1;
640609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6415efe38ccSVaclav Hapla   PetscBool   eq;
6425efe38ccSVaclav Hapla   PetscMPIInt rank;
643609dae6eSVaclav Hapla 
644609dae6eSVaclav Hapla   PetscFunctionBegin;
6455efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6465efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6475efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
6485efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
6499566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6519566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
652609dae6eSVaclav Hapla   {
653609dae6eSVaclav Hapla     PetscInt v0, v1;
654609dae6eSVaclav Hapla 
6559566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6569566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6575efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
65848a46eb9SPierre 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));
6599566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6605efe38ccSVaclav Hapla     if (!eq) goto finish;
661609dae6eSVaclav Hapla   }
662609dae6eSVaclav Hapla   {
663609dae6eSVaclav Hapla     IS is0, is1;
664609dae6eSVaclav Hapla 
6659566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6669566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6679566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6689566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6699566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
67048a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
6719566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6725efe38ccSVaclav Hapla     if (!eq) goto finish;
673609dae6eSVaclav Hapla   }
674609dae6eSVaclav Hapla   {
675609dae6eSVaclav Hapla     PetscInt i, nValues;
676609dae6eSVaclav Hapla 
6779566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
678609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
679609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
680609dae6eSVaclav Hapla       PetscInt       n;
681609dae6eSVaclav Hapla       IS             is0, is1;
682609dae6eSVaclav Hapla 
6839566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
684609dae6eSVaclav Hapla       if (!n) continue;
6859566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6869566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6879566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6889566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6899566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6905efe38ccSVaclav Hapla       if (!eq) {
69163a3b9bcSJacob 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));
6925efe38ccSVaclav Hapla         break;
693609dae6eSVaclav Hapla       }
694609dae6eSVaclav Hapla     }
6959566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
696609dae6eSVaclav Hapla   }
697609dae6eSVaclav Hapla finish:
6985efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
699609dae6eSVaclav Hapla   if (message) {
700609dae6eSVaclav Hapla     *message = NULL;
70148a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
7025efe38ccSVaclav Hapla   } else {
70348a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
7049566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
7055efe38ccSVaclav Hapla   }
7065efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
7075efe38ccSVaclav Hapla   if (equal) *equal = eq;
70863a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
7093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
710609dae6eSVaclav Hapla }
711609dae6eSVaclav Hapla 
712c6a43d28SMatthew G. Knepley /*@
713c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
714c6a43d28SMatthew G. Knepley 
715*20f4b53cSBarry Smith   Not Collective
7165b5e7992SMatthew G. Knepley 
717c6a43d28SMatthew G. Knepley   Input Parameter:
718*20f4b53cSBarry Smith . label  - The `DMLabel`
719c6a43d28SMatthew G. Knepley 
720c6a43d28SMatthew G. Knepley   Level: intermediate
721c6a43d28SMatthew G. Knepley 
722*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
723c6a43d28SMatthew G. Knepley @*/
724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
725d71ae5a4SJacob Faibussowitsch {
726c6a43d28SMatthew G. Knepley   PetscInt pStart = PETSC_MAX_INT, pEnd = -1, v;
727c6a43d28SMatthew G. Knepley 
728c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
729c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7309566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
731c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
732c6a43d28SMatthew G. Knepley     const PetscInt *points;
733c6a43d28SMatthew G. Knepley     PetscInt        i;
734c6a43d28SMatthew G. Knepley 
7359566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
736c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
737c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
738c6a43d28SMatthew G. Knepley 
739c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
740c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
741c6a43d28SMatthew G. Knepley     }
7429566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
743c6a43d28SMatthew G. Knepley   }
744c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
745c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7469566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
7473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
748c6a43d28SMatthew G. Knepley }
749c6a43d28SMatthew G. Knepley 
750c6a43d28SMatthew G. Knepley /*@
751c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
752c6a43d28SMatthew G. Knepley 
753*20f4b53cSBarry Smith   Not Collective
7545b5e7992SMatthew G. Knepley 
755c6a43d28SMatthew G. Knepley   Input Parameters:
756*20f4b53cSBarry Smith + label  - The `DMLabel`
757c6a43d28SMatthew G. Knepley . pStart - The smallest point
758c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
759c6a43d28SMatthew G. Knepley 
760c6a43d28SMatthew G. Knepley   Level: intermediate
761c6a43d28SMatthew G. Knepley 
762*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
763c6a43d28SMatthew G. Knepley @*/
764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
765d71ae5a4SJacob Faibussowitsch {
766c58f1c22SToby Isaac   PetscInt v;
767c58f1c22SToby Isaac 
768c58f1c22SToby Isaac   PetscFunctionBegin;
769d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7709566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7719566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
772c58f1c22SToby Isaac   label->pStart = pStart;
773c58f1c22SToby Isaac   label->pEnd   = pEnd;
774c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7759566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
776c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
7779f6c5813SMatthew G. Knepley     IS              pointIS;
778ad8374ffSToby Isaac     const PetscInt *points;
779c58f1c22SToby Isaac     PetscInt        i;
780c58f1c22SToby Isaac 
7819f6c5813SMatthew G. Knepley     PetscUseTypeMethod(label, getstratumis, v, &pointIS);
7829f6c5813SMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
783c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
784ad8374ffSToby Isaac       const PetscInt point = points[i];
785c58f1c22SToby Isaac 
7869f6c5813SMatthew 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);
7879566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
788c58f1c22SToby Isaac     }
7899566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
7909f6c5813SMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
791c58f1c22SToby Isaac   }
7923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
793c58f1c22SToby Isaac }
794c58f1c22SToby Isaac 
795c6a43d28SMatthew G. Knepley /*@
796c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
797c6a43d28SMatthew G. Knepley 
798*20f4b53cSBarry Smith   Not Collective
7995b5e7992SMatthew G. Knepley 
800c6a43d28SMatthew G. Knepley   Input Parameter:
801*20f4b53cSBarry Smith . label - the `DMLabel`
802c6a43d28SMatthew G. Knepley 
803c6a43d28SMatthew G. Knepley   Level: intermediate
804c6a43d28SMatthew G. Knepley 
805*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
806c6a43d28SMatthew G. Knepley @*/
807d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
808d71ae5a4SJacob Faibussowitsch {
809c58f1c22SToby Isaac   PetscFunctionBegin;
810d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
811c58f1c22SToby Isaac   label->pStart = -1;
812c58f1c22SToby Isaac   label->pEnd   = -1;
8139566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
8143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
815c58f1c22SToby Isaac }
816c58f1c22SToby Isaac 
817c58f1c22SToby Isaac /*@
818c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
819c6a43d28SMatthew G. Knepley 
820*20f4b53cSBarry Smith   Not Collective
8215b5e7992SMatthew G. Knepley 
822c6a43d28SMatthew G. Knepley   Input Parameter:
823*20f4b53cSBarry Smith . label - the `DMLabel`
824c6a43d28SMatthew G. Knepley 
825c6a43d28SMatthew G. Knepley   Output Parameters:
826c6a43d28SMatthew G. Knepley + pStart - The smallest point
827c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
828c6a43d28SMatthew G. Knepley 
829c6a43d28SMatthew G. Knepley   Level: intermediate
830c6a43d28SMatthew G. Knepley 
831*20f4b53cSBarry Smith   Note:
832*20f4b53cSBarry Smith   This will compute an index for the label if one does not exist.
833*20f4b53cSBarry Smith 
834*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
835c6a43d28SMatthew G. Knepley @*/
836d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
837d71ae5a4SJacob Faibussowitsch {
838c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
839c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8409566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
841c6a43d28SMatthew G. Knepley   if (pStart) {
842534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
843c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
844c6a43d28SMatthew G. Knepley   }
845c6a43d28SMatthew G. Knepley   if (pEnd) {
846534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
847c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
848c6a43d28SMatthew G. Knepley   }
8493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
850c6a43d28SMatthew G. Knepley }
851c6a43d28SMatthew G. Knepley 
852c6a43d28SMatthew G. Knepley /*@
853c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
854c58f1c22SToby Isaac 
855*20f4b53cSBarry Smith   Not Collective
8565b5e7992SMatthew G. Knepley 
857c58f1c22SToby Isaac   Input Parameters:
858*20f4b53cSBarry Smith + label - the `DMLabel`
859c58f1c22SToby Isaac - value - the value
860c58f1c22SToby Isaac 
861c58f1c22SToby Isaac   Output Parameter:
862c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
863c58f1c22SToby Isaac 
864c58f1c22SToby Isaac   Level: developer
865c58f1c22SToby Isaac 
866*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
867c58f1c22SToby Isaac @*/
868d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
869d71ae5a4SJacob Faibussowitsch {
870c58f1c22SToby Isaac   PetscInt v;
871c58f1c22SToby Isaac 
872c58f1c22SToby Isaac   PetscFunctionBegin;
873d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
874534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8759566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8760c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
8773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
878c58f1c22SToby Isaac }
879c58f1c22SToby Isaac 
880c58f1c22SToby Isaac /*@
881c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
882c58f1c22SToby Isaac 
883*20f4b53cSBarry Smith   Not Collective
8845b5e7992SMatthew G. Knepley 
885c58f1c22SToby Isaac   Input Parameters:
886*20f4b53cSBarry Smith + label - the `DMLabel`
887c58f1c22SToby Isaac - point - the point
888c58f1c22SToby Isaac 
889c58f1c22SToby Isaac   Output Parameter:
890c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
891c58f1c22SToby Isaac 
892c58f1c22SToby Isaac   Level: developer
893c58f1c22SToby Isaac 
894*20f4b53cSBarry Smith   Note:
895*20f4b53cSBarry Smith   The user must call `DMLabelCreateIndex()` before this function.
896*20f4b53cSBarry Smith 
897*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
898c58f1c22SToby Isaac @*/
899d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
900d71ae5a4SJacob Faibussowitsch {
901c58f1c22SToby Isaac   PetscFunctionBeginHot;
902d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
903534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
9049566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
90576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
90628b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
90763a3b9bcSJacob 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);
90876bd3646SJed Brown   }
909c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
9103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
911c58f1c22SToby Isaac }
912c58f1c22SToby Isaac 
913c58f1c22SToby Isaac /*@
914c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
915c58f1c22SToby Isaac 
916*20f4b53cSBarry Smith   Not Collective
9175b5e7992SMatthew G. Knepley 
918c58f1c22SToby Isaac   Input Parameters:
919*20f4b53cSBarry Smith + label - the `DMLabel`
920c58f1c22SToby Isaac . value - the stratum value
921c58f1c22SToby Isaac - point - the point
922c58f1c22SToby Isaac 
923c58f1c22SToby Isaac   Output Parameter:
924c58f1c22SToby Isaac . contains - true if the stratum contains the point
925c58f1c22SToby Isaac 
926c58f1c22SToby Isaac   Level: intermediate
927c58f1c22SToby Isaac 
928*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
929c58f1c22SToby Isaac @*/
930d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
931d71ae5a4SJacob Faibussowitsch {
9320c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
933d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
934534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
935cffad2c9SToby Isaac   if (value == label->defaultValue) {
936cffad2c9SToby Isaac     PetscInt pointVal;
9370c3c4a36SLisandro Dalcin 
938cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
939cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
940cffad2c9SToby Isaac   } else {
941cffad2c9SToby Isaac     PetscInt v;
942cffad2c9SToby Isaac 
943cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
944cffad2c9SToby Isaac     if (v >= 0) {
9459f6c5813SMatthew G. Knepley       if (label->validIS[v] || label->readonly) {
9469f6c5813SMatthew G. Knepley         IS       is;
947c58f1c22SToby Isaac         PetscInt i;
948c58f1c22SToby Isaac 
9499f6c5813SMatthew G. Knepley         PetscUseTypeMethod(label, getstratumis, v, &is);
9509f6c5813SMatthew G. Knepley         PetscCall(ISLocate(is, point, &i));
9519f6c5813SMatthew G. Knepley         PetscCall(ISDestroy(&is));
952cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
953c58f1c22SToby Isaac       } else {
954cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
955cffad2c9SToby Isaac       }
956cffad2c9SToby Isaac     } else { // value is not present
957cffad2c9SToby Isaac       *contains = PETSC_FALSE;
958cffad2c9SToby Isaac     }
959c58f1c22SToby Isaac   }
9603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
961c58f1c22SToby Isaac }
962c58f1c22SToby Isaac 
96384f0b6dfSMatthew G. Knepley /*@
964*20f4b53cSBarry Smith   DMLabelGetDefaultValue - Get the default value returned by `DMLabelGetValue()` if a point has not been explicitly given a value.
9655aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9665aa44df4SToby Isaac 
967*20f4b53cSBarry Smith   Not Collective
9685b5e7992SMatthew G. Knepley 
9695aa44df4SToby Isaac   Input parameter:
970*20f4b53cSBarry Smith . label - a `DMLabel` object
9715aa44df4SToby Isaac 
9725aa44df4SToby Isaac   Output parameter:
9735aa44df4SToby Isaac . defaultValue - the default value
9745aa44df4SToby Isaac 
9755aa44df4SToby Isaac   Level: beginner
9765aa44df4SToby Isaac 
977*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
97884f0b6dfSMatthew G. Knepley @*/
979d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
980d71ae5a4SJacob Faibussowitsch {
9815aa44df4SToby Isaac   PetscFunctionBegin;
982d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9835aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9855aa44df4SToby Isaac }
9865aa44df4SToby Isaac 
98784f0b6dfSMatthew G. Knepley /*@
988*20f4b53cSBarry Smith   DMLabelSetDefaultValue - Set 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 
991*20f4b53cSBarry Smith   Not Collective
9925b5e7992SMatthew G. Knepley 
9935aa44df4SToby Isaac   Input parameter:
994*20f4b53cSBarry Smith . label - a `DMLabel` object
9955aa44df4SToby Isaac 
9965aa44df4SToby Isaac   Output parameter:
9975aa44df4SToby Isaac . defaultValue - the default value
9985aa44df4SToby Isaac 
9995aa44df4SToby Isaac   Level: beginner
10005aa44df4SToby Isaac 
1001*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
100284f0b6dfSMatthew G. Knepley @*/
1003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1004d71ae5a4SJacob Faibussowitsch {
10055aa44df4SToby Isaac   PetscFunctionBegin;
1006d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10075aa44df4SToby Isaac   label->defaultValue = defaultValue;
10083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10095aa44df4SToby Isaac }
10105aa44df4SToby Isaac 
1011c58f1c22SToby Isaac /*@
1012*20f4b53cSBarry 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
1013*20f4b53cSBarry Smith                     `DMLabelSetDefaultValue()`)
1014c58f1c22SToby Isaac 
1015*20f4b53cSBarry Smith   Not Collective
10165b5e7992SMatthew G. Knepley 
1017c58f1c22SToby Isaac   Input Parameters:
1018*20f4b53cSBarry Smith + label - the `DMLabel`
1019c58f1c22SToby Isaac - point - the point
1020c58f1c22SToby Isaac 
1021c58f1c22SToby Isaac   Output Parameter:
10228e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
1023c58f1c22SToby Isaac 
1024c58f1c22SToby Isaac   Level: intermediate
1025c58f1c22SToby Isaac 
1026*20f4b53cSBarry Smith   Note:
1027*20f4b53cSBarry Smith   A label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.
1028*20f4b53cSBarry Smith   Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
1029*20f4b53cSBarry Smith 
1030*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1031c58f1c22SToby Isaac @*/
1032d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1033d71ae5a4SJacob Faibussowitsch {
1034c58f1c22SToby Isaac   PetscInt v;
1035c58f1c22SToby Isaac 
10360c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
1037d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1038dadcf809SJacob Faibussowitsch   PetscValidIntPointer(value, 3);
10395aa44df4SToby Isaac   *value = label->defaultValue;
1040c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
10419f6c5813SMatthew G. Knepley     if (label->validIS[v] || label->readonly) {
10429f6c5813SMatthew G. Knepley       IS       is;
1043c58f1c22SToby Isaac       PetscInt i;
1044c58f1c22SToby Isaac 
10459f6c5813SMatthew G. Knepley       PetscUseTypeMethod(label, getstratumis, v, &is);
10469566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
10479f6c5813SMatthew G. Knepley       PetscCall(ISDestroy(&is));
1048c58f1c22SToby Isaac       if (i >= 0) {
1049c58f1c22SToby Isaac         *value = label->stratumValues[v];
1050c58f1c22SToby Isaac         break;
1051c58f1c22SToby Isaac       }
1052c58f1c22SToby Isaac     } else {
1053c58f1c22SToby Isaac       PetscBool has;
1054c58f1c22SToby Isaac 
10559566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1056c58f1c22SToby Isaac       if (has) {
1057c58f1c22SToby Isaac         *value = label->stratumValues[v];
1058c58f1c22SToby Isaac         break;
1059c58f1c22SToby Isaac       }
1060c58f1c22SToby Isaac     }
1061c58f1c22SToby Isaac   }
10623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1063c58f1c22SToby Isaac }
1064c58f1c22SToby Isaac 
1065c58f1c22SToby Isaac /*@
1066*20f4b53cSBarry 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
1067*20f4b53cSBarry Smith   be changed with `DMLabelSetDefaultValue()` to something different), then this function will do nothing.
1068c58f1c22SToby Isaac 
1069*20f4b53cSBarry Smith   Not Collective
10705b5e7992SMatthew G. Knepley 
1071c58f1c22SToby Isaac   Input Parameters:
1072*20f4b53cSBarry Smith + label - the `DMLabel`
1073c58f1c22SToby Isaac . point - the point
1074c58f1c22SToby Isaac - value - The point value
1075c58f1c22SToby Isaac 
1076c58f1c22SToby Isaac   Level: intermediate
1077c58f1c22SToby Isaac 
1078*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1079c58f1c22SToby Isaac @*/
1080d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1081d71ae5a4SJacob Faibussowitsch {
1082c58f1c22SToby Isaac   PetscInt v;
1083c58f1c22SToby Isaac 
1084c58f1c22SToby Isaac   PetscFunctionBegin;
1085d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10860c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10873ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
10889f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
10899566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1090c58f1c22SToby Isaac   /* Set key */
10919566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10929566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
10933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1094c58f1c22SToby Isaac }
1095c58f1c22SToby Isaac 
1096c58f1c22SToby Isaac /*@
1097c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1098c58f1c22SToby Isaac 
1099*20f4b53cSBarry Smith   Not Collective
11005b5e7992SMatthew G. Knepley 
1101c58f1c22SToby Isaac   Input Parameters:
1102*20f4b53cSBarry Smith + label - the `DMLabel`
1103c58f1c22SToby Isaac . point - the point
1104c58f1c22SToby Isaac - value - The point value
1105c58f1c22SToby Isaac 
1106c58f1c22SToby Isaac   Level: intermediate
1107c58f1c22SToby Isaac 
1108*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1109c58f1c22SToby Isaac @*/
1110d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1111d71ae5a4SJacob Faibussowitsch {
1112ad8374ffSToby Isaac   PetscInt v;
1113c58f1c22SToby Isaac 
1114c58f1c22SToby Isaac   PetscFunctionBegin;
1115d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11169f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1117c58f1c22SToby Isaac   /* Find label value */
11189566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
11193ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
11200c3c4a36SLisandro Dalcin 
1121eeed21e7SToby Isaac   if (label->bt) {
112263a3b9bcSJacob 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);
11239566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1124eeed21e7SToby Isaac   }
11250c3c4a36SLisandro Dalcin 
11260c3c4a36SLisandro Dalcin   /* Delete key */
11279566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11289566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
11293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1130c58f1c22SToby Isaac }
1131c58f1c22SToby Isaac 
1132c58f1c22SToby Isaac /*@
1133*20f4b53cSBarry Smith   DMLabelInsertIS - Set all points in the `IS` to a value
1134c58f1c22SToby Isaac 
1135*20f4b53cSBarry Smith   Not Collective
11365b5e7992SMatthew G. Knepley 
1137c58f1c22SToby Isaac   Input Parameters:
1138*20f4b53cSBarry Smith + label - the `DMLabel`
1139c58f1c22SToby Isaac . is    - the point IS
1140c58f1c22SToby Isaac - value - The point value
1141c58f1c22SToby Isaac 
1142c58f1c22SToby Isaac   Level: intermediate
1143c58f1c22SToby Isaac 
1144*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1145c58f1c22SToby Isaac @*/
1146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1147d71ae5a4SJacob Faibussowitsch {
11480c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1149c58f1c22SToby Isaac   const PetscInt *points;
1150c58f1c22SToby Isaac 
1151c58f1c22SToby Isaac   PetscFunctionBegin;
1152d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1153c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11540c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11553ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11569f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11579566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11580c3c4a36SLisandro Dalcin   /* Set keys */
11599566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11609566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11619566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11629566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11639566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
11643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1165c58f1c22SToby Isaac }
1166c58f1c22SToby Isaac 
116784f0b6dfSMatthew G. Knepley /*@
1168*20f4b53cSBarry Smith   DMLabelGetNumValues - Get the number of values that the `DMLabel` takes
116984f0b6dfSMatthew G. Knepley 
1170*20f4b53cSBarry Smith   Not Collective
11715b5e7992SMatthew G. Knepley 
117284f0b6dfSMatthew G. Knepley   Input Parameter:
1173*20f4b53cSBarry Smith . label - the `DMLabel`
117484f0b6dfSMatthew G. Knepley 
117501d2d390SJose E. Roman   Output Parameter:
117684f0b6dfSMatthew G. Knepley . numValues - the number of values
117784f0b6dfSMatthew G. Knepley 
117884f0b6dfSMatthew G. Knepley   Level: intermediate
117984f0b6dfSMatthew G. Knepley 
1180*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
118184f0b6dfSMatthew G. Knepley @*/
1182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1183d71ae5a4SJacob Faibussowitsch {
1184c58f1c22SToby Isaac   PetscFunctionBegin;
1185d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1186dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numValues, 2);
1187c58f1c22SToby Isaac   *numValues = label->numStrata;
11883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1189c58f1c22SToby Isaac }
1190c58f1c22SToby Isaac 
119184f0b6dfSMatthew G. Knepley /*@
1192*20f4b53cSBarry Smith   DMLabelGetValueIS - Get an `IS` of all values that the `DMlabel` takes
119384f0b6dfSMatthew G. Knepley 
1194*20f4b53cSBarry Smith   Not Collective
11955b5e7992SMatthew G. Knepley 
119684f0b6dfSMatthew G. Knepley   Input Parameter:
1197*20f4b53cSBarry Smith . label - the `DMLabel`
119884f0b6dfSMatthew G. Knepley 
119901d2d390SJose E. Roman   Output Parameter:
1200*20f4b53cSBarry Smith . is    - the value `IS`
120184f0b6dfSMatthew G. Knepley 
120284f0b6dfSMatthew G. Knepley   Level: intermediate
120384f0b6dfSMatthew G. Knepley 
12041d04cbbeSVaclav Hapla   Notes:
1205*20f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
1206*20f4b53cSBarry Smith   Strata which are allocated but empty [`DMLabelGetStratumSize()` yields 0] are counted.
1207*20f4b53cSBarry Smith   If you need to count only nonempty strata, use `DMLabelGetNonEmptyStratumValuesIS()`.
12081d04cbbeSVaclav Hapla 
1209*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
121084f0b6dfSMatthew G. Knepley @*/
1211d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1212d71ae5a4SJacob Faibussowitsch {
1213c58f1c22SToby Isaac   PetscFunctionBegin;
1214d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1215c58f1c22SToby Isaac   PetscValidPointer(values, 2);
12169566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1218c58f1c22SToby Isaac }
1219c58f1c22SToby Isaac 
122084f0b6dfSMatthew G. Knepley /*@
1221*20f4b53cSBarry Smith   DMLabelGetNonEmptyStratumValuesIS - Get an `IS` of all values that the `DMlabel` takes
12221d04cbbeSVaclav Hapla 
1223*20f4b53cSBarry Smith   Not Collective
12241d04cbbeSVaclav Hapla 
12251d04cbbeSVaclav Hapla   Input Parameter:
1226*20f4b53cSBarry Smith . label - the `DMLabel`
12271d04cbbeSVaclav Hapla 
1228d5b43468SJose E. Roman   Output Parameter:
1229*20f4b53cSBarry Smith . is    - the value `IS`
12301d04cbbeSVaclav Hapla 
12311d04cbbeSVaclav Hapla   Level: intermediate
12321d04cbbeSVaclav Hapla 
12331d04cbbeSVaclav Hapla   Notes:
1234*20f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
1235*20f4b53cSBarry Smith   This is similar to `DMLabelGetValueIS()` but counts only nonempty strata.
12361d04cbbeSVaclav Hapla 
1237*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
12381d04cbbeSVaclav Hapla @*/
1239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1240d71ae5a4SJacob Faibussowitsch {
12411d04cbbeSVaclav Hapla   PetscInt  i, j;
12421d04cbbeSVaclav Hapla   PetscInt *valuesArr;
12431d04cbbeSVaclav Hapla 
12441d04cbbeSVaclav Hapla   PetscFunctionBegin;
12451d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12461d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
12479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
12481d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
12491d04cbbeSVaclav Hapla     PetscInt n;
12501d04cbbeSVaclav Hapla 
12519566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
12521d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
12531d04cbbeSVaclav Hapla   }
12541d04cbbeSVaclav Hapla   if (j == label->numStrata) {
12559566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12561d04cbbeSVaclav Hapla   } else {
12579566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
12581d04cbbeSVaclav Hapla   }
12599566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
12603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12611d04cbbeSVaclav Hapla }
12621d04cbbeSVaclav Hapla 
12631d04cbbeSVaclav Hapla /*@
1264*20f4b53cSBarry Smith   DMLabelGetValueIndex - Get the index of a given value in the list of values for the `DMlabel`, or -1 if it is not present
1265d123abd9SMatthew G. Knepley 
1266*20f4b53cSBarry Smith   Not Collective
1267d123abd9SMatthew G. Knepley 
1268d123abd9SMatthew G. Knepley   Input Parameters:
1269*20f4b53cSBarry Smith + label - the `DMLabel`
127097bb3fdcSJose E. Roman - value - the value
1271d123abd9SMatthew G. Knepley 
127201d2d390SJose E. Roman   Output Parameter:
1273d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1274d123abd9SMatthew G. Knepley 
1275d123abd9SMatthew G. Knepley   Level: intermediate
1276d123abd9SMatthew G. Knepley 
1277*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1278d123abd9SMatthew G. Knepley @*/
1279d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1280d71ae5a4SJacob Faibussowitsch {
1281d123abd9SMatthew G. Knepley   PetscInt v;
1282d123abd9SMatthew G. Knepley 
1283d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1284d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1285dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 3);
1286d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
12879371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
12889371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1289d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1290d123abd9SMatthew G. Knepley   else *index = v;
12913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1292d123abd9SMatthew G. Knepley }
1293d123abd9SMatthew G. Knepley 
1294d123abd9SMatthew G. Knepley /*@
129584f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
129684f0b6dfSMatthew G. Knepley 
1297*20f4b53cSBarry Smith   Not Collective
12985b5e7992SMatthew G. Knepley 
129984f0b6dfSMatthew G. Knepley   Input Parameters:
1300*20f4b53cSBarry Smith + label - the `DMLabel`
130184f0b6dfSMatthew G. Knepley - value - the stratum value
130284f0b6dfSMatthew G. Knepley 
130301d2d390SJose E. Roman   Output Parameter:
130484f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
130584f0b6dfSMatthew G. Knepley 
130684f0b6dfSMatthew G. Knepley   Level: intermediate
130784f0b6dfSMatthew G. Knepley 
1308*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
130984f0b6dfSMatthew G. Knepley @*/
1310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1311d71ae5a4SJacob Faibussowitsch {
1312fada774cSMatthew G. Knepley   PetscInt v;
1313fada774cSMatthew G. Knepley 
1314fada774cSMatthew G. Knepley   PetscFunctionBegin;
1315d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1316dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(exists, 3);
13179566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13180c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
13193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1320fada774cSMatthew G. Knepley }
1321fada774cSMatthew G. Knepley 
132284f0b6dfSMatthew G. Knepley /*@
132384f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
132484f0b6dfSMatthew G. Knepley 
1325*20f4b53cSBarry Smith   Not Collective
13265b5e7992SMatthew G. Knepley 
132784f0b6dfSMatthew G. Knepley   Input Parameters:
1328*20f4b53cSBarry Smith + label - the `DMLabel`
132984f0b6dfSMatthew G. Knepley - value - the stratum value
133084f0b6dfSMatthew G. Knepley 
133101d2d390SJose E. Roman   Output Parameter:
133284f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
133384f0b6dfSMatthew G. Knepley 
133484f0b6dfSMatthew G. Knepley   Level: intermediate
133584f0b6dfSMatthew G. Knepley 
1336*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
133784f0b6dfSMatthew G. Knepley @*/
1338d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1339d71ae5a4SJacob Faibussowitsch {
1340c58f1c22SToby Isaac   PetscInt v;
1341c58f1c22SToby Isaac 
1342c58f1c22SToby Isaac   PetscFunctionBegin;
1343d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1344dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
13459566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13469566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
13473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1348c58f1c22SToby Isaac }
1349c58f1c22SToby Isaac 
135084f0b6dfSMatthew G. Knepley /*@
135184f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
135284f0b6dfSMatthew G. Knepley 
1353*20f4b53cSBarry Smith   Not Collective
13545b5e7992SMatthew G. Knepley 
135584f0b6dfSMatthew G. Knepley   Input Parameters:
1356*20f4b53cSBarry Smith + label - the `DMLabel`
135784f0b6dfSMatthew G. Knepley - value - the stratum value
135884f0b6dfSMatthew G. Knepley 
135901d2d390SJose E. Roman   Output Parameters:
136084f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
136184f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
136284f0b6dfSMatthew G. Knepley 
136384f0b6dfSMatthew G. Knepley   Level: intermediate
136484f0b6dfSMatthew G. Knepley 
1365*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
136684f0b6dfSMatthew G. Knepley @*/
1367d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1368d71ae5a4SJacob Faibussowitsch {
13699f6c5813SMatthew G. Knepley   IS       is;
13700c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1371c58f1c22SToby Isaac 
1372c58f1c22SToby Isaac   PetscFunctionBegin;
1373d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13749371c9d4SSatish Balay   if (start) {
13759371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
13769371c9d4SSatish Balay     *start = -1;
13779371c9d4SSatish Balay   }
13789371c9d4SSatish Balay   if (end) {
13799371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
13809371c9d4SSatish Balay     *end = -1;
13819371c9d4SSatish Balay   }
13829566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13833ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
13849566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13853ba16761SJacob Faibussowitsch   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
13869f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &is);
13879f6c5813SMatthew G. Knepley   PetscCall(ISGetMinMax(is, &min, &max));
13889f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&is));
1389d6cb179aSToby Isaac   if (start) *start = min;
1390d6cb179aSToby Isaac   if (end) *end = max + 1;
13913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1392c58f1c22SToby Isaac }
1393c58f1c22SToby Isaac 
13949f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
13959f6c5813SMatthew G. Knepley {
13969f6c5813SMatthew G. Knepley   PetscFunctionBegin;
13979f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
13989f6c5813SMatthew G. Knepley   *pointIS = label->points[v];
13993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14009f6c5813SMatthew G. Knepley }
14019f6c5813SMatthew G. Knepley 
140284f0b6dfSMatthew G. Knepley /*@
1403*20f4b53cSBarry Smith   DMLabelGetStratumIS - Get an `IS` with the stratum points
140484f0b6dfSMatthew G. Knepley 
1405*20f4b53cSBarry Smith   Not Collective
14065b5e7992SMatthew G. Knepley 
140784f0b6dfSMatthew G. Knepley   Input Parameters:
1408*20f4b53cSBarry Smith + label - the `DMLabel`
140984f0b6dfSMatthew G. Knepley - value - the stratum value
141084f0b6dfSMatthew G. Knepley 
141101d2d390SJose E. Roman   Output Parameter:
141284f0b6dfSMatthew G. Knepley . points - The stratum points
141384f0b6dfSMatthew G. Knepley 
141484f0b6dfSMatthew G. Knepley   Level: intermediate
141584f0b6dfSMatthew G. Knepley 
1416593ce467SVaclav Hapla   Notes:
1417*20f4b53cSBarry Smith   The output `IS` should be destroyed when no longer needed.
1418*20f4b53cSBarry Smith   Returns `NULL` if the stratum is empty.
1419593ce467SVaclav Hapla 
1420*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
142184f0b6dfSMatthew G. Knepley @*/
1422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1423d71ae5a4SJacob Faibussowitsch {
1424c58f1c22SToby Isaac   PetscInt v;
1425c58f1c22SToby Isaac 
1426c58f1c22SToby Isaac   PetscFunctionBegin;
1427d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1428c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1429c58f1c22SToby Isaac   *points = NULL;
14309566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14313ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14329566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14339f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, points);
14343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1435c58f1c22SToby Isaac }
1436c58f1c22SToby Isaac 
143784f0b6dfSMatthew G. Knepley /*@
1438*20f4b53cSBarry Smith   DMLabelSetStratumIS - Set the stratum points using an `IS`
143984f0b6dfSMatthew G. Knepley 
1440*20f4b53cSBarry Smith   Not Collective
14415b5e7992SMatthew G. Knepley 
144284f0b6dfSMatthew G. Knepley   Input Parameters:
1443*20f4b53cSBarry Smith + label - the `DMLabel`
144484f0b6dfSMatthew G. Knepley . value - the stratum value
144584f0b6dfSMatthew G. Knepley - points - The stratum points
144684f0b6dfSMatthew G. Knepley 
144784f0b6dfSMatthew G. Knepley   Level: intermediate
144884f0b6dfSMatthew G. Knepley 
1449*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
145084f0b6dfSMatthew G. Knepley @*/
1451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1452d71ae5a4SJacob Faibussowitsch {
14530c3c4a36SLisandro Dalcin   PetscInt v;
14544de306b1SToby Isaac 
14554de306b1SToby Isaac   PetscFunctionBegin;
1456d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1457d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
14589f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
14599566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
14603ba16761SJacob Faibussowitsch   if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
14619566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
14629566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
14639566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
14649566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&(label->points[v])));
14650c3c4a36SLisandro Dalcin   label->points[v]  = is;
14660c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
14679566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
14684de306b1SToby Isaac   if (label->bt) {
14694de306b1SToby Isaac     const PetscInt *points;
14704de306b1SToby Isaac     PetscInt        p;
14714de306b1SToby Isaac 
14729566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
14734de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
14744de306b1SToby Isaac       const PetscInt point = points[p];
14754de306b1SToby Isaac 
147663a3b9bcSJacob 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);
14779566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
14784de306b1SToby Isaac     }
14794de306b1SToby Isaac   }
14803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14814de306b1SToby Isaac }
14824de306b1SToby Isaac 
148384f0b6dfSMatthew G. Knepley /*@
148484f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14854de306b1SToby Isaac 
1486*20f4b53cSBarry Smith   Not Collective
14875b5e7992SMatthew G. Knepley 
148884f0b6dfSMatthew G. Knepley   Input Parameters:
1489*20f4b53cSBarry Smith + label - the `DMLabel`
149084f0b6dfSMatthew G. Knepley - value - the stratum value
149184f0b6dfSMatthew G. Knepley 
149284f0b6dfSMatthew G. Knepley   Level: intermediate
149384f0b6dfSMatthew G. Knepley 
1494*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
149584f0b6dfSMatthew G. Knepley @*/
1496d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1497d71ae5a4SJacob Faibussowitsch {
1498c58f1c22SToby Isaac   PetscInt v;
1499c58f1c22SToby Isaac 
1500c58f1c22SToby Isaac   PetscFunctionBegin;
1501d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15029f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15039566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15043ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15054de306b1SToby Isaac   if (label->validIS[v]) {
15064de306b1SToby Isaac     if (label->bt) {
1507c58f1c22SToby Isaac       PetscInt        i;
1508ad8374ffSToby Isaac       const PetscInt *points;
1509c58f1c22SToby Isaac 
15109566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1511c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1512ad8374ffSToby Isaac         const PetscInt point = points[i];
1513c58f1c22SToby Isaac 
151463a3b9bcSJacob 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);
15159566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1516c58f1c22SToby Isaac       }
15179566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1518c58f1c22SToby Isaac     }
1519c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
15209566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
15219566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
15229566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
15239566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1524c58f1c22SToby Isaac   } else {
15259566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1526c58f1c22SToby Isaac   }
15273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1528c58f1c22SToby Isaac }
1529c58f1c22SToby Isaac 
153084f0b6dfSMatthew G. Knepley /*@
1531412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1532412e9a14SMatthew G. Knepley 
1533*20f4b53cSBarry Smith   Not Collective
1534412e9a14SMatthew G. Knepley 
1535412e9a14SMatthew G. Knepley   Input Parameters:
1536*20f4b53cSBarry Smith + label  - The `DMLabel`
1537412e9a14SMatthew G. Knepley . value  - The label value for all points
1538412e9a14SMatthew G. Knepley . pStart - The first point
1539412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1540412e9a14SMatthew G. Knepley 
1541412e9a14SMatthew G. Knepley   Level: intermediate
1542412e9a14SMatthew G. Knepley 
1543*20f4b53cSBarry Smith   Note:
1544*20f4b53cSBarry Smith   The marks points are [`pStart`, `pEnd`), and only the bounds are stored.
1545*20f4b53cSBarry Smith 
1546*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1547412e9a14SMatthew G. Knepley @*/
1548d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1549d71ae5a4SJacob Faibussowitsch {
1550412e9a14SMatthew G. Knepley   IS pIS;
1551412e9a14SMatthew G. Knepley 
1552412e9a14SMatthew G. Knepley   PetscFunctionBegin;
15539566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
15549566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
15559566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
15563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1557412e9a14SMatthew G. Knepley }
1558412e9a14SMatthew G. Knepley 
1559412e9a14SMatthew G. Knepley /*@
1560d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1561d123abd9SMatthew G. Knepley 
1562*20f4b53cSBarry Smith   Not Collective
1563d123abd9SMatthew G. Knepley 
1564d123abd9SMatthew G. Knepley   Input Parameters:
1565*20f4b53cSBarry Smith + label  - The `DMLabel`
1566d123abd9SMatthew G. Knepley . value  - The label value
1567d123abd9SMatthew G. Knepley - p      - A point with this value
1568d123abd9SMatthew G. Knepley 
1569d123abd9SMatthew G. Knepley   Output Parameter:
1570d123abd9SMatthew 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
1571d123abd9SMatthew G. Knepley 
1572d123abd9SMatthew G. Knepley   Level: intermediate
1573d123abd9SMatthew G. Knepley 
1574*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1575d123abd9SMatthew G. Knepley @*/
1576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1577d71ae5a4SJacob Faibussowitsch {
15789f6c5813SMatthew G. Knepley   IS              pointIS;
1579d123abd9SMatthew G. Knepley   const PetscInt *indices;
1580d123abd9SMatthew G. Knepley   PetscInt        v;
1581d123abd9SMatthew G. Knepley 
1582d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1583d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1584dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 4);
1585d123abd9SMatthew G. Knepley   *index = -1;
15869566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
15873ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15889566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
15899f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &pointIS);
15909f6c5813SMatthew G. Knepley   PetscCall(ISGetIndices(pointIS, &indices));
15919566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
15929f6c5813SMatthew G. Knepley   PetscCall(ISRestoreIndices(pointIS, &indices));
15939f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&pointIS));
15943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1595d123abd9SMatthew G. Knepley }
1596d123abd9SMatthew G. Knepley 
1597d123abd9SMatthew G. Knepley /*@
1598*20f4b53cSBarry Smith   DMLabelFilter - Remove all points outside of [`start`, `end`)
159984f0b6dfSMatthew G. Knepley 
1600*20f4b53cSBarry Smith   Not Collective
16015b5e7992SMatthew G. Knepley 
160284f0b6dfSMatthew G. Knepley   Input Parameters:
1603*20f4b53cSBarry Smith + label - the `DMLabel`
160422cd2cdaSVaclav Hapla . start - the first point kept
160522cd2cdaSVaclav Hapla - end - one more than the last point kept
160684f0b6dfSMatthew G. Knepley 
160784f0b6dfSMatthew G. Knepley   Level: intermediate
160884f0b6dfSMatthew G. Knepley 
1609*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
161084f0b6dfSMatthew G. Knepley @*/
1611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1612d71ae5a4SJacob Faibussowitsch {
1613c58f1c22SToby Isaac   PetscInt v;
1614c58f1c22SToby Isaac 
1615c58f1c22SToby Isaac   PetscFunctionBegin;
1616d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16179f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16189566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
16199566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16209f6c5813SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
16219f6c5813SMatthew G. Knepley     PetscCall(ISGeneralFilter(label->points[v], start, end));
16229f6c5813SMatthew G. Knepley     PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
16239f6c5813SMatthew G. Knepley   }
16249566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
16253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1626c58f1c22SToby Isaac }
1627c58f1c22SToby Isaac 
162884f0b6dfSMatthew G. Knepley /*@
162984f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
163084f0b6dfSMatthew G. Knepley 
1631*20f4b53cSBarry Smith   Not Collective
16325b5e7992SMatthew G. Knepley 
163384f0b6dfSMatthew G. Knepley   Input Parameters:
1634*20f4b53cSBarry Smith + label - the `DMLabel`
163584f0b6dfSMatthew G. Knepley - permutation - the point permutation
163684f0b6dfSMatthew G. Knepley 
163784f0b6dfSMatthew G. Knepley   Output Parameter:
163884f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
163984f0b6dfSMatthew G. Knepley 
164084f0b6dfSMatthew G. Knepley   Level: intermediate
164184f0b6dfSMatthew G. Knepley 
1642*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
164384f0b6dfSMatthew G. Knepley @*/
1644d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1645d71ae5a4SJacob Faibussowitsch {
1646c58f1c22SToby Isaac   const PetscInt *perm;
1647c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1648c58f1c22SToby Isaac 
1649c58f1c22SToby Isaac   PetscFunctionBegin;
1650d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1651d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
16529f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16539566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16549566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
16559566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
16569566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
16579566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1658c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1659c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1660ad8374ffSToby Isaac     const PetscInt *points;
1661ad8374ffSToby Isaac     PetscInt       *pointsNew;
1662c58f1c22SToby Isaac 
16639566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
16649f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(size, &pointsNew));
1665c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1666ad8374ffSToby Isaac       const PetscInt point = points[q];
1667c58f1c22SToby Isaac 
166863a3b9bcSJacob 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);
1669ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1670c58f1c22SToby Isaac     }
16719566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
16729566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
16739566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1674fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
16759566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
16769566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1677fa8e8ae5SToby Isaac     } else {
16789566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1679fa8e8ae5SToby Isaac     }
16809566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1681c58f1c22SToby Isaac   }
16829566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1683c58f1c22SToby Isaac   if (label->bt) {
16849566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
16859566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1686c58f1c22SToby Isaac   }
16873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1688c58f1c22SToby Isaac }
1689c58f1c22SToby Isaac 
1690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1691d71ae5a4SJacob Faibussowitsch {
169226c55118SMichael Lange   MPI_Comm     comm;
1693eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
169426c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
169526c55118SMichael Lange   PetscSection rootSection;
169626c55118SMichael Lange   PetscSF      labelSF;
169726c55118SMichael Lange 
169826c55118SMichael Lange   PetscFunctionBegin;
16999566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
17009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
170126c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
170226c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
17039566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
17049566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
17059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
170626c55118SMichael Lange   if (label) {
170726c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1708ad8374ffSToby Isaac       const PetscInt *points;
1709ad8374ffSToby Isaac 
17109566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
171148a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
17129566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
171326c55118SMichael Lange     }
171426c55118SMichael Lange   }
17159566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
171626c55118SMichael Lange   /* Create a point-wise array of stratum values */
17179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
17189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
17199566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
172026c55118SMichael Lange   if (label) {
172126c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1722ad8374ffSToby Isaac       const PetscInt *points;
1723ad8374ffSToby Isaac 
17249566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
172526c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1726ad8374ffSToby Isaac         const PetscInt p = points[l];
17279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
172826c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
172926c55118SMichael Lange       }
17309566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
173126c55118SMichael Lange     }
173226c55118SMichael Lange   }
173326c55118SMichael Lange   /* Build SF that maps label points to remote processes */
17349566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
17359566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
17369566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
17379566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
173826c55118SMichael Lange   /* Send the strata for each point over the derived SF */
17399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
17409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
17419566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
17429566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
174326c55118SMichael Lange   /* Clean up */
17449566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
17459566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
17469566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
17479566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
17483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
174926c55118SMichael Lange }
175026c55118SMichael Lange 
175184f0b6dfSMatthew G. Knepley /*@
1752*20f4b53cSBarry Smith   DMLabelDistribute - Create a new label pushed forward over the `PetscSF`
175384f0b6dfSMatthew G. Knepley 
1754*20f4b53cSBarry Smith   Collective
17555b5e7992SMatthew G. Knepley 
175684f0b6dfSMatthew G. Knepley   Input Parameters:
1757*20f4b53cSBarry Smith + label - the `DMLabel`
175884f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
175984f0b6dfSMatthew G. Knepley 
176084f0b6dfSMatthew G. Knepley   Output Parameter:
176184f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
176284f0b6dfSMatthew G. Knepley 
176384f0b6dfSMatthew G. Knepley   Level: intermediate
176484f0b6dfSMatthew G. Knepley 
1765*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
176684f0b6dfSMatthew G. Knepley @*/
1767d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1768d71ae5a4SJacob Faibussowitsch {
1769c58f1c22SToby Isaac   MPI_Comm     comm;
177026c55118SMichael Lange   PetscSection leafSection;
177126c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
177226c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1773ad8374ffSToby Isaac   PetscInt   **points;
1774d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1775c58f1c22SToby Isaac   char        *name;
1776c58f1c22SToby Isaac   PetscInt     nameSize;
1777e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1778c58f1c22SToby Isaac   size_t       len = 0;
177926c55118SMichael Lange   PetscMPIInt  rank;
1780c58f1c22SToby Isaac 
1781c58f1c22SToby Isaac   PetscFunctionBegin;
1782d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1783f018e600SMatthew G. Knepley   if (label) {
1784f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17859f6c5813SMatthew G. Knepley     PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
17869566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1787f018e600SMatthew G. Knepley   }
17889566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1790c58f1c22SToby Isaac   /* Bcast name */
1791dd400576SPatrick Sanan   if (rank == 0) {
17929566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
17939566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1794d67d17b1SMatthew G. Knepley   }
1795c58f1c22SToby Isaac   nameSize = len;
17969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17979566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
17989566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
17999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
18009566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
18019566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
180277d236dfSMichael Lange   /* Bcast defaultValue */
1803dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
18049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
180526c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
18069566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
18075cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
18089566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
18099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
18109566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
18119566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
18129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1813ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
18149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
18155cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
18165cbdf6fcSMichael Lange   offset = 0;
18179566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
18189566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
181948a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
18205cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1821231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
18229371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
18239371c9d4SSatish Balay         leafStrata[p] = s;
18249371c9d4SSatish Balay         break;
18259371c9d4SSatish Balay       }
18265cbdf6fcSMichael Lange     }
18275cbdf6fcSMichael Lange   }
1828c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
18299566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
18309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1831c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
18329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
18339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1834ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1835c58f1c22SToby Isaac   }
18369566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
18379f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
18389f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1839c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
18409566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
18419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1842c58f1c22SToby Isaac   }
1843c58f1c22SToby Isaac   /* Insert points into new strata */
18449566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
18459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1846c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
18479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
18489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1849c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1850c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1851ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1852c58f1c22SToby Isaac     }
1853c58f1c22SToby Isaac   }
1854ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
18559566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &(points[s][0]), PETSC_OWN_POINTER, &((*labelNew)->points[s])));
18569566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1857ad8374ffSToby Isaac   }
18589566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
18599566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
18609566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
18619566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
18629566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
18633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1864c58f1c22SToby Isaac }
1865c58f1c22SToby Isaac 
18667937d9ceSMichael Lange /*@
18677937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
18687937d9ceSMichael Lange 
1869*20f4b53cSBarry Smith   Collective
18705b5e7992SMatthew G. Knepley 
18717937d9ceSMichael Lange   Input Parameters:
1872*20f4b53cSBarry Smith + label - the `DMLabel`
1873*20f4b53cSBarry Smith - sf - the `PetscSF` communication map
18747937d9ceSMichael Lange 
187584f0b6dfSMatthew G. Knepley   Output Parameters:
1876*20f4b53cSBarry Smith . labelNew - the new `DMLabel` with localised leaf values
18777937d9ceSMichael Lange 
18787937d9ceSMichael Lange   Level: developer
18797937d9ceSMichael Lange 
1880*20f4b53cSBarry Smith   Note:
1881*20f4b53cSBarry Smith   This is the inverse operation to `DMLabelDistribute()`.
18827937d9ceSMichael Lange 
1883*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
18847937d9ceSMichael Lange @*/
1885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
1886d71ae5a4SJacob Faibussowitsch {
18877937d9ceSMichael Lange   MPI_Comm        comm;
18887937d9ceSMichael Lange   PetscSection    rootSection;
18897937d9ceSMichael Lange   PetscSF         sfLabel;
18907937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
18917937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18927937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18937937d9ceSMichael Lange   PetscInt       *rootStrata;
1894d67d17b1SMatthew G. Knepley   const char     *lname;
18957937d9ceSMichael Lange   char           *name;
18967937d9ceSMichael Lange   PetscInt        nameSize;
18977937d9ceSMichael Lange   size_t          len = 0;
18989852e123SBarry Smith   PetscMPIInt     rank, size;
18997937d9ceSMichael Lange 
19007937d9ceSMichael Lange   PetscFunctionBegin;
1901d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1902d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
19039f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
19049566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
19059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
19069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
19077937d9ceSMichael Lange   /* Bcast name */
1908dd400576SPatrick Sanan   if (rank == 0) {
19099566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
19109566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1911d67d17b1SMatthew G. Knepley   }
19127937d9ceSMichael Lange   nameSize = len;
19139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
19149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
19159566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
19169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
19179566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
19189566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
19197937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
19207937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
19217937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
19229566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
19239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1924dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
19257937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
19268212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
19278212dd46SStefano Zampini 
19288212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
19298212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
19307937d9ceSMichael Lange   }
19319566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
19329566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
19337937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
19349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
19359566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
19369566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
19379566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
19389566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
19397937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
19409566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
19417937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
19427937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
19437937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
19449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
19459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
19469566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
19477937d9ceSMichael Lange     }
19487937d9ceSMichael Lange     idx += rootDegree[p];
19497937d9ceSMichael Lange   }
19509566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
19519566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
19529566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
19539566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
19543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19557937d9ceSMichael Lange }
19567937d9ceSMichael Lange 
1957d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1958d71ae5a4SJacob Faibussowitsch {
1959d42890abSMatthew G. Knepley   const PetscInt *degree;
1960d42890abSMatthew G. Knepley   const PetscInt *points;
1961d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1962d42890abSMatthew G. Knepley 
1963d42890abSMatthew G. Knepley   PetscFunctionBegin;
1964d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1965d42890abSMatthew G. Knepley   /* Add in leaves */
1966d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1967d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1968d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1969d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1970d42890abSMatthew G. Knepley   }
1971d42890abSMatthew G. Knepley   /* Add in shared roots */
1972d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1973d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1974d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1975d42890abSMatthew G. Knepley     if (degree[r]) {
1976d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1977d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1978d42890abSMatthew G. Knepley     }
1979d42890abSMatthew G. Knepley   }
19803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1981d42890abSMatthew G. Knepley }
1982d42890abSMatthew G. Knepley 
1983d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1984d71ae5a4SJacob Faibussowitsch {
1985d42890abSMatthew G. Knepley   const PetscInt *degree;
1986d42890abSMatthew G. Knepley   const PetscInt *points;
1987d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1988d42890abSMatthew G. Knepley 
1989d42890abSMatthew G. Knepley   PetscFunctionBegin;
1990d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1991d42890abSMatthew G. Knepley   /* Read out leaves */
1992d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1993d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1994d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1995d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1996d42890abSMatthew G. Knepley 
1997d42890abSMatthew G. Knepley     if (cval != defVal) {
1998d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1999d42890abSMatthew G. Knepley       if (val == defVal) {
2000d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
200148a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
2002d42890abSMatthew G. Knepley       }
2003d42890abSMatthew G. Knepley     }
2004d42890abSMatthew G. Knepley   }
2005d42890abSMatthew G. Knepley   /* Read out shared roots */
2006d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2007d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2008d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2009d42890abSMatthew G. Knepley     if (degree[r]) {
2010d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
2011d42890abSMatthew G. Knepley 
2012d42890abSMatthew G. Knepley       if (cval != defVal) {
2013d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
2014d42890abSMatthew G. Knepley         if (val == defVal) {
2015d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
201648a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2017d42890abSMatthew G. Knepley         }
2018d42890abSMatthew G. Knepley       }
2019d42890abSMatthew G. Knepley     }
2020d42890abSMatthew G. Knepley   }
20213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2022d42890abSMatthew G. Knepley }
2023d42890abSMatthew G. Knepley 
2024d42890abSMatthew G. Knepley /*@
2025d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
2026d42890abSMatthew G. Knepley 
2027*20f4b53cSBarry Smith   Collective
2028d42890abSMatthew G. Knepley 
2029d42890abSMatthew G. Knepley   Input Parameters:
2030*20f4b53cSBarry Smith + label - The `DMLabel` to propagate across processes
2031*20f4b53cSBarry Smith - sf    - The `PetscSF` describing parallel layout of the label points
2032d42890abSMatthew G. Knepley 
2033d42890abSMatthew G. Knepley   Level: intermediate
2034d42890abSMatthew G. Knepley 
2035*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2036d42890abSMatthew G. Knepley @*/
2037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2038d71ae5a4SJacob Faibussowitsch {
2039d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
2040d42890abSMatthew G. Knepley   PetscMPIInt size;
2041d42890abSMatthew G. Knepley 
2042d42890abSMatthew G. Knepley   PetscFunctionBegin;
20439f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2044d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2045d42890abSMatthew G. Knepley   if (size > 1) {
2046d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
2047d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2048d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2049d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2050d42890abSMatthew G. Knepley   }
20513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2052d42890abSMatthew G. Knepley }
2053d42890abSMatthew G. Knepley 
2054d42890abSMatthew G. Knepley /*@
2055d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
2056d42890abSMatthew G. Knepley 
2057*20f4b53cSBarry Smith   Collective
2058d42890abSMatthew G. Knepley 
2059d42890abSMatthew G. Knepley   Input Parameters:
2060*20f4b53cSBarry Smith + label - The `DMLabel` to propagate across processes
2061*20f4b53cSBarry Smith - sf    - The `PetscSF` describing parallel layout of the label points
2062d42890abSMatthew G. Knepley 
2063d42890abSMatthew G. Knepley   Level: intermediate
2064d42890abSMatthew G. Knepley 
2065*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2066d42890abSMatthew G. Knepley @*/
2067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2068d71ae5a4SJacob Faibussowitsch {
2069d42890abSMatthew G. Knepley   PetscFunctionBegin;
20709f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2071d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
2072d42890abSMatthew G. Knepley   label->propArray = NULL;
20733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2074d42890abSMatthew G. Knepley }
2075d42890abSMatthew G. Knepley 
2076d42890abSMatthew G. Knepley /*@C
2077d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2078d42890abSMatthew G. Knepley 
2079*20f4b53cSBarry Smith   Collective
2080d42890abSMatthew G. Knepley 
2081d42890abSMatthew G. Knepley   Input Parameters:
2082*20f4b53cSBarry Smith + label     - The `DMLabel` to propagate across processes
2083*20f4b53cSBarry Smith . sf        - The `PetscSF` describing parallel layout of the label points
2084*20f4b53cSBarry Smith . markPoint - An optional callback that is called when a point is marked, or `NULL`
2085*20f4b53cSBarry Smith - ctx       - An optional user context for the callback, or `NULL`
2086d42890abSMatthew G. Knepley 
2087*20f4b53cSBarry Smith   Calling sequence of `markPoint`:
2088*20f4b53cSBarry Smith $ PetscErrorCode markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
2089*20f4b53cSBarry Smith + label - The `DMLabel`
2090d42890abSMatthew G. Knepley . p     - The point being marked
2091*20f4b53cSBarry Smith . val   - The label value for `p`
2092d42890abSMatthew G. Knepley - ctx   - An optional user context
2093d42890abSMatthew G. Knepley 
2094d42890abSMatthew G. Knepley   Level: intermediate
2095d42890abSMatthew G. Knepley 
2096*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2097d42890abSMatthew G. Knepley @*/
2098d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2099d71ae5a4SJacob Faibussowitsch {
2100c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2101d42890abSMatthew G. Knepley   PetscMPIInt size;
2102d42890abSMatthew G. Knepley 
2103d42890abSMatthew G. Knepley   PetscFunctionBegin;
21049f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2105d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2106c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2107c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2108d42890abSMatthew G. Knepley     /* Communicate marked edges
2109d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2110d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2111d42890abSMatthew G. Knepley 
2112d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2113d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2114d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2115d42890abSMatthew G. Knepley 
2116d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2117d42890abSMatthew 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
2118d42890abSMatthew G. Knepley        edge to the queue.
2119d42890abSMatthew G. Knepley     */
2120d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2121d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2122d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2123d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2124d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2125d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2126d42890abSMatthew G. Knepley   }
21273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2128d42890abSMatthew G. Knepley }
2129d42890abSMatthew G. Knepley 
213084f0b6dfSMatthew G. Knepley /*@
2131*20f4b53cSBarry Smith   DMLabelConvertToSection - Make a `PetscSection`/`IS` pair that encodes the label
213284f0b6dfSMatthew G. Knepley 
2133*20f4b53cSBarry Smith   Not Collective
21345b5e7992SMatthew G. Knepley 
213584f0b6dfSMatthew G. Knepley   Input Parameter:
2136*20f4b53cSBarry Smith . label - the `DMLabel`
213784f0b6dfSMatthew G. Knepley 
213884f0b6dfSMatthew G. Knepley   Output Parameters:
213984f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
2140*20f4b53cSBarry Smith - is - An `IS` containing all the label points
214184f0b6dfSMatthew G. Knepley 
214284f0b6dfSMatthew G. Knepley   Level: developer
214384f0b6dfSMatthew G. Knepley 
2144*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelDistribute()`
214584f0b6dfSMatthew G. Knepley @*/
2146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2147d71ae5a4SJacob Faibussowitsch {
2148c58f1c22SToby Isaac   IS              vIS;
2149c58f1c22SToby Isaac   const PetscInt *values;
2150c58f1c22SToby Isaac   PetscInt       *points;
2151c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2152c58f1c22SToby Isaac 
2153c58f1c22SToby Isaac   PetscFunctionBegin;
2154d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
21559566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
21569566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
21579566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
21589371c9d4SSatish Balay   if (nV) {
21599371c9d4SSatish Balay     vS = values[0];
21609371c9d4SSatish Balay     vE = values[0] + 1;
21619371c9d4SSatish Balay   }
2162c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2163c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2164c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2165c58f1c22SToby Isaac   }
21669566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
21679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2168c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2169c58f1c22SToby Isaac     PetscInt n;
2170c58f1c22SToby Isaac 
21719566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
21729566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2173c58f1c22SToby Isaac   }
21749566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
21759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
21769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2177c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2178c58f1c22SToby Isaac     IS              is;
2179c58f1c22SToby Isaac     const PetscInt *spoints;
2180c58f1c22SToby Isaac     PetscInt        dof, off, p;
2181c58f1c22SToby Isaac 
21829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
21839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
21849566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
21859566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2186c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
21879566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
21889566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2189c58f1c22SToby Isaac   }
21909566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
21919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
21929566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
21933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2194c58f1c22SToby Isaac }
2195c58f1c22SToby Isaac 
21969f6c5813SMatthew G. Knepley /*@C
21979f6c5813SMatthew G. Knepley   DMLabelRegister - Adds a new label component implementation
21989f6c5813SMatthew G. Knepley 
21999f6c5813SMatthew G. Knepley   Not Collective
22009f6c5813SMatthew G. Knepley 
22019f6c5813SMatthew G. Knepley   Input Parameters:
22029f6c5813SMatthew G. Knepley + name        - The name of a new user-defined creation routine
22039f6c5813SMatthew G. Knepley - create_func - The creation routine itself
22049f6c5813SMatthew G. Knepley 
22059f6c5813SMatthew G. Knepley   Notes:
22069f6c5813SMatthew G. Knepley   `DMLabelRegister()` may be called multiple times to add several user-defined labels
22079f6c5813SMatthew G. Knepley 
22089f6c5813SMatthew G. Knepley   Sample usage:
22099f6c5813SMatthew G. Knepley .vb
22109f6c5813SMatthew G. Knepley   DMLabelRegister("my_label", MyLabelCreate);
22119f6c5813SMatthew G. Knepley .ve
22129f6c5813SMatthew G. Knepley 
22139f6c5813SMatthew G. Knepley   Then, your label type can be chosen with the procedural interface via
22149f6c5813SMatthew G. Knepley .vb
22159f6c5813SMatthew G. Knepley   DMLabelCreate(MPI_Comm, DMLabel *);
22169f6c5813SMatthew G. Knepley   DMLabelSetType(DMLabel, "my_label");
22179f6c5813SMatthew G. Knepley .ve
22189f6c5813SMatthew G. Knepley   or at runtime via the option
22199f6c5813SMatthew G. Knepley .vb
22209f6c5813SMatthew G. Knepley   -dm_label_type my_label
22219f6c5813SMatthew G. Knepley .ve
22229f6c5813SMatthew G. Knepley 
22239f6c5813SMatthew G. Knepley   Level: advanced
22249f6c5813SMatthew G. Knepley 
2225*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabel`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
22269f6c5813SMatthew G. Knepley @*/
22279f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
22289f6c5813SMatthew G. Knepley {
22299f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22309f6c5813SMatthew G. Knepley   PetscCall(DMInitializePackage());
22319f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
22323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22339f6c5813SMatthew G. Knepley }
22349f6c5813SMatthew G. Knepley 
22359f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
22369f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
22379f6c5813SMatthew G. Knepley 
22389f6c5813SMatthew G. Knepley /*@C
22399f6c5813SMatthew G. Knepley   DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
22409f6c5813SMatthew G. Knepley 
22419f6c5813SMatthew G. Knepley   Not Collective
22429f6c5813SMatthew G. Knepley 
22439f6c5813SMatthew G. Knepley   Level: advanced
22449f6c5813SMatthew G. Knepley 
2245*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMRegisterAll()`, `DMLabelRegisterDestroy()`
22469f6c5813SMatthew G. Knepley @*/
22479f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterAll(void)
22489f6c5813SMatthew G. Knepley {
22499f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22503ba16761SJacob Faibussowitsch   if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
22519f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_TRUE;
22529f6c5813SMatthew G. Knepley 
22539f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
22549f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
22553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22569f6c5813SMatthew G. Knepley }
22579f6c5813SMatthew G. Knepley 
22589f6c5813SMatthew G. Knepley /*@C
22599f6c5813SMatthew G. Knepley   DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
22609f6c5813SMatthew G. Knepley 
22619f6c5813SMatthew G. Knepley   Level: developer
22629f6c5813SMatthew G. Knepley 
2263*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscInitialize()`
22649f6c5813SMatthew G. Knepley @*/
22659f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterDestroy(void)
22669f6c5813SMatthew G. Knepley {
22679f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22689f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListDestroy(&DMLabelList));
22699f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_FALSE;
22703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22719f6c5813SMatthew G. Knepley }
22729f6c5813SMatthew G. Knepley 
22739f6c5813SMatthew G. Knepley /*@C
22749f6c5813SMatthew G. Knepley   DMLabelSetType - Sets the particular implementation for a label.
22759f6c5813SMatthew G. Knepley 
2276*20f4b53cSBarry Smith   Collective
22779f6c5813SMatthew G. Knepley 
22789f6c5813SMatthew G. Knepley   Input Parameters:
22799f6c5813SMatthew G. Knepley + label  - The label
22809f6c5813SMatthew G. Knepley - method - The name of the label type
22819f6c5813SMatthew G. Knepley 
22829f6c5813SMatthew G. Knepley   Options Database Key:
2283*20f4b53cSBarry Smith . -dm_label_type <type> - Sets the label type; use -help for a list of available types or see `DMLabelType`
22849f6c5813SMatthew G. Knepley 
22859f6c5813SMatthew G. Knepley   Level: intermediate
22869f6c5813SMatthew G. Knepley 
2287*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelGetType()`, `DMLabelCreate()`
22889f6c5813SMatthew G. Knepley @*/
22899f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
22909f6c5813SMatthew G. Knepley {
22919f6c5813SMatthew G. Knepley   PetscErrorCode (*r)(DMLabel);
22929f6c5813SMatthew G. Knepley   PetscBool match;
22939f6c5813SMatthew G. Knepley 
22949f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22959f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
22969f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
22973ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
22989f6c5813SMatthew G. Knepley 
22999f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
23009f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
23019f6c5813SMatthew G. Knepley   PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
23029f6c5813SMatthew G. Knepley 
23039f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, destroy);
23049f6c5813SMatthew G. Knepley   PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
23059f6c5813SMatthew G. Knepley   PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
23069f6c5813SMatthew G. Knepley   PetscCall((*r)(label));
23073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23089f6c5813SMatthew G. Knepley }
23099f6c5813SMatthew G. Knepley 
23109f6c5813SMatthew G. Knepley /*@C
23119f6c5813SMatthew G. Knepley   DMLabelGetType - Gets the type name (as a string) from the label.
23129f6c5813SMatthew G. Knepley 
23139f6c5813SMatthew G. Knepley   Not Collective
23149f6c5813SMatthew G. Knepley 
23159f6c5813SMatthew G. Knepley   Input Parameter:
2316*20f4b53cSBarry Smith . label  - The `DMLabel`
23179f6c5813SMatthew G. Knepley 
23189f6c5813SMatthew G. Knepley   Output Parameter:
2319*20f4b53cSBarry Smith . type - The `DMLabel` type name
23209f6c5813SMatthew G. Knepley 
23219f6c5813SMatthew G. Knepley   Level: intermediate
23229f6c5813SMatthew G. Knepley 
2323*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `DMLabelSetType()`, `DMLabelCreate()`
23249f6c5813SMatthew G. Knepley @*/
23259f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
23269f6c5813SMatthew G. Knepley {
23279f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23289f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
23299f6c5813SMatthew G. Knepley   PetscValidPointer(type, 2);
23309f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
23319f6c5813SMatthew G. Knepley   *type = ((PetscObject)label)->type_name;
23323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23339f6c5813SMatthew G. Knepley }
23349f6c5813SMatthew G. Knepley 
23359f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
23369f6c5813SMatthew G. Knepley {
23379f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23389f6c5813SMatthew G. Knepley   label->ops->view         = DMLabelView_Concrete;
23399f6c5813SMatthew G. Knepley   label->ops->setup        = NULL;
23409f6c5813SMatthew G. Knepley   label->ops->duplicate    = DMLabelDuplicate_Concrete;
23419f6c5813SMatthew G. Knepley   label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
23423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23439f6c5813SMatthew G. Knepley }
23449f6c5813SMatthew G. Knepley 
23459f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
23469f6c5813SMatthew G. Knepley {
23479f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23489f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
23499f6c5813SMatthew G. Knepley   PetscCall(DMLabelInitialize_Concrete(label));
23503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23519f6c5813SMatthew G. Knepley }
23529f6c5813SMatthew G. Knepley 
235384f0b6dfSMatthew G. Knepley /*@
2354c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2355*20f4b53cSBarry Smith   the local section and an `PetscSF` describing the section point overlap.
2356c58f1c22SToby Isaac 
2357*20f4b53cSBarry Smith   Collective
23585b5e7992SMatthew G. Knepley 
2359c58f1c22SToby Isaac   Input Parameters:
2360*20f4b53cSBarry Smith + s - The `PetscSection` for the local field layout
2361*20f4b53cSBarry Smith . sf - The `PetscSF` describing parallel layout of the section points
2362*20f4b53cSBarry Smith . includeConstraints - By default this is `PETSC_FALSE`, meaning that the global field vector will not possess constrained dofs
2363c58f1c22SToby Isaac . label - The label specifying the points
2364c58f1c22SToby Isaac - labelValue - The label stratum specifying the points
2365c58f1c22SToby Isaac 
2366c58f1c22SToby Isaac   Output Parameter:
2367*20f4b53cSBarry Smith . gsection - The `PetscSection` for the global field layout
2368c58f1c22SToby Isaac 
2369c58f1c22SToby Isaac   Level: developer
2370c58f1c22SToby Isaac 
2371*20f4b53cSBarry Smith   Note:
2372*20f4b53cSBarry Smith   This gives negative sizes and offsets to points not owned by this process
2373*20f4b53cSBarry Smith 
2374*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionCreate()`
2375c58f1c22SToby Isaac @*/
2376d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2377d71ae5a4SJacob Faibussowitsch {
2378c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2379c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2380c58f1c22SToby Isaac 
2381c58f1c22SToby Isaac   PetscFunctionBegin;
2382d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2383d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2384d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
23859566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
23869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
23879566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
23889566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2389c58f1c22SToby Isaac   if (nroots >= 0) {
239063a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
23919566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2392c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
23939566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2394c58f1c22SToby Isaac     } else {
2395c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2396c58f1c22SToby Isaac     }
2397c58f1c22SToby Isaac   }
2398c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2399c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2400c58f1c22SToby Isaac     PetscInt value;
2401c58f1c22SToby Isaac 
24029566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2403c58f1c22SToby Isaac     if (value != labelValue) continue;
24049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
24059566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
24069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
24079566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2408c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2409c58f1c22SToby Isaac   }
24109566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2411c58f1c22SToby Isaac   if (nroots >= 0) {
24129566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
24139566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2414c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
24159371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
24169371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
24179371c9d4SSatish Balay       }
2418c58f1c22SToby Isaac     }
2419c58f1c22SToby Isaac   }
242035cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
2421c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2422c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2423c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2424c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2425c58f1c22SToby Isaac   }
24269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2427c58f1c22SToby Isaac   globalOff -= off;
2428c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2429c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2430c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2431c58f1c22SToby Isaac   }
2432c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2433c58f1c22SToby Isaac   if (nroots >= 0) {
24349566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
24359566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2436c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
24379371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
24389371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
24399371c9d4SSatish Balay       }
2440c58f1c22SToby Isaac     }
2441c58f1c22SToby Isaac   }
24429566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
24439566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
24443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2445c58f1c22SToby Isaac }
2446c58f1c22SToby Isaac 
24479371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
24485fdea053SToby Isaac   DMLabel              label;
24495fdea053SToby Isaac   PetscCopyMode       *modes;
24505fdea053SToby Isaac   PetscInt            *sizes;
24515fdea053SToby Isaac   const PetscInt    ***perms;
24525fdea053SToby Isaac   const PetscScalar ***rots;
24535fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
24545fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
24555fdea053SToby Isaac } PetscSectionSym_Label;
24565fdea053SToby Isaac 
2457d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2458d71ae5a4SJacob Faibussowitsch {
24595fdea053SToby Isaac   PetscInt               i, j;
24605fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
24615fdea053SToby Isaac 
24625fdea053SToby Isaac   PetscFunctionBegin;
24635fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
24645fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
24655fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
24669566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
24679566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
24685fdea053SToby Isaac       }
24695fdea053SToby Isaac       if (sl->perms[i]) {
24705fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
24715fdea053SToby Isaac 
24729566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
24735fdea053SToby Isaac       }
24745fdea053SToby Isaac       if (sl->rots[i]) {
24755fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
24765fdea053SToby Isaac 
24779566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
24785fdea053SToby Isaac       }
24795fdea053SToby Isaac     }
24805fdea053SToby Isaac   }
24819566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
24829566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
24835fdea053SToby Isaac   sl->numStrata = 0;
24843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24855fdea053SToby Isaac }
24865fdea053SToby Isaac 
2487d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2488d71ae5a4SJacob Faibussowitsch {
24895fdea053SToby Isaac   PetscFunctionBegin;
24909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
24919566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
24923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24935fdea053SToby Isaac }
24945fdea053SToby Isaac 
2495d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2496d71ae5a4SJacob Faibussowitsch {
24975fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
24985fdea053SToby Isaac   PetscBool              isAscii;
24995fdea053SToby Isaac   DMLabel                label = sl->label;
2500d67d17b1SMatthew G. Knepley   const char            *name;
25015fdea053SToby Isaac 
25025fdea053SToby Isaac   PetscFunctionBegin;
25039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
25045fdea053SToby Isaac   if (isAscii) {
25055fdea053SToby Isaac     PetscInt          i, j, k;
25065fdea053SToby Isaac     PetscViewerFormat format;
25075fdea053SToby Isaac 
25089566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
25095fdea053SToby Isaac     if (label) {
25109566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
25115fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
25129566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
25139566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
25149566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
25155fdea053SToby Isaac       } else {
25169566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
25179566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
25185fdea053SToby Isaac       }
25195fdea053SToby Isaac     } else {
25209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
25215fdea053SToby Isaac     }
25229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
25235fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
25245fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
25255fdea053SToby Isaac 
25265fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
252763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
25285fdea053SToby Isaac       } else {
252963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
25309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
253163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
25325fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
25339566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
25345fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
25355fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
253663a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
25375fdea053SToby Isaac             } else {
25385fdea053SToby Isaac               PetscInt tab;
25395fdea053SToby Isaac 
254063a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
25419566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
25429566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
25435fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
25449566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
25459566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
254663a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
25479566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
25489566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
25495fdea053SToby Isaac               }
25505fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
25519566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
25529566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
25535fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
255463a3b9bcSJacob 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])));
25555fdea053SToby Isaac #else
255663a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
25575fdea053SToby Isaac #endif
25589566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
25599566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
25605fdea053SToby Isaac               }
25619566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
25625fdea053SToby Isaac             }
25635fdea053SToby Isaac           }
25649566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
25655fdea053SToby Isaac         }
25669566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
25675fdea053SToby Isaac       }
25685fdea053SToby Isaac     }
25699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
25705fdea053SToby Isaac   }
25713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25725fdea053SToby Isaac }
25735fdea053SToby Isaac 
25745fdea053SToby Isaac /*@
25755fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
25765fdea053SToby Isaac 
2577*20f4b53cSBarry Smith   Logically
25785fdea053SToby Isaac 
25795fdea053SToby Isaac   Input parameters:
25805fdea053SToby Isaac + sym - the section symmetries
2581*20f4b53cSBarry Smith - label - the `DMLabel` describing the types of points
25825fdea053SToby Isaac 
25835fdea053SToby Isaac   Level: developer:
25845fdea053SToby Isaac 
2585*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
25865fdea053SToby Isaac @*/
2587d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2588d71ae5a4SJacob Faibussowitsch {
25895fdea053SToby Isaac   PetscSectionSym_Label *sl;
25905fdea053SToby Isaac 
25915fdea053SToby Isaac   PetscFunctionBegin;
25925fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
25935fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
25949566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
25955fdea053SToby Isaac   if (label) {
25965fdea053SToby Isaac     sl->label = label;
25979566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
25989566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
25999566063dSJacob 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));
26009566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
26019566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
26029566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
26039566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
26049566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
26055fdea053SToby Isaac   }
26063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26075fdea053SToby Isaac }
26085fdea053SToby Isaac 
26095fdea053SToby Isaac /*@C
2610b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2611b004864fSMatthew G. Knepley 
2612*20f4b53cSBarry Smith   Logically Collective
2613b004864fSMatthew G. Knepley 
2614b004864fSMatthew G. Knepley   Input Parameters:
2615b004864fSMatthew G. Knepley + sym       - the section symmetries
2616b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2617b004864fSMatthew G. Knepley 
2618b004864fSMatthew G. Knepley   Output Parameters:
2619*20f4b53cSBarry Smith + size      - the number of dofs for points in the `stratum` of the label
2620*20f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
2621*20f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a ppoint in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
2622*20f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
2623*20f4b53cSBarry 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
2624b004864fSMatthew G. Knepley 
2625b004864fSMatthew G. Knepley   Level: developer
2626b004864fSMatthew G. Knepley 
2627*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2628b004864fSMatthew G. Knepley @*/
2629d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2630d71ae5a4SJacob Faibussowitsch {
2631b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2632b004864fSMatthew G. Knepley   const char            *name;
2633b004864fSMatthew G. Knepley   PetscInt               i;
2634b004864fSMatthew G. Knepley 
2635b004864fSMatthew G. Knepley   PetscFunctionBegin;
2636b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2637b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2638b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2639b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2640b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2641b004864fSMatthew G. Knepley 
2642b004864fSMatthew G. Knepley     if (stratum == value) break;
2643b004864fSMatthew G. Knepley   }
26449566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2645b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
26469371c9d4SSatish Balay   if (size) {
26479371c9d4SSatish Balay     PetscValidIntPointer(size, 3);
26489371c9d4SSatish Balay     *size = sl->sizes[i];
26499371c9d4SSatish Balay   }
26509371c9d4SSatish Balay   if (minOrient) {
26519371c9d4SSatish Balay     PetscValidIntPointer(minOrient, 4);
26529371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
26539371c9d4SSatish Balay   }
26549371c9d4SSatish Balay   if (maxOrient) {
26559371c9d4SSatish Balay     PetscValidIntPointer(maxOrient, 5);
26569371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
26579371c9d4SSatish Balay   }
26589371c9d4SSatish Balay   if (perms) {
26599371c9d4SSatish Balay     PetscValidPointer(perms, 6);
26609371c9d4SSatish Balay     *perms = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;
26619371c9d4SSatish Balay   }
26629371c9d4SSatish Balay   if (rots) {
26639371c9d4SSatish Balay     PetscValidPointer(rots, 7);
26649371c9d4SSatish Balay     *rots = sl->rots[i] ? &sl->rots[i][sl->minMaxOrients[i][0]] : NULL;
26659371c9d4SSatish Balay   }
26663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2667b004864fSMatthew G. Knepley }
2668b004864fSMatthew G. Knepley 
2669b004864fSMatthew G. Knepley /*@C
26705fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
26715fdea053SToby Isaac 
2672*20f4b53cSBarry Smith   Logically
26735fdea053SToby Isaac 
26745fdea053SToby Isaac   InputParameters:
26755b5e7992SMatthew G. Knepley + sym       - the section symmetries
26765fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
2677*20f4b53cSBarry Smith . size      - the number of dofs for points in the `stratum` of the label
2678*20f4b53cSBarry Smith . minOrient - the smallest orientation for a point in this `stratum`
2679*20f4b53cSBarry Smith . maxOrient - one greater than the largest orientation for a point in this `stratum` (i.e., orientations are in the range [`minOrient`, `maxOrient`))
2680*20f4b53cSBarry Smith . mode      - how `sym` should copy the `perms` and `rots` arrays
2681*20f4b53cSBarry Smith . perms     - `NULL` if there are no permutations, or (`maxOrient` - `minOrient`) permutations, one for each orientation.  A `NULL` permutation is the identity
2682*20f4b53cSBarry 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
26835fdea053SToby Isaac 
26845fdea053SToby Isaac   Level: developer
26855fdea053SToby Isaac 
2686*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
26875fdea053SToby Isaac @*/
2688d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2689d71ae5a4SJacob Faibussowitsch {
26905fdea053SToby Isaac   PetscSectionSym_Label *sl;
2691d67d17b1SMatthew G. Knepley   const char            *name;
2692d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
26935fdea053SToby Isaac 
26945fdea053SToby Isaac   PetscFunctionBegin;
26955fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
26965fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2697b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
26985fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
26995fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
27005fdea053SToby Isaac 
27015fdea053SToby Isaac     if (stratum == value) break;
27025fdea053SToby Isaac   }
27039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
270463a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
27055fdea053SToby Isaac   sl->sizes[i]            = size;
27065fdea053SToby Isaac   sl->modes[i]            = mode;
27075fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
27085fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
27095fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
27105fdea053SToby Isaac     if (perms) {
27115fdea053SToby Isaac       PetscInt **ownPerms;
27125fdea053SToby Isaac 
27139566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
27145fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
27155fdea053SToby Isaac         if (perms[j]) {
27169566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2717ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
27185fdea053SToby Isaac         }
27195fdea053SToby Isaac       }
27205fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
27215fdea053SToby Isaac     }
27225fdea053SToby Isaac     if (rots) {
27235fdea053SToby Isaac       PetscScalar **ownRots;
27245fdea053SToby Isaac 
27259566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
27265fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
27275fdea053SToby Isaac         if (rots[j]) {
27289566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2729ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
27305fdea053SToby Isaac         }
27315fdea053SToby Isaac       }
27325fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
27335fdea053SToby Isaac     }
27345fdea053SToby Isaac   } else {
27355fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
27365fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
27375fdea053SToby Isaac   }
27383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27395fdea053SToby Isaac }
27405fdea053SToby Isaac 
2741d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2742d71ae5a4SJacob Faibussowitsch {
27435fdea053SToby Isaac   PetscInt               i, j, numStrata;
27445fdea053SToby Isaac   PetscSectionSym_Label *sl;
27455fdea053SToby Isaac   DMLabel                label;
27465fdea053SToby Isaac 
27475fdea053SToby Isaac   PetscFunctionBegin;
27485fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
27495fdea053SToby Isaac   numStrata = sl->numStrata;
27505fdea053SToby Isaac   label     = sl->label;
27515fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
27525fdea053SToby Isaac     PetscInt point = points[2 * i];
27535fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
27545fdea053SToby Isaac 
27555fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
27565fdea053SToby Isaac       if (label->validIS[j]) {
27575fdea053SToby Isaac         PetscInt k;
27585fdea053SToby Isaac 
27599566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j], point, &k));
27605fdea053SToby Isaac         if (k >= 0) break;
27615fdea053SToby Isaac       } else {
27625fdea053SToby Isaac         PetscBool has;
27635fdea053SToby Isaac 
27649566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
27655fdea053SToby Isaac         if (has) break;
27665fdea053SToby Isaac       }
27675fdea053SToby Isaac     }
27689371c9d4SSatish 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],
27699371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2770ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2771ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
27725fdea053SToby Isaac   }
27733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27745fdea053SToby Isaac }
27755fdea053SToby Isaac 
2776d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2777d71ae5a4SJacob Faibussowitsch {
2778b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2779b004864fSMatthew G. Knepley   IS                     valIS;
2780b004864fSMatthew G. Knepley   const PetscInt        *values;
2781b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2782b004864fSMatthew G. Knepley 
2783b004864fSMatthew G. Knepley   PetscFunctionBegin;
27849566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
27859566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
27869566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2787b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2788b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2789b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2790b004864fSMatthew G. Knepley     const PetscInt    **perms;
2791b004864fSMatthew G. Knepley     const PetscScalar **rots;
2792b004864fSMatthew G. Knepley 
27939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
27949566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2795b004864fSMatthew G. Knepley   }
27969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
27973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2798b004864fSMatthew G. Knepley }
2799b004864fSMatthew G. Knepley 
2800d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2801d71ae5a4SJacob Faibussowitsch {
2802b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2803b004864fSMatthew G. Knepley   DMLabel                dlabel;
2804b004864fSMatthew G. Knepley 
2805b004864fSMatthew G. Knepley   PetscFunctionBegin;
28069566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
28079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
28089566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
28099566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
28103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2811b004864fSMatthew G. Knepley }
2812b004864fSMatthew G. Knepley 
2813d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2814d71ae5a4SJacob Faibussowitsch {
28155fdea053SToby Isaac   PetscSectionSym_Label *sl;
28165fdea053SToby Isaac 
28175fdea053SToby Isaac   PetscFunctionBegin;
28184dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
28195fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2820b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2821b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
28225fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
28235fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
28245fdea053SToby Isaac   sym->data            = (void *)sl;
28253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28265fdea053SToby Isaac }
28275fdea053SToby Isaac 
28285fdea053SToby Isaac /*@
28295fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
28305fdea053SToby Isaac 
28315fdea053SToby Isaac   Collective
28325fdea053SToby Isaac 
28335fdea053SToby Isaac   Input Parameters:
28345fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
28355fdea053SToby Isaac - label - the label defining the strata
28365fdea053SToby Isaac 
28375fdea053SToby Isaac   Output Parameters:
28385fdea053SToby Isaac . sym - the section symmetries
28395fdea053SToby Isaac 
28405fdea053SToby Isaac   Level: developer
28415fdea053SToby Isaac 
2842*20f4b53cSBarry Smith .seealso: `DMLabel`, `DM`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
28435fdea053SToby Isaac @*/
2844d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2845d71ae5a4SJacob Faibussowitsch {
28465fdea053SToby Isaac   PetscFunctionBegin;
28479566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
28489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
28499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
28509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
28513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28525fdea053SToby Isaac }
2853