xref: /petsc/src/dm/label/dmlabel.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
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
11c58f1c22SToby Isaac   DMLabelCreate - Create a DMLabel object, which is a multimap
12c58f1c22SToby Isaac 
135b5e7992SMatthew G. Knepley   Collective
145b5e7992SMatthew G. Knepley 
15d67d17b1SMatthew G. Knepley   Input parameters:
16d67d17b1SMatthew G. Knepley + comm - The communicator, usually PETSC_COMM_SELF
17d67d17b1SMatthew G. Knepley - name - The label name
18c58f1c22SToby Isaac 
19c58f1c22SToby Isaac   Output parameter:
20c58f1c22SToby Isaac . label - The DMLabel
21c58f1c22SToby Isaac 
22c58f1c22SToby Isaac   Level: beginner
23c58f1c22SToby Isaac 
2405ab7a9fSVaclav Hapla   Notes:
2505ab7a9fSVaclav Hapla   The label name is actually usual PetscObject name.
2605ab7a9fSVaclav Hapla   One can get/set it with PetscObjectGetName()/PetscObjectSetName().
2705ab7a9fSVaclav Hapla 
28db781477SPatrick Sanan .seealso: `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));
51*3ba16761SJacob 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 
649f6c5813SMatthew G. Knepley .seealso: `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);
71*3ba16761SJacob 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:
80c58f1c22SToby Isaac + label - The DMLabel
81c58f1c22SToby Isaac - v - The stratum value
82c58f1c22SToby Isaac 
83c58f1c22SToby Isaac   Output parameter:
84c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
85c58f1c22SToby Isaac 
86c58f1c22SToby Isaac   Level: developer
87c58f1c22SToby Isaac 
88db781477SPatrick Sanan .seealso: `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 
95*3ba16761SJacob 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));
120*3ba16761SJacob 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 
1265b5e7992SMatthew G. Knepley   Not collective
1275b5e7992SMatthew G. Knepley 
128c58f1c22SToby Isaac   Input parameter:
129c58f1c22SToby Isaac . label - The DMLabel
130c58f1c22SToby Isaac 
131c58f1c22SToby Isaac   Output parameter:
132c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Level: developer
135c58f1c22SToby Isaac 
136db781477SPatrick Sanan .seealso: `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));
144*3ba16761SJacob 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 
1505b5e7992SMatthew G. Knepley   Not collective
1515b5e7992SMatthew G. Knepley 
152c58f1c22SToby Isaac   Input parameter:
153c58f1c22SToby Isaac + label - The DMLabel
154c58f1c22SToby Isaac - v - The stratum value
155c58f1c22SToby Isaac 
156c58f1c22SToby Isaac   Output parameter:
157c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
158c58f1c22SToby Isaac 
159c58f1c22SToby Isaac   Level: developer
160c58f1c22SToby Isaac 
161db781477SPatrick Sanan .seealso: `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 
168*3ba16761SJacob 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;
178*3ba16761SJacob 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));
187*3ba16761SJacob 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   }
224*3ba16761SJacob 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;
282*3ba16761SJacob 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));
290*3ba16761SJacob 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;
297*3ba16761SJacob 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   }
303*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3049e63cc69SVaclav Hapla }
3059e63cc69SVaclav Hapla 
306b9907514SLisandro Dalcin /*@
307b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
308b9907514SLisandro Dalcin 
309d8d19677SJose E. Roman   Input Parameters:
310b9907514SLisandro Dalcin + label - The DMLabel
311b9907514SLisandro Dalcin - value - The stratum value
312b9907514SLisandro Dalcin 
313b9907514SLisandro Dalcin   Level: beginner
314b9907514SLisandro Dalcin 
315db781477SPatrick Sanan .seealso: `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));
325*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326b9907514SLisandro Dalcin }
327b9907514SLisandro Dalcin 
328b9907514SLisandro Dalcin /*@
329b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
330b9907514SLisandro Dalcin 
3315b5e7992SMatthew G. Knepley   Not collective
3325b5e7992SMatthew G. Knepley 
333d8d19677SJose E. Roman   Input Parameters:
334b9907514SLisandro Dalcin + 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 
340db781477SPatrick Sanan .seealso: `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));
387*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388b9907514SLisandro Dalcin }
389b9907514SLisandro Dalcin 
390b9907514SLisandro Dalcin /*@
391b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
392b9907514SLisandro Dalcin 
3935b5e7992SMatthew G. Knepley   Not collective
3945b5e7992SMatthew G. Knepley 
395d8d19677SJose E. Roman   Input Parameters:
396b9907514SLisandro Dalcin + label - The DMLabel
397b9907514SLisandro Dalcin - valueIS - Index set with stratum values
398b9907514SLisandro Dalcin 
399b9907514SLisandro Dalcin   Level: beginner
400b9907514SLisandro Dalcin 
401db781477SPatrick Sanan .seealso: `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));
415*3ba16761SJacob 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));
444*3ba16761SJacob 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));
454*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4559f6c5813SMatthew G. Knepley }
4569f6c5813SMatthew G. Knepley 
457c58f1c22SToby Isaac /*@C
458c58f1c22SToby Isaac   DMLabelView - View the label
459c58f1c22SToby Isaac 
4605b5e7992SMatthew G. Knepley   Collective on viewer
4615b5e7992SMatthew G. Knepley 
462c58f1c22SToby Isaac   Input Parameters:
463c58f1c22SToby Isaac + label - The DMLabel
464c58f1c22SToby Isaac - viewer - The PetscViewer
465c58f1c22SToby Isaac 
466c58f1c22SToby Isaac   Level: intermediate
467c58f1c22SToby Isaac 
468db781477SPatrick Sanan .seealso: `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);
478*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
479c58f1c22SToby Isaac }
480c58f1c22SToby Isaac 
48184f0b6dfSMatthew G. Knepley /*@
482d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
483d67d17b1SMatthew G. Knepley 
4845b5e7992SMatthew G. Knepley   Not collective
4855b5e7992SMatthew G. Knepley 
486d67d17b1SMatthew G. Knepley   Input Parameter:
487d67d17b1SMatthew G. Knepley . label - The DMLabel
488d67d17b1SMatthew G. Knepley 
489d67d17b1SMatthew G. Knepley   Level: beginner
490d67d17b1SMatthew G. Knepley 
491db781477SPatrick Sanan .seealso: `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));
518*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
519d67d17b1SMatthew G. Knepley }
520d67d17b1SMatthew G. Knepley 
521d67d17b1SMatthew G. Knepley /*@
52284f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
52384f0b6dfSMatthew G. Knepley 
5245b5e7992SMatthew G. Knepley   Collective on label
5255b5e7992SMatthew G. Knepley 
52684f0b6dfSMatthew G. Knepley   Input Parameter:
52784f0b6dfSMatthew G. Knepley . label - The DMLabel
52884f0b6dfSMatthew G. Knepley 
52984f0b6dfSMatthew G. Knepley   Level: beginner
53084f0b6dfSMatthew G. Knepley 
531db781477SPatrick Sanan .seealso: `DMLabelReset()`, `DMLabelCreate()`
53284f0b6dfSMatthew G. Knepley @*/
533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
534d71ae5a4SJacob Faibussowitsch {
535c58f1c22SToby Isaac   PetscFunctionBegin;
536*3ba16761SJacob 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;
540*3ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5419371c9d4SSatish Balay   }
5429566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5439566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5449566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
545*3ba16761SJacob 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));
558*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5599f6c5813SMatthew G. Knepley }
5609f6c5813SMatthew G. Knepley 
56184f0b6dfSMatthew G. Knepley /*@
56284f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
56384f0b6dfSMatthew G. Knepley 
5645b5e7992SMatthew G. Knepley   Collective on label
5655b5e7992SMatthew G. Knepley 
56684f0b6dfSMatthew G. Knepley   Input Parameter:
56784f0b6dfSMatthew G. Knepley . label - The DMLabel
56884f0b6dfSMatthew G. Knepley 
56984f0b6dfSMatthew G. Knepley   Output Parameter:
57084f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
57184f0b6dfSMatthew G. Knepley 
57284f0b6dfSMatthew G. Knepley   Level: intermediate
57384f0b6dfSMatthew G. Knepley 
574db781477SPatrick Sanan .seealso: `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);
602*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
603c58f1c22SToby Isaac }
604c58f1c22SToby Isaac 
605609dae6eSVaclav Hapla /*@C
606609dae6eSVaclav Hapla   DMLabelCompare - Compare two DMLabel objects
607609dae6eSVaclav Hapla 
6085efe38ccSVaclav Hapla   Collective on comm
609609dae6eSVaclav Hapla 
610609dae6eSVaclav Hapla   Input Parameters:
611f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
612f1a722f8SMatthew G. Knepley . l0 - First DMLabel
613609dae6eSVaclav Hapla - 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.
6235efe38ccSVaclav Hapla   If it is passed as NULL and difference is found, an error is thrown on all processes.
6245efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
625609dae6eSVaclav Hapla 
6265efe38ccSVaclav Hapla   The output message is set independently on each rank.
6275efe38ccSVaclav Hapla   It is set to NULL if no difference was found on the current rank. It must be freed by user.
6285efe38ccSVaclav Hapla   If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
6295efe38ccSVaclav Hapla   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 
6335efe38ccSVaclav Hapla   The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
6345efe38ccSVaclav Hapla 
635609dae6eSVaclav Hapla   Fortran Notes:
636609dae6eSVaclav Hapla   This function is currently not available from Fortran.
637609dae6eSVaclav Hapla 
638db781477SPatrick Sanan .seealso: `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
639609dae6eSVaclav Hapla @*/
640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
641d71ae5a4SJacob Faibussowitsch {
642609dae6eSVaclav Hapla   const char *name0, *name1;
643609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6445efe38ccSVaclav Hapla   PetscBool   eq;
6455efe38ccSVaclav Hapla   PetscMPIInt rank;
646609dae6eSVaclav Hapla 
647609dae6eSVaclav Hapla   PetscFunctionBegin;
6485efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6495efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6505efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
6515efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
6529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6539566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6549566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
655609dae6eSVaclav Hapla   {
656609dae6eSVaclav Hapla     PetscInt v0, v1;
657609dae6eSVaclav Hapla 
6589566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6599566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6605efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
66148a46eb9SPierre 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));
6629566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6635efe38ccSVaclav Hapla     if (!eq) goto finish;
664609dae6eSVaclav Hapla   }
665609dae6eSVaclav Hapla   {
666609dae6eSVaclav Hapla     IS is0, is1;
667609dae6eSVaclav Hapla 
6689566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6699566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6709566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6719566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6729566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
67348a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
6749566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6755efe38ccSVaclav Hapla     if (!eq) goto finish;
676609dae6eSVaclav Hapla   }
677609dae6eSVaclav Hapla   {
678609dae6eSVaclav Hapla     PetscInt i, nValues;
679609dae6eSVaclav Hapla 
6809566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
681609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
682609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
683609dae6eSVaclav Hapla       PetscInt       n;
684609dae6eSVaclav Hapla       IS             is0, is1;
685609dae6eSVaclav Hapla 
6869566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
687609dae6eSVaclav Hapla       if (!n) continue;
6889566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6899566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6909566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6919566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6929566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6935efe38ccSVaclav Hapla       if (!eq) {
69463a3b9bcSJacob 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));
6955efe38ccSVaclav Hapla         break;
696609dae6eSVaclav Hapla       }
697609dae6eSVaclav Hapla     }
6989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
699609dae6eSVaclav Hapla   }
700609dae6eSVaclav Hapla finish:
7015efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
702609dae6eSVaclav Hapla   if (message) {
703609dae6eSVaclav Hapla     *message = NULL;
70448a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
7055efe38ccSVaclav Hapla   } else {
70648a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
7079566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
7085efe38ccSVaclav Hapla   }
7095efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
7105efe38ccSVaclav Hapla   if (equal) *equal = eq;
71163a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
712*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
713609dae6eSVaclav Hapla }
714609dae6eSVaclav Hapla 
715c6a43d28SMatthew G. Knepley /*@
716c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
717c6a43d28SMatthew G. Knepley 
7185b5e7992SMatthew G. Knepley   Not collective
7195b5e7992SMatthew G. Knepley 
720c6a43d28SMatthew G. Knepley   Input Parameter:
721c6a43d28SMatthew G. Knepley . label  - The DMLabel
722c6a43d28SMatthew G. Knepley 
723c6a43d28SMatthew G. Knepley   Level: intermediate
724c6a43d28SMatthew G. Knepley 
725db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
726c6a43d28SMatthew G. Knepley @*/
727d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
728d71ae5a4SJacob Faibussowitsch {
729c6a43d28SMatthew G. Knepley   PetscInt pStart = PETSC_MAX_INT, pEnd = -1, v;
730c6a43d28SMatthew G. Knepley 
731c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
732c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7339566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
734c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
735c6a43d28SMatthew G. Knepley     const PetscInt *points;
736c6a43d28SMatthew G. Knepley     PetscInt        i;
737c6a43d28SMatthew G. Knepley 
7389566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
739c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
740c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
741c6a43d28SMatthew G. Knepley 
742c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
743c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
744c6a43d28SMatthew G. Knepley     }
7459566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
746c6a43d28SMatthew G. Knepley   }
747c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
748c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7499566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
750*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
751c6a43d28SMatthew G. Knepley }
752c6a43d28SMatthew G. Knepley 
753c6a43d28SMatthew G. Knepley /*@
754c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
755c6a43d28SMatthew G. Knepley 
7565b5e7992SMatthew G. Knepley   Not collective
7575b5e7992SMatthew G. Knepley 
758c6a43d28SMatthew G. Knepley   Input Parameters:
759c6a43d28SMatthew G. Knepley + label  - The DMLabel
760c6a43d28SMatthew G. Knepley . pStart - The smallest point
761c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
762c6a43d28SMatthew G. Knepley 
763c6a43d28SMatthew G. Knepley   Level: intermediate
764c6a43d28SMatthew G. Knepley 
765db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
766c6a43d28SMatthew G. Knepley @*/
767d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
768d71ae5a4SJacob Faibussowitsch {
769c58f1c22SToby Isaac   PetscInt v;
770c58f1c22SToby Isaac 
771c58f1c22SToby Isaac   PetscFunctionBegin;
772d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7739566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7749566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
775c58f1c22SToby Isaac   label->pStart = pStart;
776c58f1c22SToby Isaac   label->pEnd   = pEnd;
777c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7789566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
779c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
7809f6c5813SMatthew G. Knepley     IS              pointIS;
781ad8374ffSToby Isaac     const PetscInt *points;
782c58f1c22SToby Isaac     PetscInt        i;
783c58f1c22SToby Isaac 
7849f6c5813SMatthew G. Knepley     PetscUseTypeMethod(label, getstratumis, v, &pointIS);
7859f6c5813SMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
786c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
787ad8374ffSToby Isaac       const PetscInt point = points[i];
788c58f1c22SToby Isaac 
7899f6c5813SMatthew 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);
7909566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
791c58f1c22SToby Isaac     }
7929566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
7939f6c5813SMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
794c58f1c22SToby Isaac   }
795*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
796c58f1c22SToby Isaac }
797c58f1c22SToby Isaac 
798c6a43d28SMatthew G. Knepley /*@
799c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
800c6a43d28SMatthew G. Knepley 
8015b5e7992SMatthew G. Knepley   Not collective
8025b5e7992SMatthew G. Knepley 
803c6a43d28SMatthew G. Knepley   Input Parameter:
804c6a43d28SMatthew G. Knepley . label - the DMLabel
805c6a43d28SMatthew G. Knepley 
806c6a43d28SMatthew G. Knepley   Level: intermediate
807c6a43d28SMatthew G. Knepley 
808db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
809c6a43d28SMatthew G. Knepley @*/
810d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
811d71ae5a4SJacob Faibussowitsch {
812c58f1c22SToby Isaac   PetscFunctionBegin;
813d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
814c58f1c22SToby Isaac   label->pStart = -1;
815c58f1c22SToby Isaac   label->pEnd   = -1;
8169566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
817*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818c58f1c22SToby Isaac }
819c58f1c22SToby Isaac 
820c58f1c22SToby Isaac /*@
821c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
822c6a43d28SMatthew G. Knepley 
8235b5e7992SMatthew G. Knepley   Not collective
8245b5e7992SMatthew G. Knepley 
825c6a43d28SMatthew G. Knepley   Input Parameter:
826c6a43d28SMatthew G. Knepley . label - the DMLabel
827c6a43d28SMatthew G. Knepley 
828c6a43d28SMatthew G. Knepley   Output Parameters:
829c6a43d28SMatthew G. Knepley + pStart - The smallest point
830c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
831c6a43d28SMatthew G. Knepley 
832c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
833c6a43d28SMatthew G. Knepley 
834c6a43d28SMatthew G. Knepley   Level: intermediate
835c6a43d28SMatthew G. Knepley 
836db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
837c6a43d28SMatthew G. Knepley @*/
838d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
839d71ae5a4SJacob Faibussowitsch {
840c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
841c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8429566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
843c6a43d28SMatthew G. Knepley   if (pStart) {
844534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
845c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
846c6a43d28SMatthew G. Knepley   }
847c6a43d28SMatthew G. Knepley   if (pEnd) {
848534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
849c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
850c6a43d28SMatthew G. Knepley   }
851*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
852c6a43d28SMatthew G. Knepley }
853c6a43d28SMatthew G. Knepley 
854c6a43d28SMatthew G. Knepley /*@
855c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
856c58f1c22SToby Isaac 
8575b5e7992SMatthew G. Knepley   Not collective
8585b5e7992SMatthew G. Knepley 
859c58f1c22SToby Isaac   Input Parameters:
860c58f1c22SToby Isaac + label - the DMLabel
861c58f1c22SToby Isaac - value - the value
862c58f1c22SToby Isaac 
863c58f1c22SToby Isaac   Output Parameter:
864c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
865c58f1c22SToby Isaac 
866c58f1c22SToby Isaac   Level: developer
867c58f1c22SToby Isaac 
868db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
869c58f1c22SToby Isaac @*/
870d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
871d71ae5a4SJacob Faibussowitsch {
872c58f1c22SToby Isaac   PetscInt v;
873c58f1c22SToby Isaac 
874c58f1c22SToby Isaac   PetscFunctionBegin;
875d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
876534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8779566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8780c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
879*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
880c58f1c22SToby Isaac }
881c58f1c22SToby Isaac 
882c58f1c22SToby Isaac /*@
883c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
884c58f1c22SToby Isaac 
8855b5e7992SMatthew G. Knepley   Not collective
8865b5e7992SMatthew G. Knepley 
887c58f1c22SToby Isaac   Input Parameters:
888c58f1c22SToby Isaac + label - the DMLabel
889c58f1c22SToby Isaac - point - the point
890c58f1c22SToby Isaac 
891c58f1c22SToby Isaac   Output Parameter:
892c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
893c58f1c22SToby Isaac 
894c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
895c58f1c22SToby Isaac 
896c58f1c22SToby Isaac   Level: developer
897c58f1c22SToby Isaac 
898db781477SPatrick Sanan .seealso: `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
899c58f1c22SToby Isaac @*/
900d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
901d71ae5a4SJacob Faibussowitsch {
902c58f1c22SToby Isaac   PetscFunctionBeginHot;
903d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
904534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
9059566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
90676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
90728b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
90863a3b9bcSJacob 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);
90976bd3646SJed Brown   }
910c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
911*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
912c58f1c22SToby Isaac }
913c58f1c22SToby Isaac 
914c58f1c22SToby Isaac /*@
915c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
916c58f1c22SToby Isaac 
9175b5e7992SMatthew G. Knepley   Not collective
9185b5e7992SMatthew G. Knepley 
919c58f1c22SToby Isaac   Input Parameters:
920c58f1c22SToby Isaac + label - the DMLabel
921c58f1c22SToby Isaac . value - the stratum value
922c58f1c22SToby Isaac - point - the point
923c58f1c22SToby Isaac 
924c58f1c22SToby Isaac   Output Parameter:
925c58f1c22SToby Isaac . contains - true if the stratum contains the point
926c58f1c22SToby Isaac 
927c58f1c22SToby Isaac   Level: intermediate
928c58f1c22SToby Isaac 
929db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
930c58f1c22SToby Isaac @*/
931d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
932d71ae5a4SJacob Faibussowitsch {
9330c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
934d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
935534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
936cffad2c9SToby Isaac   if (value == label->defaultValue) {
937cffad2c9SToby Isaac     PetscInt pointVal;
9380c3c4a36SLisandro Dalcin 
939cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
940cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
941cffad2c9SToby Isaac   } else {
942cffad2c9SToby Isaac     PetscInt v;
943cffad2c9SToby Isaac 
944cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
945cffad2c9SToby Isaac     if (v >= 0) {
9469f6c5813SMatthew G. Knepley       if (label->validIS[v] || label->readonly) {
9479f6c5813SMatthew G. Knepley         IS       is;
948c58f1c22SToby Isaac         PetscInt i;
949c58f1c22SToby Isaac 
9509f6c5813SMatthew G. Knepley         PetscUseTypeMethod(label, getstratumis, v, &is);
9519f6c5813SMatthew G. Knepley         PetscCall(ISLocate(is, point, &i));
9529f6c5813SMatthew G. Knepley         PetscCall(ISDestroy(&is));
953cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
954c58f1c22SToby Isaac       } else {
955cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
956cffad2c9SToby Isaac       }
957cffad2c9SToby Isaac     } else { // value is not present
958cffad2c9SToby Isaac       *contains = PETSC_FALSE;
959cffad2c9SToby Isaac     }
960c58f1c22SToby Isaac   }
961*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
962c58f1c22SToby Isaac }
963c58f1c22SToby Isaac 
96484f0b6dfSMatthew G. Knepley /*@
9655aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9665aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9675aa44df4SToby Isaac 
9685b5e7992SMatthew G. Knepley   Not collective
9695b5e7992SMatthew G. Knepley 
9705aa44df4SToby Isaac   Input parameter:
9715aa44df4SToby Isaac . label - a DMLabel object
9725aa44df4SToby Isaac 
9735aa44df4SToby Isaac   Output parameter:
9745aa44df4SToby Isaac . defaultValue - the default value
9755aa44df4SToby Isaac 
9765aa44df4SToby Isaac   Level: beginner
9775aa44df4SToby Isaac 
978db781477SPatrick Sanan .seealso: `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
97984f0b6dfSMatthew G. Knepley @*/
980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
981d71ae5a4SJacob Faibussowitsch {
9825aa44df4SToby Isaac   PetscFunctionBegin;
983d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9845aa44df4SToby Isaac   *defaultValue = label->defaultValue;
985*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9865aa44df4SToby Isaac }
9875aa44df4SToby Isaac 
98884f0b6dfSMatthew G. Knepley /*@
9895aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9905aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9915aa44df4SToby Isaac 
9925b5e7992SMatthew G. Knepley   Not collective
9935b5e7992SMatthew G. Knepley 
9945aa44df4SToby Isaac   Input parameter:
9955aa44df4SToby Isaac . label - a DMLabel object
9965aa44df4SToby Isaac 
9975aa44df4SToby Isaac   Output parameter:
9985aa44df4SToby Isaac . defaultValue - the default value
9995aa44df4SToby Isaac 
10005aa44df4SToby Isaac   Level: beginner
10015aa44df4SToby Isaac 
1002db781477SPatrick Sanan .seealso: `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
100384f0b6dfSMatthew G. Knepley @*/
1004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
1005d71ae5a4SJacob Faibussowitsch {
10065aa44df4SToby Isaac   PetscFunctionBegin;
1007d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10085aa44df4SToby Isaac   label->defaultValue = defaultValue;
1009*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10105aa44df4SToby Isaac }
10115aa44df4SToby Isaac 
1012c58f1c22SToby Isaac /*@
10135aa44df4SToby Isaac   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 DMLabelSetDefaultValue())
1014c58f1c22SToby Isaac 
10155b5e7992SMatthew G. Knepley   Not collective
10165b5e7992SMatthew G. Knepley 
1017c58f1c22SToby Isaac   Input Parameters:
1018c58f1c22SToby Isaac + 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 
1024cffad2c9SToby Isaac   Note: a label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.  Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
1025cffad2c9SToby Isaac 
1026c58f1c22SToby Isaac   Level: intermediate
1027c58f1c22SToby Isaac 
1028db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1029c58f1c22SToby Isaac @*/
1030d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
1031d71ae5a4SJacob Faibussowitsch {
1032c58f1c22SToby Isaac   PetscInt v;
1033c58f1c22SToby Isaac 
10340c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
1035d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1036dadcf809SJacob Faibussowitsch   PetscValidIntPointer(value, 3);
10375aa44df4SToby Isaac   *value = label->defaultValue;
1038c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
10399f6c5813SMatthew G. Knepley     if (label->validIS[v] || label->readonly) {
10409f6c5813SMatthew G. Knepley       IS       is;
1041c58f1c22SToby Isaac       PetscInt i;
1042c58f1c22SToby Isaac 
10439f6c5813SMatthew G. Knepley       PetscUseTypeMethod(label, getstratumis, v, &is);
10449566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
10459f6c5813SMatthew G. Knepley       PetscCall(ISDestroy(&is));
1046c58f1c22SToby Isaac       if (i >= 0) {
1047c58f1c22SToby Isaac         *value = label->stratumValues[v];
1048c58f1c22SToby Isaac         break;
1049c58f1c22SToby Isaac       }
1050c58f1c22SToby Isaac     } else {
1051c58f1c22SToby Isaac       PetscBool has;
1052c58f1c22SToby Isaac 
10539566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1054c58f1c22SToby Isaac       if (has) {
1055c58f1c22SToby Isaac         *value = label->stratumValues[v];
1056c58f1c22SToby Isaac         break;
1057c58f1c22SToby Isaac       }
1058c58f1c22SToby Isaac     }
1059c58f1c22SToby Isaac   }
1060*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1061c58f1c22SToby Isaac }
1062c58f1c22SToby Isaac 
1063c58f1c22SToby Isaac /*@
1064367003a6SStefano Zampini   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 be changed with DMLabelSetDefaultValue() to something different), then this function will do nothing.
1065c58f1c22SToby Isaac 
10665b5e7992SMatthew G. Knepley   Not collective
10675b5e7992SMatthew G. Knepley 
1068c58f1c22SToby Isaac   Input Parameters:
1069c58f1c22SToby Isaac + label - the DMLabel
1070c58f1c22SToby Isaac . point - the point
1071c58f1c22SToby Isaac - value - The point value
1072c58f1c22SToby Isaac 
1073c58f1c22SToby Isaac   Level: intermediate
1074c58f1c22SToby Isaac 
1075db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1076c58f1c22SToby Isaac @*/
1077d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1078d71ae5a4SJacob Faibussowitsch {
1079c58f1c22SToby Isaac   PetscInt v;
1080c58f1c22SToby Isaac 
1081c58f1c22SToby Isaac   PetscFunctionBegin;
1082d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10830c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
1084*3ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
10859f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
10869566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1087c58f1c22SToby Isaac   /* Set key */
10889566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10899566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
1090*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1091c58f1c22SToby Isaac }
1092c58f1c22SToby Isaac 
1093c58f1c22SToby Isaac /*@
1094c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1095c58f1c22SToby Isaac 
10965b5e7992SMatthew G. Knepley   Not collective
10975b5e7992SMatthew G. Knepley 
1098c58f1c22SToby Isaac   Input Parameters:
1099c58f1c22SToby Isaac + label - the DMLabel
1100c58f1c22SToby Isaac . point - the point
1101c58f1c22SToby Isaac - value - The point value
1102c58f1c22SToby Isaac 
1103c58f1c22SToby Isaac   Level: intermediate
1104c58f1c22SToby Isaac 
1105db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1106c58f1c22SToby Isaac @*/
1107d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1108d71ae5a4SJacob Faibussowitsch {
1109ad8374ffSToby Isaac   PetscInt v;
1110c58f1c22SToby Isaac 
1111c58f1c22SToby Isaac   PetscFunctionBegin;
1112d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11139f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
1114c58f1c22SToby Isaac   /* Find label value */
11159566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1116*3ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
11170c3c4a36SLisandro Dalcin 
1118eeed21e7SToby Isaac   if (label->bt) {
111963a3b9bcSJacob 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);
11209566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1121eeed21e7SToby Isaac   }
11220c3c4a36SLisandro Dalcin 
11230c3c4a36SLisandro Dalcin   /* Delete key */
11249566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11259566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
1126*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1127c58f1c22SToby Isaac }
1128c58f1c22SToby Isaac 
1129c58f1c22SToby Isaac /*@
1130c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
1131c58f1c22SToby Isaac 
11325b5e7992SMatthew G. Knepley   Not collective
11335b5e7992SMatthew G. Knepley 
1134c58f1c22SToby Isaac   Input Parameters:
1135c58f1c22SToby Isaac + label - the DMLabel
1136c58f1c22SToby Isaac . is    - the point IS
1137c58f1c22SToby Isaac - value - The point value
1138c58f1c22SToby Isaac 
1139c58f1c22SToby Isaac   Level: intermediate
1140c58f1c22SToby Isaac 
1141db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1142c58f1c22SToby Isaac @*/
1143d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1144d71ae5a4SJacob Faibussowitsch {
11450c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1146c58f1c22SToby Isaac   const PetscInt *points;
1147c58f1c22SToby Isaac 
1148c58f1c22SToby Isaac   PetscFunctionBegin;
1149d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1150c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11510c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
1152*3ba16761SJacob Faibussowitsch   if (value == label->defaultValue) PetscFunctionReturn(PETSC_SUCCESS);
11539f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
11549566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11550c3c4a36SLisandro Dalcin   /* Set keys */
11569566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11579566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11589566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11599566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11609566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
1161*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1162c58f1c22SToby Isaac }
1163c58f1c22SToby Isaac 
116484f0b6dfSMatthew G. Knepley /*@
116584f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
116684f0b6dfSMatthew G. Knepley 
11675b5e7992SMatthew G. Knepley   Not collective
11685b5e7992SMatthew G. Knepley 
116984f0b6dfSMatthew G. Knepley   Input Parameter:
117084f0b6dfSMatthew G. Knepley . label - the DMLabel
117184f0b6dfSMatthew G. Knepley 
117201d2d390SJose E. Roman   Output Parameter:
117384f0b6dfSMatthew G. Knepley . numValues - the number of values
117484f0b6dfSMatthew G. Knepley 
117584f0b6dfSMatthew G. Knepley   Level: intermediate
117684f0b6dfSMatthew G. Knepley 
1177db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
117884f0b6dfSMatthew G. Knepley @*/
1179d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1180d71ae5a4SJacob Faibussowitsch {
1181c58f1c22SToby Isaac   PetscFunctionBegin;
1182d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1183dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numValues, 2);
1184c58f1c22SToby Isaac   *numValues = label->numStrata;
1185*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1186c58f1c22SToby Isaac }
1187c58f1c22SToby Isaac 
118884f0b6dfSMatthew G. Knepley /*@
118984f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
119084f0b6dfSMatthew G. Knepley 
11915b5e7992SMatthew G. Knepley   Not collective
11925b5e7992SMatthew G. Knepley 
119384f0b6dfSMatthew G. Knepley   Input Parameter:
119484f0b6dfSMatthew G. Knepley . label - the DMLabel
119584f0b6dfSMatthew G. Knepley 
119601d2d390SJose E. Roman   Output Parameter:
119784f0b6dfSMatthew G. Knepley . is    - the value IS
119884f0b6dfSMatthew G. Knepley 
119984f0b6dfSMatthew G. Knepley   Level: intermediate
120084f0b6dfSMatthew G. Knepley 
12011d04cbbeSVaclav Hapla   Notes:
12021d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
12031d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
12041d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
12051d04cbbeSVaclav Hapla 
1206db781477SPatrick Sanan .seealso: `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
120784f0b6dfSMatthew G. Knepley @*/
1208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1209d71ae5a4SJacob Faibussowitsch {
1210c58f1c22SToby Isaac   PetscFunctionBegin;
1211d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1212c58f1c22SToby Isaac   PetscValidPointer(values, 2);
12139566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1214*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1215c58f1c22SToby Isaac }
1216c58f1c22SToby Isaac 
121784f0b6dfSMatthew G. Knepley /*@
12181d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
12191d04cbbeSVaclav Hapla 
12201d04cbbeSVaclav Hapla   Not collective
12211d04cbbeSVaclav Hapla 
12221d04cbbeSVaclav Hapla   Input Parameter:
12231d04cbbeSVaclav Hapla . label - the DMLabel
12241d04cbbeSVaclav Hapla 
1225d5b43468SJose E. Roman   Output Parameter:
12261d04cbbeSVaclav Hapla . is    - the value IS
12271d04cbbeSVaclav Hapla 
12281d04cbbeSVaclav Hapla   Level: intermediate
12291d04cbbeSVaclav Hapla 
12301d04cbbeSVaclav Hapla   Notes:
12311d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
12321d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
12331d04cbbeSVaclav Hapla 
1234db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
12351d04cbbeSVaclav Hapla @*/
1236d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1237d71ae5a4SJacob Faibussowitsch {
12381d04cbbeSVaclav Hapla   PetscInt  i, j;
12391d04cbbeSVaclav Hapla   PetscInt *valuesArr;
12401d04cbbeSVaclav Hapla 
12411d04cbbeSVaclav Hapla   PetscFunctionBegin;
12421d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12431d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
12449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
12451d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
12461d04cbbeSVaclav Hapla     PetscInt n;
12471d04cbbeSVaclav Hapla 
12489566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
12491d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
12501d04cbbeSVaclav Hapla   }
12511d04cbbeSVaclav Hapla   if (j == label->numStrata) {
12529566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12531d04cbbeSVaclav Hapla   } else {
12549566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
12551d04cbbeSVaclav Hapla   }
12569566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
1257*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12581d04cbbeSVaclav Hapla }
12591d04cbbeSVaclav Hapla 
12601d04cbbeSVaclav Hapla /*@
1261d123abd9SMatthew G. Knepley   DMLabelGetValueIndex - Get the index of a given value in the list of values for the DMlabel, or -1 if it is not present
1262d123abd9SMatthew G. Knepley 
1263d123abd9SMatthew G. Knepley   Not collective
1264d123abd9SMatthew G. Knepley 
1265d123abd9SMatthew G. Knepley   Input Parameters:
1266d123abd9SMatthew G. Knepley + label - the DMLabel
126797bb3fdcSJose E. Roman - value - the value
1268d123abd9SMatthew G. Knepley 
126901d2d390SJose E. Roman   Output Parameter:
1270d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1271d123abd9SMatthew G. Knepley 
1272d123abd9SMatthew G. Knepley   Level: intermediate
1273d123abd9SMatthew G. Knepley 
1274db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1275d123abd9SMatthew G. Knepley @*/
1276d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1277d71ae5a4SJacob Faibussowitsch {
1278d123abd9SMatthew G. Knepley   PetscInt v;
1279d123abd9SMatthew G. Knepley 
1280d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1281d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1282dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 3);
1283d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
12849371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
12859371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1286d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1287d123abd9SMatthew G. Knepley   else *index = v;
1288*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1289d123abd9SMatthew G. Knepley }
1290d123abd9SMatthew G. Knepley 
1291d123abd9SMatthew G. Knepley /*@
129284f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
129384f0b6dfSMatthew G. Knepley 
12945b5e7992SMatthew G. Knepley   Not collective
12955b5e7992SMatthew G. Knepley 
129684f0b6dfSMatthew G. Knepley   Input Parameters:
129784f0b6dfSMatthew G. Knepley + label - the DMLabel
129884f0b6dfSMatthew G. Knepley - value - the stratum value
129984f0b6dfSMatthew G. Knepley 
130001d2d390SJose E. Roman   Output Parameter:
130184f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
130284f0b6dfSMatthew G. Knepley 
130384f0b6dfSMatthew G. Knepley   Level: intermediate
130484f0b6dfSMatthew G. Knepley 
1305db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
130684f0b6dfSMatthew G. Knepley @*/
1307d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1308d71ae5a4SJacob Faibussowitsch {
1309fada774cSMatthew G. Knepley   PetscInt v;
1310fada774cSMatthew G. Knepley 
1311fada774cSMatthew G. Knepley   PetscFunctionBegin;
1312d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1313dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(exists, 3);
13149566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13150c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1316*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1317fada774cSMatthew G. Knepley }
1318fada774cSMatthew G. Knepley 
131984f0b6dfSMatthew G. Knepley /*@
132084f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
132184f0b6dfSMatthew G. Knepley 
13225b5e7992SMatthew G. Knepley   Not collective
13235b5e7992SMatthew G. Knepley 
132484f0b6dfSMatthew G. Knepley   Input Parameters:
132584f0b6dfSMatthew G. Knepley + label - the DMLabel
132684f0b6dfSMatthew G. Knepley - value - the stratum value
132784f0b6dfSMatthew G. Knepley 
132801d2d390SJose E. Roman   Output Parameter:
132984f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
133084f0b6dfSMatthew G. Knepley 
133184f0b6dfSMatthew G. Knepley   Level: intermediate
133284f0b6dfSMatthew G. Knepley 
1333db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
133484f0b6dfSMatthew G. Knepley @*/
1335d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1336d71ae5a4SJacob Faibussowitsch {
1337c58f1c22SToby Isaac   PetscInt v;
1338c58f1c22SToby Isaac 
1339c58f1c22SToby Isaac   PetscFunctionBegin;
1340d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1341dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
13429566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13439566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
1344*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1345c58f1c22SToby Isaac }
1346c58f1c22SToby Isaac 
134784f0b6dfSMatthew G. Knepley /*@
134884f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
134984f0b6dfSMatthew G. Knepley 
13505b5e7992SMatthew G. Knepley   Not collective
13515b5e7992SMatthew G. Knepley 
135284f0b6dfSMatthew G. Knepley   Input Parameters:
135384f0b6dfSMatthew G. Knepley + label - the DMLabel
135484f0b6dfSMatthew G. Knepley - value - the stratum value
135584f0b6dfSMatthew G. Knepley 
135601d2d390SJose E. Roman   Output Parameters:
135784f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
135884f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
135984f0b6dfSMatthew G. Knepley 
136084f0b6dfSMatthew G. Knepley   Level: intermediate
136184f0b6dfSMatthew G. Knepley 
1362db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
136384f0b6dfSMatthew G. Knepley @*/
1364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1365d71ae5a4SJacob Faibussowitsch {
13669f6c5813SMatthew G. Knepley   IS       is;
13670c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1368c58f1c22SToby Isaac 
1369c58f1c22SToby Isaac   PetscFunctionBegin;
1370d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13719371c9d4SSatish Balay   if (start) {
13729371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
13739371c9d4SSatish Balay     *start = -1;
13749371c9d4SSatish Balay   }
13759371c9d4SSatish Balay   if (end) {
13769371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
13779371c9d4SSatish Balay     *end = -1;
13789371c9d4SSatish Balay   }
13799566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1380*3ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
13819566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
1382*3ba16761SJacob Faibussowitsch   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(PETSC_SUCCESS);
13839f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &is);
13849f6c5813SMatthew G. Knepley   PetscCall(ISGetMinMax(is, &min, &max));
13859f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&is));
1386d6cb179aSToby Isaac   if (start) *start = min;
1387d6cb179aSToby Isaac   if (end) *end = max + 1;
1388*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1389c58f1c22SToby Isaac }
1390c58f1c22SToby Isaac 
13919f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetStratumIS_Concrete(DMLabel label, PetscInt v, IS *pointIS)
13929f6c5813SMatthew G. Knepley {
13939f6c5813SMatthew G. Knepley   PetscFunctionBegin;
13949f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
13959f6c5813SMatthew G. Knepley   *pointIS = label->points[v];
1396*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13979f6c5813SMatthew G. Knepley }
13989f6c5813SMatthew G. Knepley 
139984f0b6dfSMatthew G. Knepley /*@
140084f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
140184f0b6dfSMatthew G. Knepley 
14025b5e7992SMatthew G. Knepley   Not collective
14035b5e7992SMatthew G. Knepley 
140484f0b6dfSMatthew G. Knepley   Input Parameters:
140584f0b6dfSMatthew G. Knepley + label - the DMLabel
140684f0b6dfSMatthew G. Knepley - value - the stratum value
140784f0b6dfSMatthew G. Knepley 
140801d2d390SJose E. Roman   Output Parameter:
140984f0b6dfSMatthew G. Knepley . points - The stratum points
141084f0b6dfSMatthew G. Knepley 
141184f0b6dfSMatthew G. Knepley   Level: intermediate
141284f0b6dfSMatthew G. Knepley 
1413593ce467SVaclav Hapla   Notes:
1414593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1415593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1416593ce467SVaclav Hapla 
1417db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
141884f0b6dfSMatthew G. Knepley @*/
1419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1420d71ae5a4SJacob Faibussowitsch {
1421c58f1c22SToby Isaac   PetscInt v;
1422c58f1c22SToby Isaac 
1423c58f1c22SToby Isaac   PetscFunctionBegin;
1424d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1425c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1426c58f1c22SToby Isaac   *points = NULL;
14279566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1428*3ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
14299566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14309f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, points);
1431*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1432c58f1c22SToby Isaac }
1433c58f1c22SToby Isaac 
143484f0b6dfSMatthew G. Knepley /*@
143584f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
143684f0b6dfSMatthew G. Knepley 
14375b5e7992SMatthew G. Knepley   Not collective
14385b5e7992SMatthew G. Knepley 
143984f0b6dfSMatthew G. Knepley   Input Parameters:
144084f0b6dfSMatthew G. Knepley + label - the DMLabel
144184f0b6dfSMatthew G. Knepley . value - the stratum value
144284f0b6dfSMatthew G. Knepley - points - The stratum points
144384f0b6dfSMatthew G. Knepley 
144484f0b6dfSMatthew G. Knepley   Level: intermediate
144584f0b6dfSMatthew G. Knepley 
1446db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
144784f0b6dfSMatthew G. Knepley @*/
1448d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1449d71ae5a4SJacob Faibussowitsch {
14500c3c4a36SLisandro Dalcin   PetscInt v;
14514de306b1SToby Isaac 
14524de306b1SToby Isaac   PetscFunctionBegin;
1453d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1454d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
14559f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
14569566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1457*3ba16761SJacob Faibussowitsch   if (is == label->points[v]) PetscFunctionReturn(PETSC_SUCCESS);
14589566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
14599566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
14609566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
14619566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&(label->points[v])));
14620c3c4a36SLisandro Dalcin   label->points[v]  = is;
14630c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
14649566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
14654de306b1SToby Isaac   if (label->bt) {
14664de306b1SToby Isaac     const PetscInt *points;
14674de306b1SToby Isaac     PetscInt        p;
14684de306b1SToby Isaac 
14699566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
14704de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
14714de306b1SToby Isaac       const PetscInt point = points[p];
14724de306b1SToby Isaac 
147363a3b9bcSJacob 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);
14749566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
14754de306b1SToby Isaac     }
14764de306b1SToby Isaac   }
1477*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14784de306b1SToby Isaac }
14794de306b1SToby Isaac 
148084f0b6dfSMatthew G. Knepley /*@
148184f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14824de306b1SToby Isaac 
14835b5e7992SMatthew G. Knepley   Not collective
14845b5e7992SMatthew G. Knepley 
148584f0b6dfSMatthew G. Knepley   Input Parameters:
148684f0b6dfSMatthew G. Knepley + label - the DMLabel
148784f0b6dfSMatthew G. Knepley - value - the stratum value
148884f0b6dfSMatthew G. Knepley 
148984f0b6dfSMatthew G. Knepley   Level: intermediate
149084f0b6dfSMatthew G. Knepley 
1491db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
149284f0b6dfSMatthew G. Knepley @*/
1493d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1494d71ae5a4SJacob Faibussowitsch {
1495c58f1c22SToby Isaac   PetscInt v;
1496c58f1c22SToby Isaac 
1497c58f1c22SToby Isaac   PetscFunctionBegin;
1498d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14999f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
15009566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1501*3ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15024de306b1SToby Isaac   if (label->validIS[v]) {
15034de306b1SToby Isaac     if (label->bt) {
1504c58f1c22SToby Isaac       PetscInt        i;
1505ad8374ffSToby Isaac       const PetscInt *points;
1506c58f1c22SToby Isaac 
15079566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1508c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1509ad8374ffSToby Isaac         const PetscInt point = points[i];
1510c58f1c22SToby Isaac 
151163a3b9bcSJacob 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);
15129566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1513c58f1c22SToby Isaac       }
15149566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1515c58f1c22SToby Isaac     }
1516c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
15179566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
15189566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
15199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
15209566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1521c58f1c22SToby Isaac   } else {
15229566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1523c58f1c22SToby Isaac   }
1524*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1525c58f1c22SToby Isaac }
1526c58f1c22SToby Isaac 
152784f0b6dfSMatthew G. Knepley /*@
1528412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1529412e9a14SMatthew G. Knepley 
1530412e9a14SMatthew G. Knepley   Not collective
1531412e9a14SMatthew G. Knepley 
1532412e9a14SMatthew G. Knepley   Input Parameters:
1533412e9a14SMatthew G. Knepley + label  - The DMLabel
1534412e9a14SMatthew G. Knepley . value  - The label value for all points
1535412e9a14SMatthew G. Knepley . pStart - The first point
1536412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1537412e9a14SMatthew G. Knepley 
1538412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1539412e9a14SMatthew G. Knepley 
1540412e9a14SMatthew G. Knepley   Level: intermediate
1541412e9a14SMatthew G. Knepley 
1542db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1543412e9a14SMatthew G. Knepley @*/
1544d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1545d71ae5a4SJacob Faibussowitsch {
1546412e9a14SMatthew G. Knepley   IS pIS;
1547412e9a14SMatthew G. Knepley 
1548412e9a14SMatthew G. Knepley   PetscFunctionBegin;
15499566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
15509566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
15519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
1552*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1553412e9a14SMatthew G. Knepley }
1554412e9a14SMatthew G. Knepley 
1555412e9a14SMatthew G. Knepley /*@
1556d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1557d123abd9SMatthew G. Knepley 
1558d123abd9SMatthew G. Knepley   Not collective
1559d123abd9SMatthew G. Knepley 
1560d123abd9SMatthew G. Knepley   Input Parameters:
1561d123abd9SMatthew G. Knepley + label  - The DMLabel
1562d123abd9SMatthew G. Knepley . value  - The label value
1563d123abd9SMatthew G. Knepley - p      - A point with this value
1564d123abd9SMatthew G. Knepley 
1565d123abd9SMatthew G. Knepley   Output Parameter:
1566d123abd9SMatthew G. Knepley . index  - The index of this point in the stratum, or -1 if the point is not in the stratum or the stratum does not exist
1567d123abd9SMatthew G. Knepley 
1568d123abd9SMatthew G. Knepley   Level: intermediate
1569d123abd9SMatthew G. Knepley 
1570db781477SPatrick Sanan .seealso: `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1571d123abd9SMatthew G. Knepley @*/
1572d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1573d71ae5a4SJacob Faibussowitsch {
15749f6c5813SMatthew G. Knepley   IS              pointIS;
1575d123abd9SMatthew G. Knepley   const PetscInt *indices;
1576d123abd9SMatthew G. Knepley   PetscInt        v;
1577d123abd9SMatthew G. Knepley 
1578d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1579d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1580dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 4);
1581d123abd9SMatthew G. Knepley   *index = -1;
15829566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1583*3ba16761SJacob Faibussowitsch   if (v < 0) PetscFunctionReturn(PETSC_SUCCESS);
15849566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
15859f6c5813SMatthew G. Knepley   PetscUseTypeMethod(label, getstratumis, v, &pointIS);
15869f6c5813SMatthew G. Knepley   PetscCall(ISGetIndices(pointIS, &indices));
15879566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
15889f6c5813SMatthew G. Knepley   PetscCall(ISRestoreIndices(pointIS, &indices));
15899f6c5813SMatthew G. Knepley   PetscCall(ISDestroy(&pointIS));
1590*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1591d123abd9SMatthew G. Knepley }
1592d123abd9SMatthew G. Knepley 
1593d123abd9SMatthew G. Knepley /*@
159484f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
159584f0b6dfSMatthew G. Knepley 
15965b5e7992SMatthew G. Knepley   Not collective
15975b5e7992SMatthew G. Knepley 
159884f0b6dfSMatthew G. Knepley   Input Parameters:
159984f0b6dfSMatthew G. Knepley + label - the DMLabel
160022cd2cdaSVaclav Hapla . start - the first point kept
160122cd2cdaSVaclav Hapla - end - one more than the last point kept
160284f0b6dfSMatthew G. Knepley 
160384f0b6dfSMatthew G. Knepley   Level: intermediate
160484f0b6dfSMatthew G. Knepley 
1605db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
160684f0b6dfSMatthew G. Knepley @*/
1607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1608d71ae5a4SJacob Faibussowitsch {
1609c58f1c22SToby Isaac   PetscInt v;
1610c58f1c22SToby Isaac 
1611c58f1c22SToby Isaac   PetscFunctionBegin;
1612d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16139f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16149566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
16159566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16169f6c5813SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
16179f6c5813SMatthew G. Knepley     PetscCall(ISGeneralFilter(label->points[v], start, end));
16189f6c5813SMatthew G. Knepley     PetscCall(ISGetLocalSize(label->points[v], &label->stratumSizes[v]));
16199f6c5813SMatthew G. Knepley   }
16209566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
1621*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1622c58f1c22SToby Isaac }
1623c58f1c22SToby Isaac 
162484f0b6dfSMatthew G. Knepley /*@
162584f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
162684f0b6dfSMatthew G. Knepley 
16275b5e7992SMatthew G. Knepley   Not collective
16285b5e7992SMatthew G. Knepley 
162984f0b6dfSMatthew G. Knepley   Input Parameters:
163084f0b6dfSMatthew G. Knepley + label - the DMLabel
163184f0b6dfSMatthew G. Knepley - permutation - the point permutation
163284f0b6dfSMatthew G. Knepley 
163384f0b6dfSMatthew G. Knepley   Output Parameter:
163484f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
163584f0b6dfSMatthew G. Knepley 
163684f0b6dfSMatthew G. Knepley   Level: intermediate
163784f0b6dfSMatthew G. Knepley 
1638db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
163984f0b6dfSMatthew G. Knepley @*/
1640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1641d71ae5a4SJacob Faibussowitsch {
1642c58f1c22SToby Isaac   const PetscInt *perm;
1643c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1644c58f1c22SToby Isaac 
1645c58f1c22SToby Isaac   PetscFunctionBegin;
1646d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1647d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
16489f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
16499566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
16509566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
16519566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
16529566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
16539566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1654c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1655c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1656ad8374ffSToby Isaac     const PetscInt *points;
1657ad8374ffSToby Isaac     PetscInt       *pointsNew;
1658c58f1c22SToby Isaac 
16599566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
16609f6c5813SMatthew G. Knepley     PetscCall(PetscCalloc1(size, &pointsNew));
1661c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1662ad8374ffSToby Isaac       const PetscInt point = points[q];
1663c58f1c22SToby Isaac 
166463a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < 0) && !(point >= numPoints), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ") for the remapping", point, numPoints);
1665ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1666c58f1c22SToby Isaac     }
16679566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
16689566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
16699566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1670fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
16719566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
16729566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1673fa8e8ae5SToby Isaac     } else {
16749566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1675fa8e8ae5SToby Isaac     }
16769566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1677c58f1c22SToby Isaac   }
16789566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1679c58f1c22SToby Isaac   if (label->bt) {
16809566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
16819566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1682c58f1c22SToby Isaac   }
1683*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1684c58f1c22SToby Isaac }
1685c58f1c22SToby Isaac 
1686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1687d71ae5a4SJacob Faibussowitsch {
168826c55118SMichael Lange   MPI_Comm     comm;
1689eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
169026c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
169126c55118SMichael Lange   PetscSection rootSection;
169226c55118SMichael Lange   PetscSF      labelSF;
169326c55118SMichael Lange 
169426c55118SMichael Lange   PetscFunctionBegin;
16959566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
16969566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
169726c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
169826c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
16999566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
17009566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
17019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
170226c55118SMichael Lange   if (label) {
170326c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1704ad8374ffSToby Isaac       const PetscInt *points;
1705ad8374ffSToby Isaac 
17069566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
170748a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
17089566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
170926c55118SMichael Lange     }
171026c55118SMichael Lange   }
17119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
171226c55118SMichael Lange   /* Create a point-wise array of stratum values */
17139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
17149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
17159566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
171626c55118SMichael Lange   if (label) {
171726c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1718ad8374ffSToby Isaac       const PetscInt *points;
1719ad8374ffSToby Isaac 
17209566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
172126c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1722ad8374ffSToby Isaac         const PetscInt p = points[l];
17239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
172426c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
172526c55118SMichael Lange       }
17269566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
172726c55118SMichael Lange     }
172826c55118SMichael Lange   }
172926c55118SMichael Lange   /* Build SF that maps label points to remote processes */
17309566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
17319566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
17329566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
17339566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
173426c55118SMichael Lange   /* Send the strata for each point over the derived SF */
17359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
17369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
17379566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
17389566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
173926c55118SMichael Lange   /* Clean up */
17409566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
17419566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
17429566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
17439566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
1744*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
174526c55118SMichael Lange }
174626c55118SMichael Lange 
174784f0b6dfSMatthew G. Knepley /*@
174884f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
174984f0b6dfSMatthew G. Knepley 
17505b5e7992SMatthew G. Knepley   Collective on sf
17515b5e7992SMatthew G. Knepley 
175284f0b6dfSMatthew G. Knepley   Input Parameters:
175384f0b6dfSMatthew G. Knepley + label - the DMLabel
175484f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
175584f0b6dfSMatthew G. Knepley 
175684f0b6dfSMatthew G. Knepley   Output Parameter:
175784f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
175884f0b6dfSMatthew G. Knepley 
175984f0b6dfSMatthew G. Knepley   Level: intermediate
176084f0b6dfSMatthew G. Knepley 
1761db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
176284f0b6dfSMatthew G. Knepley @*/
1763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1764d71ae5a4SJacob Faibussowitsch {
1765c58f1c22SToby Isaac   MPI_Comm     comm;
176626c55118SMichael Lange   PetscSection leafSection;
176726c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
176826c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1769ad8374ffSToby Isaac   PetscInt   **points;
1770d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1771c58f1c22SToby Isaac   char        *name;
1772c58f1c22SToby Isaac   PetscInt     nameSize;
1773e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1774c58f1c22SToby Isaac   size_t       len = 0;
177526c55118SMichael Lange   PetscMPIInt  rank;
1776c58f1c22SToby Isaac 
1777c58f1c22SToby Isaac   PetscFunctionBegin;
1778d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1779f018e600SMatthew G. Knepley   if (label) {
1780f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17819f6c5813SMatthew G. Knepley     PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
17829566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1783f018e600SMatthew G. Knepley   }
17849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1786c58f1c22SToby Isaac   /* Bcast name */
1787dd400576SPatrick Sanan   if (rank == 0) {
17889566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
17899566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1790d67d17b1SMatthew G. Knepley   }
1791c58f1c22SToby Isaac   nameSize = len;
17929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
17949566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
17959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
17969566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17979566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
179877d236dfSMichael Lange   /* Bcast defaultValue */
1799dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
18009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
180126c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
18029566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
18035cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
18049566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
18059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
18069566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
18079566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
18089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1809ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
18109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
18115cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
18125cbdf6fcSMichael Lange   offset = 0;
18139566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
18149566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
181548a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
18165cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1817231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
18189371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
18199371c9d4SSatish Balay         leafStrata[p] = s;
18209371c9d4SSatish Balay         break;
18219371c9d4SSatish Balay       }
18225cbdf6fcSMichael Lange     }
18235cbdf6fcSMichael Lange   }
1824c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
18259566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
18269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1827c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
18289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
18299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1830ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1831c58f1c22SToby Isaac   }
18329566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
18339f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->points));
18349f6c5813SMatthew G. Knepley   PetscCall(PetscCalloc1((*labelNew)->numStrata, &points));
1835c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
18369566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
18379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1838c58f1c22SToby Isaac   }
1839c58f1c22SToby Isaac   /* Insert points into new strata */
18409566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
18419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1842c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
18439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
18449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1845c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1846c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1847ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1848c58f1c22SToby Isaac     }
1849c58f1c22SToby Isaac   }
1850ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
18519566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &(points[s][0]), PETSC_OWN_POINTER, &((*labelNew)->points[s])));
18529566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1853ad8374ffSToby Isaac   }
18549566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
18559566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
18569566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
18579566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
18589566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
1859*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1860c58f1c22SToby Isaac }
1861c58f1c22SToby Isaac 
18627937d9ceSMichael Lange /*@
18637937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
18647937d9ceSMichael Lange 
18655b5e7992SMatthew G. Knepley   Collective on sf
18665b5e7992SMatthew G. Knepley 
18677937d9ceSMichael Lange   Input Parameters:
18687937d9ceSMichael Lange + label - the DMLabel
186984f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
18707937d9ceSMichael Lange 
187184f0b6dfSMatthew G. Knepley   Output Parameters:
187284f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
18737937d9ceSMichael Lange 
18747937d9ceSMichael Lange   Level: developer
18757937d9ceSMichael Lange 
18767937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
18777937d9ceSMichael Lange 
1878db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
18797937d9ceSMichael Lange @*/
1880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
1881d71ae5a4SJacob Faibussowitsch {
18827937d9ceSMichael Lange   MPI_Comm        comm;
18837937d9ceSMichael Lange   PetscSection    rootSection;
18847937d9ceSMichael Lange   PetscSF         sfLabel;
18857937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
18867937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18877937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18887937d9ceSMichael Lange   PetscInt       *rootStrata;
1889d67d17b1SMatthew G. Knepley   const char     *lname;
18907937d9ceSMichael Lange   char           *name;
18917937d9ceSMichael Lange   PetscInt        nameSize;
18927937d9ceSMichael Lange   size_t          len = 0;
18939852e123SBarry Smith   PetscMPIInt     rank, size;
18947937d9ceSMichael Lange 
18957937d9ceSMichael Lange   PetscFunctionBegin;
1896d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1897d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
18989f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
18999566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
19009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
19019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
19027937d9ceSMichael Lange   /* Bcast name */
1903dd400576SPatrick Sanan   if (rank == 0) {
19049566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
19059566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1906d67d17b1SMatthew G. Knepley   }
19077937d9ceSMichael Lange   nameSize = len;
19089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
19099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
19109566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
19119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
19129566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
19139566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
19147937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
19157937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
19167937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
19179566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
19189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1919dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
19207937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
19218212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
19228212dd46SStefano Zampini 
19238212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
19248212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
19257937d9ceSMichael Lange   }
19269566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
19279566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
19287937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
19299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
19309566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
19319566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
19329566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
19339566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
19347937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
19359566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
19367937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
19377937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
19387937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
19399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
19409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
19419566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
19427937d9ceSMichael Lange     }
19437937d9ceSMichael Lange     idx += rootDegree[p];
19447937d9ceSMichael Lange   }
19459566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
19469566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
19479566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
19489566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
1949*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19507937d9ceSMichael Lange }
19517937d9ceSMichael Lange 
1952d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1953d71ae5a4SJacob Faibussowitsch {
1954d42890abSMatthew G. Knepley   const PetscInt *degree;
1955d42890abSMatthew G. Knepley   const PetscInt *points;
1956d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1957d42890abSMatthew G. Knepley 
1958d42890abSMatthew G. Knepley   PetscFunctionBegin;
1959d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1960d42890abSMatthew G. Knepley   /* Add in leaves */
1961d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1962d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1963d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1964d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1965d42890abSMatthew G. Knepley   }
1966d42890abSMatthew G. Knepley   /* Add in shared roots */
1967d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1968d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1969d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1970d42890abSMatthew G. Knepley     if (degree[r]) {
1971d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1972d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1973d42890abSMatthew G. Knepley     }
1974d42890abSMatthew G. Knepley   }
1975*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1976d42890abSMatthew G. Knepley }
1977d42890abSMatthew G. Knepley 
1978d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1979d71ae5a4SJacob Faibussowitsch {
1980d42890abSMatthew G. Knepley   const PetscInt *degree;
1981d42890abSMatthew G. Knepley   const PetscInt *points;
1982d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1983d42890abSMatthew G. Knepley 
1984d42890abSMatthew G. Knepley   PetscFunctionBegin;
1985d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1986d42890abSMatthew G. Knepley   /* Read out leaves */
1987d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1988d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1989d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1990d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1991d42890abSMatthew G. Knepley 
1992d42890abSMatthew G. Knepley     if (cval != defVal) {
1993d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1994d42890abSMatthew G. Knepley       if (val == defVal) {
1995d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
199648a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
1997d42890abSMatthew G. Knepley       }
1998d42890abSMatthew G. Knepley     }
1999d42890abSMatthew G. Knepley   }
2000d42890abSMatthew G. Knepley   /* Read out shared roots */
2001d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
2002d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
2003d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
2004d42890abSMatthew G. Knepley     if (degree[r]) {
2005d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
2006d42890abSMatthew G. Knepley 
2007d42890abSMatthew G. Knepley       if (cval != defVal) {
2008d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
2009d42890abSMatthew G. Knepley         if (val == defVal) {
2010d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
201148a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
2012d42890abSMatthew G. Knepley         }
2013d42890abSMatthew G. Knepley       }
2014d42890abSMatthew G. Knepley     }
2015d42890abSMatthew G. Knepley   }
2016*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2017d42890abSMatthew G. Knepley }
2018d42890abSMatthew G. Knepley 
2019d42890abSMatthew G. Knepley /*@
2020d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
2021d42890abSMatthew G. Knepley 
2022d42890abSMatthew G. Knepley   Collective on sf
2023d42890abSMatthew G. Knepley 
2024d42890abSMatthew G. Knepley   Input Parameters:
2025d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
2026d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
2027d42890abSMatthew G. Knepley 
2028d42890abSMatthew G. Knepley   Level: intermediate
2029d42890abSMatthew G. Knepley 
2030db781477SPatrick Sanan .seealso: `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
2031d42890abSMatthew G. Knepley @*/
2032d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
2033d71ae5a4SJacob Faibussowitsch {
2034d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
2035d42890abSMatthew G. Knepley   PetscMPIInt size;
2036d42890abSMatthew G. Knepley 
2037d42890abSMatthew G. Knepley   PetscFunctionBegin;
20389f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2039d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
2040d42890abSMatthew G. Knepley   if (size > 1) {
2041d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
2042d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
2043d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
2044d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
2045d42890abSMatthew G. Knepley   }
2046*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2047d42890abSMatthew G. Knepley }
2048d42890abSMatthew G. Knepley 
2049d42890abSMatthew G. Knepley /*@
2050d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
2051d42890abSMatthew G. Knepley 
2052d42890abSMatthew G. Knepley   Collective on sf
2053d42890abSMatthew G. Knepley 
2054d42890abSMatthew G. Knepley   Input Parameters:
2055d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
2056d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
2057d42890abSMatthew G. Knepley 
2058d42890abSMatthew G. Knepley   Level: intermediate
2059d42890abSMatthew G. Knepley 
2060db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
2061d42890abSMatthew G. Knepley @*/
2062d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
2063d71ae5a4SJacob Faibussowitsch {
2064d42890abSMatthew G. Knepley   PetscFunctionBegin;
20659f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2066d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
2067d42890abSMatthew G. Knepley   label->propArray = NULL;
2068*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2069d42890abSMatthew G. Knepley }
2070d42890abSMatthew G. Knepley 
2071d42890abSMatthew G. Knepley /*@C
2072d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2073d42890abSMatthew G. Knepley 
2074d42890abSMatthew G. Knepley   Collective on sf
2075d42890abSMatthew G. Knepley 
2076d42890abSMatthew G. Knepley   Input Parameters:
2077d42890abSMatthew G. Knepley + label     - The DMLabel to propagate across processes
2078d42890abSMatthew G. Knepley . sf        - The SF describing parallel layout of the label points
2079ef1023bdSBarry Smith . markPoint - An optional callback that is called when a point is marked, or NULL
2080d42890abSMatthew G. Knepley - ctx       - An optional user context for the callback, or NULL
2081d42890abSMatthew G. Knepley 
2082d42890abSMatthew G. Knepley   Calling sequence of markPoint:
2083d42890abSMatthew G. Knepley $ markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
2084d42890abSMatthew G. Knepley 
2085d42890abSMatthew G. Knepley + label - The DMLabel
2086d42890abSMatthew G. Knepley . p     - The point being marked
2087d42890abSMatthew G. Knepley . val   - The label value for p
2088d42890abSMatthew G. Knepley - ctx   - An optional user context
2089d42890abSMatthew G. Knepley 
2090d42890abSMatthew G. Knepley   Level: intermediate
2091d42890abSMatthew G. Knepley 
2092db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2093d42890abSMatthew G. Knepley @*/
2094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2095d71ae5a4SJacob Faibussowitsch {
2096c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2097d42890abSMatthew G. Knepley   PetscMPIInt size;
2098d42890abSMatthew G. Knepley 
2099d42890abSMatthew G. Knepley   PetscFunctionBegin;
21009f6c5813SMatthew G. Knepley   PetscCheck(!label->readonly, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_WRONG, "Read-only labels cannot be altered");
2101d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2102c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2103c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2104d42890abSMatthew G. Knepley     /* Communicate marked edges
2105d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2106d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2107d42890abSMatthew G. Knepley 
2108d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2109d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2110d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2111d42890abSMatthew G. Knepley 
2112d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2113d42890abSMatthew 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
2114d42890abSMatthew G. Knepley        edge to the queue.
2115d42890abSMatthew G. Knepley     */
2116d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2117d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2118d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2119d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2120d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2121d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2122d42890abSMatthew G. Knepley   }
2123*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2124d42890abSMatthew G. Knepley }
2125d42890abSMatthew G. Knepley 
212684f0b6dfSMatthew G. Knepley /*@
212784f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
212884f0b6dfSMatthew G. Knepley 
21295b5e7992SMatthew G. Knepley   Not collective
21305b5e7992SMatthew G. Knepley 
213184f0b6dfSMatthew G. Knepley   Input Parameter:
213284f0b6dfSMatthew G. Knepley . label - the DMLabel
213384f0b6dfSMatthew G. Knepley 
213484f0b6dfSMatthew G. Knepley   Output Parameters:
213584f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
213684f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
213784f0b6dfSMatthew G. Knepley 
213884f0b6dfSMatthew G. Knepley   Level: developer
213984f0b6dfSMatthew G. Knepley 
2140db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
214184f0b6dfSMatthew G. Knepley @*/
2142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2143d71ae5a4SJacob Faibussowitsch {
2144c58f1c22SToby Isaac   IS              vIS;
2145c58f1c22SToby Isaac   const PetscInt *values;
2146c58f1c22SToby Isaac   PetscInt       *points;
2147c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2148c58f1c22SToby Isaac 
2149c58f1c22SToby Isaac   PetscFunctionBegin;
2150d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
21519566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
21529566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
21539566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
21549371c9d4SSatish Balay   if (nV) {
21559371c9d4SSatish Balay     vS = values[0];
21569371c9d4SSatish Balay     vE = values[0] + 1;
21579371c9d4SSatish Balay   }
2158c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2159c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2160c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2161c58f1c22SToby Isaac   }
21629566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
21639566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2164c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2165c58f1c22SToby Isaac     PetscInt n;
2166c58f1c22SToby Isaac 
21679566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
21689566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2169c58f1c22SToby Isaac   }
21709566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
21719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
21729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2173c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2174c58f1c22SToby Isaac     IS              is;
2175c58f1c22SToby Isaac     const PetscInt *spoints;
2176c58f1c22SToby Isaac     PetscInt        dof, off, p;
2177c58f1c22SToby Isaac 
21789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
21799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
21809566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
21819566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2182c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
21839566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
21849566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2185c58f1c22SToby Isaac   }
21869566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
21879566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
21889566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
2189*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2190c58f1c22SToby Isaac }
2191c58f1c22SToby Isaac 
21929f6c5813SMatthew G. Knepley /*@C
21939f6c5813SMatthew G. Knepley   DMLabelRegister - Adds a new label component implementation
21949f6c5813SMatthew G. Knepley 
21959f6c5813SMatthew G. Knepley   Not Collective
21969f6c5813SMatthew G. Knepley 
21979f6c5813SMatthew G. Knepley   Input Parameters:
21989f6c5813SMatthew G. Knepley + name        - The name of a new user-defined creation routine
21999f6c5813SMatthew G. Knepley - create_func - The creation routine itself
22009f6c5813SMatthew G. Knepley 
22019f6c5813SMatthew G. Knepley   Notes:
22029f6c5813SMatthew G. Knepley   `DMLabelRegister()` may be called multiple times to add several user-defined labels
22039f6c5813SMatthew G. Knepley 
22049f6c5813SMatthew G. Knepley   Sample usage:
22059f6c5813SMatthew G. Knepley .vb
22069f6c5813SMatthew G. Knepley   DMLabelRegister("my_label", MyLabelCreate);
22079f6c5813SMatthew G. Knepley .ve
22089f6c5813SMatthew G. Knepley 
22099f6c5813SMatthew G. Knepley   Then, your label type can be chosen with the procedural interface via
22109f6c5813SMatthew G. Knepley .vb
22119f6c5813SMatthew G. Knepley   DMLabelCreate(MPI_Comm, DMLabel *);
22129f6c5813SMatthew G. Knepley   DMLabelSetType(DMLabel, "my_label");
22139f6c5813SMatthew G. Knepley .ve
22149f6c5813SMatthew G. Knepley   or at runtime via the option
22159f6c5813SMatthew G. Knepley .vb
22169f6c5813SMatthew G. Knepley   -dm_label_type my_label
22179f6c5813SMatthew G. Knepley .ve
22189f6c5813SMatthew G. Knepley 
22199f6c5813SMatthew G. Knepley   Level: advanced
22209f6c5813SMatthew G. Knepley 
22219f6c5813SMatthew G. Knepley .seealso: `DMLabel`, `DMLabelType`, `DMLabelRegisterAll()`, `DMLabelRegisterDestroy()`
22229f6c5813SMatthew G. Knepley @*/
22239f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegister(const char name[], PetscErrorCode (*create_func)(DMLabel))
22249f6c5813SMatthew G. Knepley {
22259f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22269f6c5813SMatthew G. Knepley   PetscCall(DMInitializePackage());
22279f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListAdd(&DMLabelList, name, create_func));
2228*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22299f6c5813SMatthew G. Knepley }
22309f6c5813SMatthew G. Knepley 
22319f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel);
22329f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Ephemeral(DMLabel);
22339f6c5813SMatthew G. Knepley 
22349f6c5813SMatthew G. Knepley /*@C
22359f6c5813SMatthew G. Knepley   DMLabelRegisterAll - Registers all of the `DMLabel` implementations in the `DM` package.
22369f6c5813SMatthew G. Knepley 
22379f6c5813SMatthew G. Knepley   Not Collective
22389f6c5813SMatthew G. Knepley 
22399f6c5813SMatthew G. Knepley   Level: advanced
22409f6c5813SMatthew G. Knepley 
22419f6c5813SMatthew G. Knepley .seealso: `DMRegisterAll()`, `DMLabelRegisterDestroy()`
22429f6c5813SMatthew G. Knepley @*/
22439f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterAll(void)
22449f6c5813SMatthew G. Knepley {
22459f6c5813SMatthew G. Knepley   PetscFunctionBegin;
2246*3ba16761SJacob Faibussowitsch   if (DMLabelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
22479f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_TRUE;
22489f6c5813SMatthew G. Knepley 
22499f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELCONCRETE, DMLabelCreate_Concrete));
22509f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegister(DMLABELEPHEMERAL, DMLabelCreate_Ephemeral));
2251*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22529f6c5813SMatthew G. Knepley }
22539f6c5813SMatthew G. Knepley 
22549f6c5813SMatthew G. Knepley /*@C
22559f6c5813SMatthew G. Knepley   DMLabelRegisterDestroy - This function destroys the `DMLabel` registry. It is called from `PetscFinalize()`.
22569f6c5813SMatthew G. Knepley 
22579f6c5813SMatthew G. Knepley   Level: developer
22589f6c5813SMatthew G. Knepley 
22599f6c5813SMatthew G. Knepley .seealso: `PetscInitialize()`
22609f6c5813SMatthew G. Knepley @*/
22619f6c5813SMatthew G. Knepley PetscErrorCode DMLabelRegisterDestroy(void)
22629f6c5813SMatthew G. Knepley {
22639f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22649f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListDestroy(&DMLabelList));
22659f6c5813SMatthew G. Knepley   DMLabelRegisterAllCalled = PETSC_FALSE;
2266*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22679f6c5813SMatthew G. Knepley }
22689f6c5813SMatthew G. Knepley 
22699f6c5813SMatthew G. Knepley /*@C
22709f6c5813SMatthew G. Knepley   DMLabelSetType - Sets the particular implementation for a label.
22719f6c5813SMatthew G. Knepley 
22729f6c5813SMatthew G. Knepley   Collective on tr
22739f6c5813SMatthew G. Knepley 
22749f6c5813SMatthew G. Knepley   Input Parameters:
22759f6c5813SMatthew G. Knepley + label  - The label
22769f6c5813SMatthew G. Knepley - method - The name of the label type
22779f6c5813SMatthew G. Knepley 
22789f6c5813SMatthew G. Knepley   Options Database Key:
22799f6c5813SMatthew G. Knepley . -dm_label_type <type> - Sets the label type; use -help for a list of available types
22809f6c5813SMatthew G. Knepley 
22819f6c5813SMatthew G. Knepley   Notes:
22829f6c5813SMatthew G. Knepley   See "petsc/include/petscdmlabel.h" for available label types
22839f6c5813SMatthew G. Knepley 
22849f6c5813SMatthew G. Knepley   Level: intermediate
22859f6c5813SMatthew G. Knepley 
22869f6c5813SMatthew G. Knepley .seealso: `DMLabelGetType()`, `DMLabelCreate()`
22879f6c5813SMatthew G. Knepley @*/
22889f6c5813SMatthew G. Knepley PetscErrorCode DMLabelSetType(DMLabel label, DMLabelType method)
22899f6c5813SMatthew G. Knepley {
22909f6c5813SMatthew G. Knepley   PetscErrorCode (*r)(DMLabel);
22919f6c5813SMatthew G. Knepley   PetscBool match;
22929f6c5813SMatthew G. Knepley 
22939f6c5813SMatthew G. Knepley   PetscFunctionBegin;
22949f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
22959f6c5813SMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)label, method, &match));
2296*3ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
22979f6c5813SMatthew G. Knepley 
22989f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
22999f6c5813SMatthew G. Knepley   PetscCall(PetscFunctionListFind(DMLabelList, method, &r));
23009f6c5813SMatthew G. Knepley   PetscCheck(r, PetscObjectComm((PetscObject)label), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMLabel type: %s", method);
23019f6c5813SMatthew G. Knepley 
23029f6c5813SMatthew G. Knepley   PetscTryTypeMethod(label, destroy);
23039f6c5813SMatthew G. Knepley   PetscCall(PetscMemzero(label->ops, sizeof(*label->ops)));
23049f6c5813SMatthew G. Knepley   PetscCall(PetscObjectChangeTypeName((PetscObject)label, method));
23059f6c5813SMatthew G. Knepley   PetscCall((*r)(label));
2306*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23079f6c5813SMatthew G. Knepley }
23089f6c5813SMatthew G. Knepley 
23099f6c5813SMatthew G. Knepley /*@C
23109f6c5813SMatthew G. Knepley   DMLabelGetType - Gets the type name (as a string) from the label.
23119f6c5813SMatthew G. Knepley 
23129f6c5813SMatthew G. Knepley   Not Collective
23139f6c5813SMatthew G. Knepley 
23149f6c5813SMatthew G. Knepley   Input Parameter:
23159f6c5813SMatthew G. Knepley . label  - The DMLabel
23169f6c5813SMatthew G. Knepley 
23179f6c5813SMatthew G. Knepley   Output Parameter:
23189f6c5813SMatthew G. Knepley . type - The DMLabel type name
23199f6c5813SMatthew G. Knepley 
23209f6c5813SMatthew G. Knepley   Level: intermediate
23219f6c5813SMatthew G. Knepley 
23229f6c5813SMatthew G. Knepley .seealso: `DMLabelSetType()`, `DMLabelCreate()`
23239f6c5813SMatthew G. Knepley @*/
23249f6c5813SMatthew G. Knepley PetscErrorCode DMLabelGetType(DMLabel label, DMLabelType *type)
23259f6c5813SMatthew G. Knepley {
23269f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23279f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
23289f6c5813SMatthew G. Knepley   PetscValidPointer(type, 2);
23299f6c5813SMatthew G. Knepley   PetscCall(DMLabelRegisterAll());
23309f6c5813SMatthew G. Knepley   *type = ((PetscObject)label)->type_name;
2331*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23329f6c5813SMatthew G. Knepley }
23339f6c5813SMatthew G. Knepley 
23349f6c5813SMatthew G. Knepley static PetscErrorCode DMLabelInitialize_Concrete(DMLabel label)
23359f6c5813SMatthew G. Knepley {
23369f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23379f6c5813SMatthew G. Knepley   label->ops->view         = DMLabelView_Concrete;
23389f6c5813SMatthew G. Knepley   label->ops->setup        = NULL;
23399f6c5813SMatthew G. Knepley   label->ops->duplicate    = DMLabelDuplicate_Concrete;
23409f6c5813SMatthew G. Knepley   label->ops->getstratumis = DMLabelGetStratumIS_Concrete;
2341*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23429f6c5813SMatthew G. Knepley }
23439f6c5813SMatthew G. Knepley 
23449f6c5813SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMLabelCreate_Concrete(DMLabel label)
23459f6c5813SMatthew G. Knepley {
23469f6c5813SMatthew G. Knepley   PetscFunctionBegin;
23479f6c5813SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
23489f6c5813SMatthew G. Knepley   PetscCall(DMLabelInitialize_Concrete(label));
2349*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23509f6c5813SMatthew G. Knepley }
23519f6c5813SMatthew G. Knepley 
235284f0b6dfSMatthew G. Knepley /*@
2353c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2354c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
2355c58f1c22SToby Isaac 
23565b5e7992SMatthew G. Knepley   Collective on sf
23575b5e7992SMatthew G. Knepley 
2358c58f1c22SToby Isaac   Input Parameters:
2359c58f1c22SToby Isaac + s - The PetscSection for the local field layout
2360c58f1c22SToby Isaac . sf - The SF describing parallel layout of the section points
2361c58f1c22SToby Isaac . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
2362c58f1c22SToby Isaac . label - The label specifying the points
2363c58f1c22SToby Isaac - labelValue - The label stratum specifying the points
2364c58f1c22SToby Isaac 
2365c58f1c22SToby Isaac   Output Parameter:
2366c58f1c22SToby Isaac . gsection - The PetscSection for the global field layout
2367c58f1c22SToby Isaac 
2368c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
2369c58f1c22SToby Isaac 
2370c58f1c22SToby Isaac   Level: developer
2371c58f1c22SToby Isaac 
2372db781477SPatrick Sanan .seealso: `PetscSectionCreate()`
2373c58f1c22SToby Isaac @*/
2374d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2375d71ae5a4SJacob Faibussowitsch {
2376c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2377c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2378c58f1c22SToby Isaac 
2379c58f1c22SToby Isaac   PetscFunctionBegin;
2380d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2381d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2382d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
23839566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
23849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
23859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
23869566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2387c58f1c22SToby Isaac   if (nroots >= 0) {
238863a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
23899566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2390c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
23919566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2392c58f1c22SToby Isaac     } else {
2393c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2394c58f1c22SToby Isaac     }
2395c58f1c22SToby Isaac   }
2396c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2397c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2398c58f1c22SToby Isaac     PetscInt value;
2399c58f1c22SToby Isaac 
24009566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2401c58f1c22SToby Isaac     if (value != labelValue) continue;
24029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
24039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
24049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
24059566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2406c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2407c58f1c22SToby Isaac   }
24089566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2409c58f1c22SToby Isaac   if (nroots >= 0) {
24109566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
24119566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2412c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
24139371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
24149371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
24159371c9d4SSatish Balay       }
2416c58f1c22SToby Isaac     }
2417c58f1c22SToby Isaac   }
241835cb6cd3SPierre Jolivet   /* Calculate new sizes, get process offset, and calculate point offsets */
2419c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2420c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2421c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2422c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2423c58f1c22SToby Isaac   }
24249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2425c58f1c22SToby Isaac   globalOff -= off;
2426c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2427c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2428c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2429c58f1c22SToby Isaac   }
2430c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2431c58f1c22SToby Isaac   if (nroots >= 0) {
24329566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
24339566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2434c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
24359371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
24369371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
24379371c9d4SSatish Balay       }
2438c58f1c22SToby Isaac     }
2439c58f1c22SToby Isaac   }
24409566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
24419566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
2442*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2443c58f1c22SToby Isaac }
2444c58f1c22SToby Isaac 
24459371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
24465fdea053SToby Isaac   DMLabel              label;
24475fdea053SToby Isaac   PetscCopyMode       *modes;
24485fdea053SToby Isaac   PetscInt            *sizes;
24495fdea053SToby Isaac   const PetscInt    ***perms;
24505fdea053SToby Isaac   const PetscScalar ***rots;
24515fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
24525fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
24535fdea053SToby Isaac } PetscSectionSym_Label;
24545fdea053SToby Isaac 
2455d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2456d71ae5a4SJacob Faibussowitsch {
24575fdea053SToby Isaac   PetscInt               i, j;
24585fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
24595fdea053SToby Isaac 
24605fdea053SToby Isaac   PetscFunctionBegin;
24615fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
24625fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
24635fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
24649566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
24659566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
24665fdea053SToby Isaac       }
24675fdea053SToby Isaac       if (sl->perms[i]) {
24685fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
24695fdea053SToby Isaac 
24709566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
24715fdea053SToby Isaac       }
24725fdea053SToby Isaac       if (sl->rots[i]) {
24735fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
24745fdea053SToby Isaac 
24759566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
24765fdea053SToby Isaac       }
24775fdea053SToby Isaac     }
24785fdea053SToby Isaac   }
24799566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
24809566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
24815fdea053SToby Isaac   sl->numStrata = 0;
2482*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24835fdea053SToby Isaac }
24845fdea053SToby Isaac 
2485d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2486d71ae5a4SJacob Faibussowitsch {
24875fdea053SToby Isaac   PetscFunctionBegin;
24889566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
24899566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
2490*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24915fdea053SToby Isaac }
24925fdea053SToby Isaac 
2493d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2494d71ae5a4SJacob Faibussowitsch {
24955fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
24965fdea053SToby Isaac   PetscBool              isAscii;
24975fdea053SToby Isaac   DMLabel                label = sl->label;
2498d67d17b1SMatthew G. Knepley   const char            *name;
24995fdea053SToby Isaac 
25005fdea053SToby Isaac   PetscFunctionBegin;
25019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
25025fdea053SToby Isaac   if (isAscii) {
25035fdea053SToby Isaac     PetscInt          i, j, k;
25045fdea053SToby Isaac     PetscViewerFormat format;
25055fdea053SToby Isaac 
25069566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
25075fdea053SToby Isaac     if (label) {
25089566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
25095fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
25109566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
25119566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
25129566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
25135fdea053SToby Isaac       } else {
25149566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
25159566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
25165fdea053SToby Isaac       }
25175fdea053SToby Isaac     } else {
25189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
25195fdea053SToby Isaac     }
25209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
25215fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
25225fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
25235fdea053SToby Isaac 
25245fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
252563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
25265fdea053SToby Isaac       } else {
252763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
25289566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
252963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
25305fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
25319566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
25325fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
25335fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
253463a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
25355fdea053SToby Isaac             } else {
25365fdea053SToby Isaac               PetscInt tab;
25375fdea053SToby Isaac 
253863a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
25399566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
25409566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
25415fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
25429566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
25439566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
254463a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
25459566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
25469566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
25475fdea053SToby Isaac               }
25485fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
25499566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
25509566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
25515fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
255263a3b9bcSJacob 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])));
25535fdea053SToby Isaac #else
255463a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
25555fdea053SToby Isaac #endif
25569566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
25579566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
25585fdea053SToby Isaac               }
25599566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
25605fdea053SToby Isaac             }
25615fdea053SToby Isaac           }
25629566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
25635fdea053SToby Isaac         }
25649566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
25655fdea053SToby Isaac       }
25665fdea053SToby Isaac     }
25679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
25685fdea053SToby Isaac   }
2569*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25705fdea053SToby Isaac }
25715fdea053SToby Isaac 
25725fdea053SToby Isaac /*@
25735fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
25745fdea053SToby Isaac 
25755fdea053SToby Isaac   Logically collective on sym
25765fdea053SToby Isaac 
25775fdea053SToby Isaac   Input parameters:
25785fdea053SToby Isaac + sym - the section symmetries
25795fdea053SToby Isaac - label - the DMLabel describing the types of points
25805fdea053SToby Isaac 
25815fdea053SToby Isaac   Level: developer:
25825fdea053SToby Isaac 
2583db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
25845fdea053SToby Isaac @*/
2585d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2586d71ae5a4SJacob Faibussowitsch {
25875fdea053SToby Isaac   PetscSectionSym_Label *sl;
25885fdea053SToby Isaac 
25895fdea053SToby Isaac   PetscFunctionBegin;
25905fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
25915fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
25929566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
25935fdea053SToby Isaac   if (label) {
25945fdea053SToby Isaac     sl->label = label;
25959566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
25969566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
25979566063dSJacob 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));
25989566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
25999566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
26009566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
26019566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
26029566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
26035fdea053SToby Isaac   }
2604*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26055fdea053SToby Isaac }
26065fdea053SToby Isaac 
26075fdea053SToby Isaac /*@C
2608b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2609b004864fSMatthew G. Knepley 
2610b004864fSMatthew G. Knepley   Logically collective on sym
2611b004864fSMatthew G. Knepley 
2612b004864fSMatthew G. Knepley   Input Parameters:
2613b004864fSMatthew G. Knepley + sym       - the section symmetries
2614b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2615b004864fSMatthew G. Knepley 
2616b004864fSMatthew G. Knepley   Output Parameters:
2617b004864fSMatthew G. Knepley + size      - the number of dofs for points in the stratum of the label
2618b004864fSMatthew G. Knepley . minOrient - the smallest orientation for a point in this stratum
2619b004864fSMatthew G. Knepley . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2620b004864fSMatthew G. Knepley . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2621b004864fSMatthew G. Knepley - 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
2622b004864fSMatthew G. Knepley 
2623b004864fSMatthew G. Knepley   Level: developer
2624b004864fSMatthew G. Knepley 
2625db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2626b004864fSMatthew G. Knepley @*/
2627d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2628d71ae5a4SJacob Faibussowitsch {
2629b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2630b004864fSMatthew G. Knepley   const char            *name;
2631b004864fSMatthew G. Knepley   PetscInt               i;
2632b004864fSMatthew G. Knepley 
2633b004864fSMatthew G. Knepley   PetscFunctionBegin;
2634b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2635b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2636b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2637b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2638b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2639b004864fSMatthew G. Knepley 
2640b004864fSMatthew G. Knepley     if (stratum == value) break;
2641b004864fSMatthew G. Knepley   }
26429566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2643b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
26449371c9d4SSatish Balay   if (size) {
26459371c9d4SSatish Balay     PetscValidIntPointer(size, 3);
26469371c9d4SSatish Balay     *size = sl->sizes[i];
26479371c9d4SSatish Balay   }
26489371c9d4SSatish Balay   if (minOrient) {
26499371c9d4SSatish Balay     PetscValidIntPointer(minOrient, 4);
26509371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
26519371c9d4SSatish Balay   }
26529371c9d4SSatish Balay   if (maxOrient) {
26539371c9d4SSatish Balay     PetscValidIntPointer(maxOrient, 5);
26549371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
26559371c9d4SSatish Balay   }
26569371c9d4SSatish Balay   if (perms) {
26579371c9d4SSatish Balay     PetscValidPointer(perms, 6);
26589371c9d4SSatish Balay     *perms = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;
26599371c9d4SSatish Balay   }
26609371c9d4SSatish Balay   if (rots) {
26619371c9d4SSatish Balay     PetscValidPointer(rots, 7);
26629371c9d4SSatish Balay     *rots = sl->rots[i] ? &sl->rots[i][sl->minMaxOrients[i][0]] : NULL;
26639371c9d4SSatish Balay   }
2664*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2665b004864fSMatthew G. Knepley }
2666b004864fSMatthew G. Knepley 
2667b004864fSMatthew G. Knepley /*@C
26685fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
26695fdea053SToby Isaac 
26705b5e7992SMatthew G. Knepley   Logically collective on sym
26715fdea053SToby Isaac 
26725fdea053SToby Isaac   InputParameters:
26735b5e7992SMatthew G. Knepley + sym       - the section symmetries
26745fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
26755fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
26765fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
26775fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
26785fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
26795fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2680a2b725a8SWilliam Gropp - 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
26815fdea053SToby Isaac 
26825fdea053SToby Isaac   Level: developer
26835fdea053SToby Isaac 
2684db781477SPatrick Sanan .seealso: `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
26855fdea053SToby Isaac @*/
2686d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2687d71ae5a4SJacob Faibussowitsch {
26885fdea053SToby Isaac   PetscSectionSym_Label *sl;
2689d67d17b1SMatthew G. Knepley   const char            *name;
2690d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
26915fdea053SToby Isaac 
26925fdea053SToby Isaac   PetscFunctionBegin;
26935fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
26945fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2695b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
26965fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
26975fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
26985fdea053SToby Isaac 
26995fdea053SToby Isaac     if (stratum == value) break;
27005fdea053SToby Isaac   }
27019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
270263a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
27035fdea053SToby Isaac   sl->sizes[i]            = size;
27045fdea053SToby Isaac   sl->modes[i]            = mode;
27055fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
27065fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
27075fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
27085fdea053SToby Isaac     if (perms) {
27095fdea053SToby Isaac       PetscInt **ownPerms;
27105fdea053SToby Isaac 
27119566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
27125fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
27135fdea053SToby Isaac         if (perms[j]) {
27149566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2715ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
27165fdea053SToby Isaac         }
27175fdea053SToby Isaac       }
27185fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
27195fdea053SToby Isaac     }
27205fdea053SToby Isaac     if (rots) {
27215fdea053SToby Isaac       PetscScalar **ownRots;
27225fdea053SToby Isaac 
27239566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
27245fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
27255fdea053SToby Isaac         if (rots[j]) {
27269566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2727ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
27285fdea053SToby Isaac         }
27295fdea053SToby Isaac       }
27305fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
27315fdea053SToby Isaac     }
27325fdea053SToby Isaac   } else {
27335fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
27345fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
27355fdea053SToby Isaac   }
2736*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27375fdea053SToby Isaac }
27385fdea053SToby Isaac 
2739d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2740d71ae5a4SJacob Faibussowitsch {
27415fdea053SToby Isaac   PetscInt               i, j, numStrata;
27425fdea053SToby Isaac   PetscSectionSym_Label *sl;
27435fdea053SToby Isaac   DMLabel                label;
27445fdea053SToby Isaac 
27455fdea053SToby Isaac   PetscFunctionBegin;
27465fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
27475fdea053SToby Isaac   numStrata = sl->numStrata;
27485fdea053SToby Isaac   label     = sl->label;
27495fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
27505fdea053SToby Isaac     PetscInt point = points[2 * i];
27515fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
27525fdea053SToby Isaac 
27535fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
27545fdea053SToby Isaac       if (label->validIS[j]) {
27555fdea053SToby Isaac         PetscInt k;
27565fdea053SToby Isaac 
27579566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j], point, &k));
27585fdea053SToby Isaac         if (k >= 0) break;
27595fdea053SToby Isaac       } else {
27605fdea053SToby Isaac         PetscBool has;
27615fdea053SToby Isaac 
27629566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
27635fdea053SToby Isaac         if (has) break;
27645fdea053SToby Isaac       }
27655fdea053SToby Isaac     }
27669371c9d4SSatish 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],
27679371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2768ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2769ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
27705fdea053SToby Isaac   }
2771*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27725fdea053SToby Isaac }
27735fdea053SToby Isaac 
2774d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2775d71ae5a4SJacob Faibussowitsch {
2776b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2777b004864fSMatthew G. Knepley   IS                     valIS;
2778b004864fSMatthew G. Knepley   const PetscInt        *values;
2779b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2780b004864fSMatthew G. Knepley 
2781b004864fSMatthew G. Knepley   PetscFunctionBegin;
27829566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
27839566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
27849566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2785b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2786b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2787b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2788b004864fSMatthew G. Knepley     const PetscInt    **perms;
2789b004864fSMatthew G. Knepley     const PetscScalar **rots;
2790b004864fSMatthew G. Knepley 
27919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
27929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2793b004864fSMatthew G. Knepley   }
27949566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
2795*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2796b004864fSMatthew G. Knepley }
2797b004864fSMatthew G. Knepley 
2798d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2799d71ae5a4SJacob Faibussowitsch {
2800b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2801b004864fSMatthew G. Knepley   DMLabel                dlabel;
2802b004864fSMatthew G. Knepley 
2803b004864fSMatthew G. Knepley   PetscFunctionBegin;
28049566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
28059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
28069566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
28079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
2808*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2809b004864fSMatthew G. Knepley }
2810b004864fSMatthew G. Knepley 
2811d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2812d71ae5a4SJacob Faibussowitsch {
28135fdea053SToby Isaac   PetscSectionSym_Label *sl;
28145fdea053SToby Isaac 
28155fdea053SToby Isaac   PetscFunctionBegin;
28164dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
28175fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2818b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2819b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
28205fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
28215fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
28225fdea053SToby Isaac   sym->data            = (void *)sl;
2823*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28245fdea053SToby Isaac }
28255fdea053SToby Isaac 
28265fdea053SToby Isaac /*@
28275fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
28285fdea053SToby Isaac 
28295fdea053SToby Isaac   Collective
28305fdea053SToby Isaac 
28315fdea053SToby Isaac   Input Parameters:
28325fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
28335fdea053SToby Isaac - label - the label defining the strata
28345fdea053SToby Isaac 
28355fdea053SToby Isaac   Output Parameters:
28365fdea053SToby Isaac . sym - the section symmetries
28375fdea053SToby Isaac 
28385fdea053SToby Isaac   Level: developer
28395fdea053SToby Isaac 
2840db781477SPatrick Sanan .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
28415fdea053SToby Isaac @*/
2842d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2843d71ae5a4SJacob Faibussowitsch {
28445fdea053SToby Isaac   PetscFunctionBegin;
28459566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
28469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
28479566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
28489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
2849*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28505fdea053SToby Isaac }
2851