xref: /petsc/src/dm/label/dmlabel.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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 
7c58f1c22SToby Isaac /*@C
8c58f1c22SToby Isaac   DMLabelCreate - Create a DMLabel object, which is a multimap
9c58f1c22SToby Isaac 
105b5e7992SMatthew G. Knepley   Collective
115b5e7992SMatthew G. Knepley 
12d67d17b1SMatthew G. Knepley   Input parameters:
13d67d17b1SMatthew G. Knepley + comm - The communicator, usually PETSC_COMM_SELF
14d67d17b1SMatthew G. Knepley - name - The label name
15c58f1c22SToby Isaac 
16c58f1c22SToby Isaac   Output parameter:
17c58f1c22SToby Isaac . label - The DMLabel
18c58f1c22SToby Isaac 
19c58f1c22SToby Isaac   Level: beginner
20c58f1c22SToby Isaac 
2105ab7a9fSVaclav Hapla   Notes:
2205ab7a9fSVaclav Hapla   The label name is actually usual PetscObject name.
2305ab7a9fSVaclav Hapla   One can get/set it with PetscObjectGetName()/PetscObjectSetName().
2405ab7a9fSVaclav Hapla 
25db781477SPatrick Sanan .seealso: `DMLabelDestroy()`
26c58f1c22SToby Isaac @*/
27d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
28d71ae5a4SJacob Faibussowitsch {
29c58f1c22SToby Isaac   PetscFunctionBegin;
30064a246eSJacob Faibussowitsch   PetscValidPointer(label, 3);
319566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
32c58f1c22SToby Isaac 
339566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*label, DMLABEL_CLASSID, "DMLabel", "DMLabel", "DM", comm, DMLabelDestroy, DMLabelView));
34d67d17b1SMatthew G. Knepley 
35c58f1c22SToby Isaac   (*label)->numStrata     = 0;
365aa44df4SToby Isaac   (*label)->defaultValue  = -1;
37c58f1c22SToby Isaac   (*label)->stratumValues = NULL;
38ad8374ffSToby Isaac   (*label)->validIS       = NULL;
39c58f1c22SToby Isaac   (*label)->stratumSizes  = NULL;
40c58f1c22SToby Isaac   (*label)->points        = NULL;
41c58f1c22SToby Isaac   (*label)->ht            = NULL;
42c58f1c22SToby Isaac   (*label)->pStart        = -1;
43c58f1c22SToby Isaac   (*label)->pEnd          = -1;
44c58f1c22SToby Isaac   (*label)->bt            = NULL;
459566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*label, name));
47c58f1c22SToby Isaac   PetscFunctionReturn(0);
48c58f1c22SToby Isaac }
49c58f1c22SToby Isaac 
50c58f1c22SToby Isaac /*
51c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
52c58f1c22SToby Isaac 
535b5e7992SMatthew G. Knepley   Not collective
545b5e7992SMatthew G. Knepley 
55c58f1c22SToby Isaac   Input parameter:
56c58f1c22SToby Isaac + label - The DMLabel
57c58f1c22SToby Isaac - v - The stratum value
58c58f1c22SToby Isaac 
59c58f1c22SToby Isaac   Output parameter:
60c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
61c58f1c22SToby Isaac 
62c58f1c22SToby Isaac   Level: developer
63c58f1c22SToby Isaac 
64db781477SPatrick Sanan .seealso: `DMLabelCreate()`
65c58f1c22SToby Isaac */
66d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
67d71ae5a4SJacob Faibussowitsch {
68277ea44aSLisandro Dalcin   IS       is;
69b9907514SLisandro Dalcin   PetscInt off = 0, *pointArray, p;
70c58f1c22SToby Isaac 
71b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
72c58f1c22SToby Isaac   PetscFunctionBegin;
731dca8a05SBarry 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);
749566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
769566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
779566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
789566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
79c58f1c22SToby Isaac   if (label->bt) {
80c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
81ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
8263a3b9bcSJacob 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);
839566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
84c58f1c22SToby Isaac     }
85c58f1c22SToby Isaac   }
86ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v] - 1] == pointArray[0] + label->stratumSizes[v] - 1) {
879566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
889566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
89ba2698f1SMatthew G. Knepley   } else {
909566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
91ba2698f1SMatthew G. Knepley   }
929566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)is, "indices"));
93277ea44aSLisandro Dalcin   label->points[v]  = is;
94ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
959566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
96c58f1c22SToby Isaac   PetscFunctionReturn(0);
97c58f1c22SToby Isaac }
98c58f1c22SToby Isaac 
99c58f1c22SToby Isaac /*
100c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
101c58f1c22SToby Isaac 
1025b5e7992SMatthew G. Knepley   Not collective
1035b5e7992SMatthew G. Knepley 
104c58f1c22SToby Isaac   Input parameter:
105c58f1c22SToby Isaac . label - The DMLabel
106c58f1c22SToby Isaac 
107c58f1c22SToby Isaac   Output parameter:
108c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
109c58f1c22SToby Isaac 
110c58f1c22SToby Isaac   Level: developer
111c58f1c22SToby Isaac 
112db781477SPatrick Sanan .seealso: `DMLabelCreate()`
113c58f1c22SToby Isaac */
114d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
115d71ae5a4SJacob Faibussowitsch {
116c58f1c22SToby Isaac   PetscInt v;
117c58f1c22SToby Isaac 
118c58f1c22SToby Isaac   PetscFunctionBegin;
11948a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeValid_Private(label, v));
120c58f1c22SToby Isaac   PetscFunctionReturn(0);
121c58f1c22SToby Isaac }
122c58f1c22SToby Isaac 
123c58f1c22SToby Isaac /*
124c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
125c58f1c22SToby Isaac 
1265b5e7992SMatthew G. Knepley   Not collective
1275b5e7992SMatthew G. Knepley 
128c58f1c22SToby Isaac   Input parameter:
129c58f1c22SToby Isaac + label - The DMLabel
130c58f1c22SToby Isaac - v - The stratum value
131c58f1c22SToby Isaac 
132c58f1c22SToby Isaac   Output parameter:
133c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
134c58f1c22SToby Isaac 
135c58f1c22SToby Isaac   Level: developer
136c58f1c22SToby Isaac 
137db781477SPatrick Sanan .seealso: `DMLabelCreate()`
138c58f1c22SToby Isaac */
139d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
140d71ae5a4SJacob Faibussowitsch {
141c58f1c22SToby Isaac   PetscInt        p;
142ad8374ffSToby Isaac   const PetscInt *points;
143c58f1c22SToby Isaac 
144b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
145c58f1c22SToby Isaac   PetscFunctionBegin;
1461dca8a05SBarry 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);
147ad8374ffSToby Isaac   if (label->points[v]) {
1489566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
14948a46eb9SPierre Jolivet     for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
1509566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
1519566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&(label->points[v])));
152ad8374ffSToby Isaac   }
153ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
154c58f1c22SToby Isaac   PetscFunctionReturn(0);
155c58f1c22SToby Isaac }
156c58f1c22SToby Isaac 
157d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelMakeAllInvalid_Internal(DMLabel label)
158d71ae5a4SJacob Faibussowitsch {
159695799ffSMatthew G. Knepley   PetscInt v;
160695799ffSMatthew G. Knepley 
161695799ffSMatthew G. Knepley   PetscFunctionBegin;
16248a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeInvalid_Private(label, v));
163695799ffSMatthew G. Knepley   PetscFunctionReturn(0);
164695799ffSMatthew G. Knepley }
165695799ffSMatthew G. Knepley 
166b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
167b9907514SLisandro Dalcin   #define DMLABEL_LOOKUP_THRESHOLD 16
168b9907514SLisandro Dalcin #endif
169b9907514SLisandro Dalcin 
170d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
171d71ae5a4SJacob Faibussowitsch {
1720c3c4a36SLisandro Dalcin   PetscInt v;
1730e79e033SBarry Smith 
1740c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1750e79e033SBarry Smith   *index = -1;
176b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
177b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
1789371c9d4SSatish Balay       if (label->stratumValues[v] == value) {
1799371c9d4SSatish Balay         *index = v;
1809371c9d4SSatish Balay         break;
1819371c9d4SSatish Balay       }
182b9907514SLisandro Dalcin   } else {
1839566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(label->hmap, value, index));
1840e79e033SBarry Smith   }
18576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */
18690e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
1879566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(label->hmap, &len));
18808401ef6SPierre Jolivet     PetscCheck(len == label->numStrata, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
18990e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
1909566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(label->hmap, value, &loc));
19190e9b2aeSLisandro Dalcin     } else {
19290e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
1939371c9d4SSatish Balay         if (label->stratumValues[v] == value) {
1949371c9d4SSatish Balay           loc = v;
1959371c9d4SSatish Balay           break;
1969371c9d4SSatish Balay         }
19790e9b2aeSLisandro Dalcin     }
19808401ef6SPierre Jolivet     PetscCheck(loc == *index, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
19990e9b2aeSLisandro Dalcin   }
2000c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2010c3c4a36SLisandro Dalcin }
2020c3c4a36SLisandro Dalcin 
203d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
204d71ae5a4SJacob Faibussowitsch {
205b9907514SLisandro Dalcin   PetscInt    v;
206b9907514SLisandro Dalcin   PetscInt   *tmpV;
207b9907514SLisandro Dalcin   PetscInt   *tmpS;
208b9907514SLisandro Dalcin   PetscHSetI *tmpH, ht;
209b9907514SLisandro Dalcin   IS         *tmpP, is;
210c58f1c22SToby Isaac   PetscBool  *tmpB;
211b9907514SLisandro Dalcin   PetscHMapI  hmap = label->hmap;
212c58f1c22SToby Isaac 
213c58f1c22SToby Isaac   PetscFunctionBegin;
214b9907514SLisandro Dalcin   v    = label->numStrata;
215b9907514SLisandro Dalcin   tmpV = label->stratumValues;
216b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
217b9907514SLisandro Dalcin   tmpH = label->ht;
218b9907514SLisandro Dalcin   tmpP = label->points;
219b9907514SLisandro Dalcin   tmpB = label->validIS;
2208e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2218e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2228e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2238e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2248e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2258e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2269566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpV), &tmpV));
2279566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpS), &tmpS));
2289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpH), &tmpH));
2299566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpP), &tmpP));
2309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpB), &tmpB));
2319566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpV, oldV, v));
2329566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpS, oldS, v));
2339566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpH, oldH, v));
2349566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpP, oldP, v));
2359566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpB, oldB, v));
2369566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldV));
2379566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldS));
2389566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldH));
2399566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldP));
2409566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldB));
2418e1f8cf0SLisandro Dalcin   }
242b9907514SLisandro Dalcin   label->numStrata     = v + 1;
243c58f1c22SToby Isaac   label->stratumValues = tmpV;
244c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
245c58f1c22SToby Isaac   label->ht            = tmpH;
246c58f1c22SToby Isaac   label->points        = tmpP;
247ad8374ffSToby Isaac   label->validIS       = tmpB;
2489566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
2499566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
2509566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(hmap, value, v));
251b9907514SLisandro Dalcin   tmpV[v] = value;
252b9907514SLisandro Dalcin   tmpS[v] = 0;
253b9907514SLisandro Dalcin   tmpH[v] = ht;
254b9907514SLisandro Dalcin   tmpP[v] = is;
255b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
2569566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
2570c3c4a36SLisandro Dalcin   *index = v;
2580c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2590c3c4a36SLisandro Dalcin }
2600c3c4a36SLisandro Dalcin 
261d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
262d71ae5a4SJacob Faibussowitsch {
263b9907514SLisandro Dalcin   PetscFunctionBegin;
2649566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, index));
2659566063dSJacob Faibussowitsch   if (*index < 0) PetscCall(DMLabelNewStratum(label, value, index));
266b9907514SLisandro Dalcin   PetscFunctionReturn(0);
267b9907514SLisandro Dalcin }
268b9907514SLisandro Dalcin 
269d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
270d71ae5a4SJacob Faibussowitsch {
2719e63cc69SVaclav Hapla   PetscFunctionBegin;
2729e63cc69SVaclav Hapla   *size = 0;
2739e63cc69SVaclav Hapla   if (v < 0) PetscFunctionReturn(0);
2749e63cc69SVaclav Hapla   if (label->validIS[v]) {
2759e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
2769e63cc69SVaclav Hapla   } else {
2779566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(label->ht[v], size));
2789e63cc69SVaclav Hapla   }
2799e63cc69SVaclav Hapla   PetscFunctionReturn(0);
2809e63cc69SVaclav Hapla }
2819e63cc69SVaclav Hapla 
282b9907514SLisandro Dalcin /*@
283b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
284b9907514SLisandro Dalcin 
285d8d19677SJose E. Roman   Input Parameters:
286b9907514SLisandro Dalcin + label - The DMLabel
287b9907514SLisandro Dalcin - value - The stratum value
288b9907514SLisandro Dalcin 
289b9907514SLisandro Dalcin   Level: beginner
290b9907514SLisandro Dalcin 
291db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
292b9907514SLisandro Dalcin @*/
293d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
294d71ae5a4SJacob Faibussowitsch {
2950c3c4a36SLisandro Dalcin   PetscInt v;
2960c3c4a36SLisandro Dalcin 
2970c3c4a36SLisandro Dalcin   PetscFunctionBegin;
298d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2999566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
300b9907514SLisandro Dalcin   PetscFunctionReturn(0);
301b9907514SLisandro Dalcin }
302b9907514SLisandro Dalcin 
303b9907514SLisandro Dalcin /*@
304b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
305b9907514SLisandro Dalcin 
3065b5e7992SMatthew G. Knepley   Not collective
3075b5e7992SMatthew G. Knepley 
308d8d19677SJose E. Roman   Input Parameters:
309b9907514SLisandro Dalcin + label - The DMLabel
310b9907514SLisandro Dalcin . numStrata - The number of stratum values
311b9907514SLisandro Dalcin - stratumValues - The stratum values
312b9907514SLisandro Dalcin 
313b9907514SLisandro Dalcin   Level: beginner
314b9907514SLisandro Dalcin 
315db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
316b9907514SLisandro Dalcin @*/
317d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
318d71ae5a4SJacob Faibussowitsch {
319b9907514SLisandro Dalcin   PetscInt *values, v;
320b9907514SLisandro Dalcin 
321b9907514SLisandro Dalcin   PetscFunctionBegin;
322b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
323b9907514SLisandro Dalcin   if (numStrata) PetscValidIntPointer(stratumValues, 3);
3249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numStrata, &values));
3259566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(values, stratumValues, numStrata));
3269566063dSJacob Faibussowitsch   PetscCall(PetscSortRemoveDupsInt(&numStrata, values));
327b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
328b9907514SLisandro Dalcin     PetscInt   *tmpV;
329b9907514SLisandro Dalcin     PetscInt   *tmpS;
330b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
331b9907514SLisandro Dalcin     IS         *tmpP, is;
332b9907514SLisandro Dalcin     PetscBool  *tmpB;
333b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
334b9907514SLisandro Dalcin 
3359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpV));
3369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpS));
3379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpH));
3389566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpP));
3399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpB));
340b9907514SLisandro Dalcin     label->numStrata     = numStrata;
341b9907514SLisandro Dalcin     label->stratumValues = tmpV;
342b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
343b9907514SLisandro Dalcin     label->ht            = tmpH;
344b9907514SLisandro Dalcin     label->points        = tmpP;
345b9907514SLisandro Dalcin     label->validIS       = tmpB;
346b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3479566063dSJacob Faibussowitsch       PetscCall(PetscHSetICreate(&ht));
3489566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
3499566063dSJacob Faibussowitsch       PetscCall(PetscHMapISet(hmap, values[v], v));
350b9907514SLisandro Dalcin       tmpV[v] = values[v];
351b9907514SLisandro Dalcin       tmpS[v] = 0;
352b9907514SLisandro Dalcin       tmpH[v] = ht;
353b9907514SLisandro Dalcin       tmpP[v] = is;
354b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
355b9907514SLisandro Dalcin     }
3569566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
357b9907514SLisandro Dalcin   } else {
35848a46eb9SPierre Jolivet     for (v = 0; v < numStrata; ++v) PetscCall(DMLabelAddStratum(label, values[v]));
359b9907514SLisandro Dalcin   }
3609566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
361b9907514SLisandro Dalcin   PetscFunctionReturn(0);
362b9907514SLisandro Dalcin }
363b9907514SLisandro Dalcin 
364b9907514SLisandro Dalcin /*@
365b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
366b9907514SLisandro Dalcin 
3675b5e7992SMatthew G. Knepley   Not collective
3685b5e7992SMatthew G. Knepley 
369d8d19677SJose E. Roman   Input Parameters:
370b9907514SLisandro Dalcin + label - The DMLabel
371b9907514SLisandro Dalcin - valueIS - Index set with stratum values
372b9907514SLisandro Dalcin 
373b9907514SLisandro Dalcin   Level: beginner
374b9907514SLisandro Dalcin 
375db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
376b9907514SLisandro Dalcin @*/
377d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
378d71ae5a4SJacob Faibussowitsch {
379b9907514SLisandro Dalcin   PetscInt        numStrata;
380b9907514SLisandro Dalcin   const PetscInt *stratumValues;
381b9907514SLisandro Dalcin 
382b9907514SLisandro Dalcin   PetscFunctionBegin;
383b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
384b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
3859566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(valueIS, &numStrata));
3869566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valueIS, &stratumValues));
3879566063dSJacob Faibussowitsch   PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
388c58f1c22SToby Isaac   PetscFunctionReturn(0);
389c58f1c22SToby Isaac }
390c58f1c22SToby Isaac 
391d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer)
392d71ae5a4SJacob Faibussowitsch {
393c58f1c22SToby Isaac   PetscInt    v;
394c58f1c22SToby Isaac   PetscMPIInt rank;
395c58f1c22SToby Isaac 
396c58f1c22SToby Isaac   PetscFunctionBegin;
3979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3989566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
399c58f1c22SToby Isaac   if (label) {
400d67d17b1SMatthew G. Knepley     const char *name;
401d67d17b1SMatthew G. Knepley 
4029566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
4039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
40463a3b9bcSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", label->pStart, label->pEnd));
405c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
406c58f1c22SToby Isaac       const PetscInt  value = label->stratumValues[v];
407ad8374ffSToby Isaac       const PetscInt *points;
408c58f1c22SToby Isaac       PetscInt        p;
409c58f1c22SToby Isaac 
4109566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
41148a46eb9SPierre Jolivet       for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, points[p], value));
4129566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
413c58f1c22SToby Isaac     }
414c58f1c22SToby Isaac   }
4159566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4169566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
417c58f1c22SToby Isaac   PetscFunctionReturn(0);
418c58f1c22SToby Isaac }
419c58f1c22SToby Isaac 
420c58f1c22SToby Isaac /*@C
421c58f1c22SToby Isaac   DMLabelView - View the label
422c58f1c22SToby Isaac 
4235b5e7992SMatthew G. Knepley   Collective on viewer
4245b5e7992SMatthew G. Knepley 
425c58f1c22SToby Isaac   Input Parameters:
426c58f1c22SToby Isaac + label - The DMLabel
427c58f1c22SToby Isaac - viewer - The PetscViewer
428c58f1c22SToby Isaac 
429c58f1c22SToby Isaac   Level: intermediate
430c58f1c22SToby Isaac 
431db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
432c58f1c22SToby Isaac @*/
433d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
434d71ae5a4SJacob Faibussowitsch {
435c58f1c22SToby Isaac   PetscBool iascii;
436c58f1c22SToby Isaac 
437c58f1c22SToby Isaac   PetscFunctionBegin;
438d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4399566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
440c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4419566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
4429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4431baa6e33SBarry Smith   if (iascii) PetscCall(DMLabelView_Ascii(label, viewer));
444c58f1c22SToby Isaac   PetscFunctionReturn(0);
445c58f1c22SToby Isaac }
446c58f1c22SToby Isaac 
44784f0b6dfSMatthew G. Knepley /*@
448d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
449d67d17b1SMatthew G. Knepley 
4505b5e7992SMatthew G. Knepley   Not collective
4515b5e7992SMatthew G. Knepley 
452d67d17b1SMatthew G. Knepley   Input Parameter:
453d67d17b1SMatthew G. Knepley . label - The DMLabel
454d67d17b1SMatthew G. Knepley 
455d67d17b1SMatthew G. Knepley   Level: beginner
456d67d17b1SMatthew G. Knepley 
457db781477SPatrick Sanan .seealso: `DMLabelDestroy()`, `DMLabelCreate()`
458d67d17b1SMatthew G. Knepley @*/
459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelReset(DMLabel label)
460d71ae5a4SJacob Faibussowitsch {
461d67d17b1SMatthew G. Knepley   PetscInt v;
462d67d17b1SMatthew G. Knepley 
463d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
464d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
465d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
4669566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&label->ht[v]));
4679566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
468d67d17b1SMatthew G. Knepley   }
469b9907514SLisandro Dalcin   label->numStrata = 0;
4709566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
4719566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
4729566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
4739566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
4749566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
475f9244615SMatthew G. Knepley   label->stratumValues = NULL;
476f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
477f9244615SMatthew G. Knepley   label->ht            = NULL;
478f9244615SMatthew G. Knepley   label->points        = NULL;
479f9244615SMatthew G. Knepley   label->validIS       = NULL;
4809566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
481b9907514SLisandro Dalcin   label->pStart = -1;
482b9907514SLisandro Dalcin   label->pEnd   = -1;
4839566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
484d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
485d67d17b1SMatthew G. Knepley }
486d67d17b1SMatthew G. Knepley 
487d67d17b1SMatthew G. Knepley /*@
48884f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
48984f0b6dfSMatthew G. Knepley 
4905b5e7992SMatthew G. Knepley   Collective on label
4915b5e7992SMatthew G. Knepley 
49284f0b6dfSMatthew G. Knepley   Input Parameter:
49384f0b6dfSMatthew G. Knepley . label - The DMLabel
49484f0b6dfSMatthew G. Knepley 
49584f0b6dfSMatthew G. Knepley   Level: beginner
49684f0b6dfSMatthew G. Knepley 
497db781477SPatrick Sanan .seealso: `DMLabelReset()`, `DMLabelCreate()`
49884f0b6dfSMatthew G. Knepley @*/
499d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroy(DMLabel *label)
500d71ae5a4SJacob Faibussowitsch {
501c58f1c22SToby Isaac   PetscFunctionBegin;
502d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
503d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label), DMLABEL_CLASSID, 1);
5049371c9d4SSatish Balay   if (--((PetscObject)(*label))->refct > 0) {
5059371c9d4SSatish Balay     *label = NULL;
5069371c9d4SSatish Balay     PetscFunctionReturn(0);
5079371c9d4SSatish Balay   }
5089566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5099566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5109566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
511c58f1c22SToby Isaac   PetscFunctionReturn(0);
512c58f1c22SToby Isaac }
513c58f1c22SToby Isaac 
51484f0b6dfSMatthew G. Knepley /*@
51584f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
51684f0b6dfSMatthew G. Knepley 
5175b5e7992SMatthew G. Knepley   Collective on label
5185b5e7992SMatthew G. Knepley 
51984f0b6dfSMatthew G. Knepley   Input Parameter:
52084f0b6dfSMatthew G. Knepley . label - The DMLabel
52184f0b6dfSMatthew G. Knepley 
52284f0b6dfSMatthew G. Knepley   Output Parameter:
52384f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
52484f0b6dfSMatthew G. Knepley 
52584f0b6dfSMatthew G. Knepley   Level: intermediate
52684f0b6dfSMatthew G. Knepley 
527db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
52884f0b6dfSMatthew G. Knepley @*/
529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
530d71ae5a4SJacob Faibussowitsch {
531d67d17b1SMatthew G. Knepley   const char *name;
532ad8374ffSToby Isaac   PetscInt    v;
533c58f1c22SToby Isaac 
534c58f1c22SToby Isaac   PetscFunctionBegin;
535d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5369566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
5389566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
539c58f1c22SToby Isaac 
540c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5415aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->ht));
5459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->points));
5469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
547c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
5489566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
549c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
550c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
5519566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)(label->points[v])));
552ad8374ffSToby Isaac     (*labelnew)->points[v]  = label->points[v];
553b9907514SLisandro Dalcin     (*labelnew)->validIS[v] = PETSC_TRUE;
554c58f1c22SToby Isaac   }
5559566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5569566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
557c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
558c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
559c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
560c58f1c22SToby Isaac   PetscFunctionReturn(0);
561c58f1c22SToby Isaac }
562c58f1c22SToby Isaac 
563609dae6eSVaclav Hapla /*@C
564609dae6eSVaclav Hapla   DMLabelCompare - Compare two DMLabel objects
565609dae6eSVaclav Hapla 
5665efe38ccSVaclav Hapla   Collective on comm
567609dae6eSVaclav Hapla 
568609dae6eSVaclav Hapla   Input Parameters:
569f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
570f1a722f8SMatthew G. Knepley . l0 - First DMLabel
571609dae6eSVaclav Hapla - l1 - Second DMLabel
572609dae6eSVaclav Hapla 
573609dae6eSVaclav Hapla   Output Parameters
5745efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
5755efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
576609dae6eSVaclav Hapla 
577609dae6eSVaclav Hapla   Level: intermediate
578609dae6eSVaclav Hapla 
579609dae6eSVaclav Hapla   Notes:
5805efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
5815efe38ccSVaclav Hapla   If it is passed as NULL and difference is found, an error is thrown on all processes.
5825efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
583609dae6eSVaclav Hapla 
5845efe38ccSVaclav Hapla   The output message is set independently on each rank.
5855efe38ccSVaclav Hapla   It is set to NULL if no difference was found on the current rank. It must be freed by user.
5865efe38ccSVaclav Hapla   If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
5875efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
588609dae6eSVaclav Hapla 
589609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
590609dae6eSVaclav Hapla 
5915efe38ccSVaclav Hapla   The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
5925efe38ccSVaclav Hapla 
593609dae6eSVaclav Hapla   Fortran Notes:
594609dae6eSVaclav Hapla   This function is currently not available from Fortran.
595609dae6eSVaclav Hapla 
596db781477SPatrick Sanan .seealso: `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
597609dae6eSVaclav Hapla @*/
598d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
599d71ae5a4SJacob Faibussowitsch {
600609dae6eSVaclav Hapla   const char *name0, *name1;
601609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
6025efe38ccSVaclav Hapla   PetscBool   eq;
6035efe38ccSVaclav Hapla   PetscMPIInt rank;
604609dae6eSVaclav Hapla 
605609dae6eSVaclav Hapla   PetscFunctionBegin;
6065efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6075efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6085efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
6095efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
6109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6119566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
613609dae6eSVaclav Hapla   {
614609dae6eSVaclav Hapla     PetscInt v0, v1;
615609dae6eSVaclav Hapla 
6169566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6179566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6185efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
61948a46eb9SPierre 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));
6209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6215efe38ccSVaclav Hapla     if (!eq) goto finish;
622609dae6eSVaclav Hapla   }
623609dae6eSVaclav Hapla   {
624609dae6eSVaclav Hapla     IS is0, is1;
625609dae6eSVaclav Hapla 
6269566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6279566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6289566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6299566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6309566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
63148a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
6329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6335efe38ccSVaclav Hapla     if (!eq) goto finish;
634609dae6eSVaclav Hapla   }
635609dae6eSVaclav Hapla   {
636609dae6eSVaclav Hapla     PetscInt i, nValues;
637609dae6eSVaclav Hapla 
6389566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
639609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
640609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
641609dae6eSVaclav Hapla       PetscInt       n;
642609dae6eSVaclav Hapla       IS             is0, is1;
643609dae6eSVaclav Hapla 
6449566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
645609dae6eSVaclav Hapla       if (!n) continue;
6469566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6479566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6489566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6499566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6509566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6515efe38ccSVaclav Hapla       if (!eq) {
65263a3b9bcSJacob 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));
6535efe38ccSVaclav Hapla         break;
654609dae6eSVaclav Hapla       }
655609dae6eSVaclav Hapla     }
6569566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
657609dae6eSVaclav Hapla   }
658609dae6eSVaclav Hapla finish:
6595efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
660609dae6eSVaclav Hapla   if (message) {
661609dae6eSVaclav Hapla     *message = NULL;
66248a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
6635efe38ccSVaclav Hapla   } else {
66448a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
6659566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
6665efe38ccSVaclav Hapla   }
6675efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
6685efe38ccSVaclav Hapla   if (equal) *equal = eq;
66963a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
670609dae6eSVaclav Hapla   PetscFunctionReturn(0);
671609dae6eSVaclav Hapla }
672609dae6eSVaclav Hapla 
673c6a43d28SMatthew G. Knepley /*@
674c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
675c6a43d28SMatthew G. Knepley 
6765b5e7992SMatthew G. Knepley   Not collective
6775b5e7992SMatthew G. Knepley 
678c6a43d28SMatthew G. Knepley   Input Parameter:
679c6a43d28SMatthew G. Knepley . label  - The DMLabel
680c6a43d28SMatthew G. Knepley 
681c6a43d28SMatthew G. Knepley   Level: intermediate
682c6a43d28SMatthew G. Knepley 
683db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
684c6a43d28SMatthew G. Knepley @*/
685d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelComputeIndex(DMLabel label)
686d71ae5a4SJacob Faibussowitsch {
687c6a43d28SMatthew G. Knepley   PetscInt pStart = PETSC_MAX_INT, pEnd = -1, v;
688c6a43d28SMatthew G. Knepley 
689c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
690c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6919566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
692c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
693c6a43d28SMatthew G. Knepley     const PetscInt *points;
694c6a43d28SMatthew G. Knepley     PetscInt        i;
695c6a43d28SMatthew G. Knepley 
6969566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
697c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
698c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
699c6a43d28SMatthew G. Knepley 
700c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
701c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
702c6a43d28SMatthew G. Knepley     }
7039566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
704c6a43d28SMatthew G. Knepley   }
705c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
706c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7079566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
708c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
709c6a43d28SMatthew G. Knepley }
710c6a43d28SMatthew G. Knepley 
711c6a43d28SMatthew G. Knepley /*@
712c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
713c6a43d28SMatthew G. Knepley 
7145b5e7992SMatthew G. Knepley   Not collective
7155b5e7992SMatthew G. Knepley 
716c6a43d28SMatthew G. Knepley   Input Parameters:
717c6a43d28SMatthew G. Knepley + label  - The DMLabel
718c6a43d28SMatthew G. Knepley . pStart - The smallest point
719c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
720c6a43d28SMatthew G. Knepley 
721c6a43d28SMatthew G. Knepley   Level: intermediate
722c6a43d28SMatthew G. Knepley 
723db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
724c6a43d28SMatthew G. Knepley @*/
725d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
726d71ae5a4SJacob Faibussowitsch {
727c58f1c22SToby Isaac   PetscInt v;
728c58f1c22SToby Isaac 
729c58f1c22SToby Isaac   PetscFunctionBegin;
730d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7319566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7329566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
733c58f1c22SToby Isaac   label->pStart = pStart;
734c58f1c22SToby Isaac   label->pEnd   = pEnd;
735c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7369566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
737c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
738ad8374ffSToby Isaac     const PetscInt *points;
739c58f1c22SToby Isaac     PetscInt        i;
740c58f1c22SToby Isaac 
7419566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
742c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
743ad8374ffSToby Isaac       const PetscInt point = points[i];
744c58f1c22SToby Isaac 
74563a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < pStart) && !(point >= pEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd);
7469566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
747c58f1c22SToby Isaac     }
7489566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
749c58f1c22SToby Isaac   }
750c58f1c22SToby Isaac   PetscFunctionReturn(0);
751c58f1c22SToby Isaac }
752c58f1c22SToby Isaac 
753c6a43d28SMatthew G. Knepley /*@
754c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
755c6a43d28SMatthew G. Knepley 
7565b5e7992SMatthew G. Knepley   Not collective
7575b5e7992SMatthew G. Knepley 
758c6a43d28SMatthew G. Knepley   Input Parameter:
759c6a43d28SMatthew G. Knepley . label - the DMLabel
760c6a43d28SMatthew G. Knepley 
761c6a43d28SMatthew G. Knepley   Level: intermediate
762c6a43d28SMatthew G. Knepley 
763db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
764c6a43d28SMatthew G. Knepley @*/
765d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDestroyIndex(DMLabel label)
766d71ae5a4SJacob Faibussowitsch {
767c58f1c22SToby Isaac   PetscFunctionBegin;
768d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
769c58f1c22SToby Isaac   label->pStart = -1;
770c58f1c22SToby Isaac   label->pEnd   = -1;
7719566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
772c58f1c22SToby Isaac   PetscFunctionReturn(0);
773c58f1c22SToby Isaac }
774c58f1c22SToby Isaac 
775c58f1c22SToby Isaac /*@
776c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
777c6a43d28SMatthew G. Knepley 
7785b5e7992SMatthew G. Knepley   Not collective
7795b5e7992SMatthew G. Knepley 
780c6a43d28SMatthew G. Knepley   Input Parameter:
781c6a43d28SMatthew G. Knepley . label - the DMLabel
782c6a43d28SMatthew G. Knepley 
783c6a43d28SMatthew G. Knepley   Output Parameters:
784c6a43d28SMatthew G. Knepley + pStart - The smallest point
785c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
786c6a43d28SMatthew G. Knepley 
787c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
788c6a43d28SMatthew G. Knepley 
789c6a43d28SMatthew G. Knepley   Level: intermediate
790c6a43d28SMatthew G. Knepley 
791db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
792c6a43d28SMatthew G. Knepley @*/
793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
794d71ae5a4SJacob Faibussowitsch {
795c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
796c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7979566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
798c6a43d28SMatthew G. Knepley   if (pStart) {
799534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
800c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
801c6a43d28SMatthew G. Knepley   }
802c6a43d28SMatthew G. Knepley   if (pEnd) {
803534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
804c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
805c6a43d28SMatthew G. Knepley   }
806c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
807c6a43d28SMatthew G. Knepley }
808c6a43d28SMatthew G. Knepley 
809c6a43d28SMatthew G. Knepley /*@
810c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
811c58f1c22SToby Isaac 
8125b5e7992SMatthew G. Knepley   Not collective
8135b5e7992SMatthew G. Knepley 
814c58f1c22SToby Isaac   Input Parameters:
815c58f1c22SToby Isaac + label - the DMLabel
816c58f1c22SToby Isaac - value - the value
817c58f1c22SToby Isaac 
818c58f1c22SToby Isaac   Output Parameter:
819c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
820c58f1c22SToby Isaac 
821c58f1c22SToby Isaac   Level: developer
822c58f1c22SToby Isaac 
823db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
824c58f1c22SToby Isaac @*/
825d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
826d71ae5a4SJacob Faibussowitsch {
827c58f1c22SToby Isaac   PetscInt v;
828c58f1c22SToby Isaac 
829c58f1c22SToby Isaac   PetscFunctionBegin;
830d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
831534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8329566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8330c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
834c58f1c22SToby Isaac   PetscFunctionReturn(0);
835c58f1c22SToby Isaac }
836c58f1c22SToby Isaac 
837c58f1c22SToby Isaac /*@
838c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
839c58f1c22SToby Isaac 
8405b5e7992SMatthew G. Knepley   Not collective
8415b5e7992SMatthew G. Knepley 
842c58f1c22SToby Isaac   Input Parameters:
843c58f1c22SToby Isaac + label - the DMLabel
844c58f1c22SToby Isaac - point - the point
845c58f1c22SToby Isaac 
846c58f1c22SToby Isaac   Output Parameter:
847c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
848c58f1c22SToby Isaac 
849c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
850c58f1c22SToby Isaac 
851c58f1c22SToby Isaac   Level: developer
852c58f1c22SToby Isaac 
853db781477SPatrick Sanan .seealso: `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
854c58f1c22SToby Isaac @*/
855d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
856d71ae5a4SJacob Faibussowitsch {
857c58f1c22SToby Isaac   PetscFunctionBeginHot;
858d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
859534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8609566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
86176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
86228b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
86363a3b9bcSJacob 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);
86476bd3646SJed Brown   }
865c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
866c58f1c22SToby Isaac   PetscFunctionReturn(0);
867c58f1c22SToby Isaac }
868c58f1c22SToby Isaac 
869c58f1c22SToby Isaac /*@
870c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
871c58f1c22SToby Isaac 
8725b5e7992SMatthew G. Knepley   Not collective
8735b5e7992SMatthew G. Knepley 
874c58f1c22SToby Isaac   Input Parameters:
875c58f1c22SToby Isaac + label - the DMLabel
876c58f1c22SToby Isaac . value - the stratum value
877c58f1c22SToby Isaac - point - the point
878c58f1c22SToby Isaac 
879c58f1c22SToby Isaac   Output Parameter:
880c58f1c22SToby Isaac . contains - true if the stratum contains the point
881c58f1c22SToby Isaac 
882c58f1c22SToby Isaac   Level: intermediate
883c58f1c22SToby Isaac 
884db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
885c58f1c22SToby Isaac @*/
886d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
887d71ae5a4SJacob Faibussowitsch {
8880c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
889d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
890534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
891cffad2c9SToby Isaac   if (value == label->defaultValue) {
892cffad2c9SToby Isaac     PetscInt pointVal;
8930c3c4a36SLisandro Dalcin 
894cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
895cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
896cffad2c9SToby Isaac   } else {
897cffad2c9SToby Isaac     PetscInt v;
898cffad2c9SToby Isaac 
899cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
900cffad2c9SToby Isaac     if (v >= 0) {
901ad8374ffSToby Isaac       if (label->validIS[v]) {
902c58f1c22SToby Isaac         PetscInt i;
903c58f1c22SToby Isaac 
9049566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[v], point, &i));
905cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
906c58f1c22SToby Isaac       } else {
907cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
908cffad2c9SToby Isaac       }
909cffad2c9SToby Isaac     } else { // value is not present
910cffad2c9SToby Isaac       *contains = PETSC_FALSE;
911cffad2c9SToby Isaac     }
912c58f1c22SToby Isaac   }
913c58f1c22SToby Isaac   PetscFunctionReturn(0);
914c58f1c22SToby Isaac }
915c58f1c22SToby Isaac 
91684f0b6dfSMatthew G. Knepley /*@
9175aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9185aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9195aa44df4SToby Isaac 
9205b5e7992SMatthew G. Knepley   Not collective
9215b5e7992SMatthew G. Knepley 
9225aa44df4SToby Isaac   Input parameter:
9235aa44df4SToby Isaac . label - a DMLabel object
9245aa44df4SToby Isaac 
9255aa44df4SToby Isaac   Output parameter:
9265aa44df4SToby Isaac . defaultValue - the default value
9275aa44df4SToby Isaac 
9285aa44df4SToby Isaac   Level: beginner
9295aa44df4SToby Isaac 
930db781477SPatrick Sanan .seealso: `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
93184f0b6dfSMatthew G. Knepley @*/
932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
933d71ae5a4SJacob Faibussowitsch {
9345aa44df4SToby Isaac   PetscFunctionBegin;
935d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9365aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9375aa44df4SToby Isaac   PetscFunctionReturn(0);
9385aa44df4SToby Isaac }
9395aa44df4SToby Isaac 
94084f0b6dfSMatthew G. Knepley /*@
9415aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9425aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9435aa44df4SToby Isaac 
9445b5e7992SMatthew G. Knepley   Not collective
9455b5e7992SMatthew G. Knepley 
9465aa44df4SToby Isaac   Input parameter:
9475aa44df4SToby Isaac . label - a DMLabel object
9485aa44df4SToby Isaac 
9495aa44df4SToby Isaac   Output parameter:
9505aa44df4SToby Isaac . defaultValue - the default value
9515aa44df4SToby Isaac 
9525aa44df4SToby Isaac   Level: beginner
9535aa44df4SToby Isaac 
954db781477SPatrick Sanan .seealso: `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
95584f0b6dfSMatthew G. Knepley @*/
956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
957d71ae5a4SJacob Faibussowitsch {
9585aa44df4SToby Isaac   PetscFunctionBegin;
959d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9605aa44df4SToby Isaac   label->defaultValue = defaultValue;
9615aa44df4SToby Isaac   PetscFunctionReturn(0);
9625aa44df4SToby Isaac }
9635aa44df4SToby Isaac 
964c58f1c22SToby Isaac /*@
9655aa44df4SToby 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())
966c58f1c22SToby Isaac 
9675b5e7992SMatthew G. Knepley   Not collective
9685b5e7992SMatthew G. Knepley 
969c58f1c22SToby Isaac   Input Parameters:
970c58f1c22SToby Isaac + label - the DMLabel
971c58f1c22SToby Isaac - point - the point
972c58f1c22SToby Isaac 
973c58f1c22SToby Isaac   Output Parameter:
9748e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
975c58f1c22SToby Isaac 
976cffad2c9SToby 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.
977cffad2c9SToby Isaac 
978c58f1c22SToby Isaac   Level: intermediate
979c58f1c22SToby Isaac 
980db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
981c58f1c22SToby Isaac @*/
982d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
983d71ae5a4SJacob Faibussowitsch {
984c58f1c22SToby Isaac   PetscInt v;
985c58f1c22SToby Isaac 
9860c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
987d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
988dadcf809SJacob Faibussowitsch   PetscValidIntPointer(value, 3);
9895aa44df4SToby Isaac   *value = label->defaultValue;
990c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
991ad8374ffSToby Isaac     if (label->validIS[v]) {
992c58f1c22SToby Isaac       PetscInt i;
993c58f1c22SToby Isaac 
9949566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
995c58f1c22SToby Isaac       if (i >= 0) {
996c58f1c22SToby Isaac         *value = label->stratumValues[v];
997c58f1c22SToby Isaac         break;
998c58f1c22SToby Isaac       }
999c58f1c22SToby Isaac     } else {
1000c58f1c22SToby Isaac       PetscBool has;
1001c58f1c22SToby Isaac 
10029566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1003c58f1c22SToby Isaac       if (has) {
1004c58f1c22SToby Isaac         *value = label->stratumValues[v];
1005c58f1c22SToby Isaac         break;
1006c58f1c22SToby Isaac       }
1007c58f1c22SToby Isaac     }
1008c58f1c22SToby Isaac   }
1009c58f1c22SToby Isaac   PetscFunctionReturn(0);
1010c58f1c22SToby Isaac }
1011c58f1c22SToby Isaac 
1012c58f1c22SToby Isaac /*@
1013367003a6SStefano 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.
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 - value - The point value
1021c58f1c22SToby Isaac 
1022c58f1c22SToby Isaac   Level: intermediate
1023c58f1c22SToby Isaac 
1024db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1025c58f1c22SToby Isaac @*/
1026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1027d71ae5a4SJacob Faibussowitsch {
1028c58f1c22SToby Isaac   PetscInt v;
1029c58f1c22SToby Isaac 
1030c58f1c22SToby Isaac   PetscFunctionBegin;
1031d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10320c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10335aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
10349566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1035c58f1c22SToby Isaac   /* Set key */
10369566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10379566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
1038c58f1c22SToby Isaac   PetscFunctionReturn(0);
1039c58f1c22SToby Isaac }
1040c58f1c22SToby Isaac 
1041c58f1c22SToby Isaac /*@
1042c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1043c58f1c22SToby Isaac 
10445b5e7992SMatthew G. Knepley   Not collective
10455b5e7992SMatthew G. Knepley 
1046c58f1c22SToby Isaac   Input Parameters:
1047c58f1c22SToby Isaac + label - the DMLabel
1048c58f1c22SToby Isaac . point - the point
1049c58f1c22SToby Isaac - value - The point value
1050c58f1c22SToby Isaac 
1051c58f1c22SToby Isaac   Level: intermediate
1052c58f1c22SToby Isaac 
1053db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1054c58f1c22SToby Isaac @*/
1055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1056d71ae5a4SJacob Faibussowitsch {
1057ad8374ffSToby Isaac   PetscInt v;
1058c58f1c22SToby Isaac 
1059c58f1c22SToby Isaac   PetscFunctionBegin;
1060d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1061c58f1c22SToby Isaac   /* Find label value */
10629566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
10630c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
10640c3c4a36SLisandro Dalcin 
1065eeed21e7SToby Isaac   if (label->bt) {
106663a3b9bcSJacob 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);
10679566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1068eeed21e7SToby Isaac   }
10690c3c4a36SLisandro Dalcin 
10700c3c4a36SLisandro Dalcin   /* Delete key */
10719566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10729566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
1073c58f1c22SToby Isaac   PetscFunctionReturn(0);
1074c58f1c22SToby Isaac }
1075c58f1c22SToby Isaac 
1076c58f1c22SToby Isaac /*@
1077c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
1078c58f1c22SToby Isaac 
10795b5e7992SMatthew G. Knepley   Not collective
10805b5e7992SMatthew G. Knepley 
1081c58f1c22SToby Isaac   Input Parameters:
1082c58f1c22SToby Isaac + label - the DMLabel
1083c58f1c22SToby Isaac . is    - the point IS
1084c58f1c22SToby Isaac - value - The point value
1085c58f1c22SToby Isaac 
1086c58f1c22SToby Isaac   Level: intermediate
1087c58f1c22SToby Isaac 
1088db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1089c58f1c22SToby Isaac @*/
1090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1091d71ae5a4SJacob Faibussowitsch {
10920c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1093c58f1c22SToby Isaac   const PetscInt *points;
1094c58f1c22SToby Isaac 
1095c58f1c22SToby Isaac   PetscFunctionBegin;
1096d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1097c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
10980c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10990c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
11009566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11010c3c4a36SLisandro Dalcin   /* Set keys */
11029566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11039566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11049566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11059566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11069566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
1107c58f1c22SToby Isaac   PetscFunctionReturn(0);
1108c58f1c22SToby Isaac }
1109c58f1c22SToby Isaac 
111084f0b6dfSMatthew G. Knepley /*@
111184f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
111284f0b6dfSMatthew G. Knepley 
11135b5e7992SMatthew G. Knepley   Not collective
11145b5e7992SMatthew G. Knepley 
111584f0b6dfSMatthew G. Knepley   Input Parameter:
111684f0b6dfSMatthew G. Knepley . label - the DMLabel
111784f0b6dfSMatthew G. Knepley 
111801d2d390SJose E. Roman   Output Parameter:
111984f0b6dfSMatthew G. Knepley . numValues - the number of values
112084f0b6dfSMatthew G. Knepley 
112184f0b6dfSMatthew G. Knepley   Level: intermediate
112284f0b6dfSMatthew G. Knepley 
1123db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
112484f0b6dfSMatthew G. Knepley @*/
1125d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1126d71ae5a4SJacob Faibussowitsch {
1127c58f1c22SToby Isaac   PetscFunctionBegin;
1128d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1129dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numValues, 2);
1130c58f1c22SToby Isaac   *numValues = label->numStrata;
1131c58f1c22SToby Isaac   PetscFunctionReturn(0);
1132c58f1c22SToby Isaac }
1133c58f1c22SToby Isaac 
113484f0b6dfSMatthew G. Knepley /*@
113584f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
113684f0b6dfSMatthew G. Knepley 
11375b5e7992SMatthew G. Knepley   Not collective
11385b5e7992SMatthew G. Knepley 
113984f0b6dfSMatthew G. Knepley   Input Parameter:
114084f0b6dfSMatthew G. Knepley . label - the DMLabel
114184f0b6dfSMatthew G. Knepley 
114201d2d390SJose E. Roman   Output Parameter:
114384f0b6dfSMatthew G. Knepley . is    - the value IS
114484f0b6dfSMatthew G. Knepley 
114584f0b6dfSMatthew G. Knepley   Level: intermediate
114684f0b6dfSMatthew G. Knepley 
11471d04cbbeSVaclav Hapla   Notes:
11481d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11491d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
11501d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
11511d04cbbeSVaclav Hapla 
1152db781477SPatrick Sanan .seealso: `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
115384f0b6dfSMatthew G. Knepley @*/
1154d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1155d71ae5a4SJacob Faibussowitsch {
1156c58f1c22SToby Isaac   PetscFunctionBegin;
1157d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1158c58f1c22SToby Isaac   PetscValidPointer(values, 2);
11599566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1160c58f1c22SToby Isaac   PetscFunctionReturn(0);
1161c58f1c22SToby Isaac }
1162c58f1c22SToby Isaac 
116384f0b6dfSMatthew G. Knepley /*@
11641d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
11651d04cbbeSVaclav Hapla 
11661d04cbbeSVaclav Hapla   Not collective
11671d04cbbeSVaclav Hapla 
11681d04cbbeSVaclav Hapla   Input Parameter:
11691d04cbbeSVaclav Hapla . label - the DMLabel
11701d04cbbeSVaclav Hapla 
1171*d5b43468SJose E. Roman   Output Parameter:
11721d04cbbeSVaclav Hapla . is    - the value IS
11731d04cbbeSVaclav Hapla 
11741d04cbbeSVaclav Hapla   Level: intermediate
11751d04cbbeSVaclav Hapla 
11761d04cbbeSVaclav Hapla   Notes:
11771d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11781d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
11791d04cbbeSVaclav Hapla 
1180db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
11811d04cbbeSVaclav Hapla @*/
1182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1183d71ae5a4SJacob Faibussowitsch {
11841d04cbbeSVaclav Hapla   PetscInt  i, j;
11851d04cbbeSVaclav Hapla   PetscInt *valuesArr;
11861d04cbbeSVaclav Hapla 
11871d04cbbeSVaclav Hapla   PetscFunctionBegin;
11881d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11891d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
11909566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
11911d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
11921d04cbbeSVaclav Hapla     PetscInt n;
11931d04cbbeSVaclav Hapla 
11949566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
11951d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
11961d04cbbeSVaclav Hapla   }
11971d04cbbeSVaclav Hapla   if (j == label->numStrata) {
11989566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
11991d04cbbeSVaclav Hapla   } else {
12009566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
12011d04cbbeSVaclav Hapla   }
12029566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
12031d04cbbeSVaclav Hapla   PetscFunctionReturn(0);
12041d04cbbeSVaclav Hapla }
12051d04cbbeSVaclav Hapla 
12061d04cbbeSVaclav Hapla /*@
1207d123abd9SMatthew 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
1208d123abd9SMatthew G. Knepley 
1209d123abd9SMatthew G. Knepley   Not collective
1210d123abd9SMatthew G. Knepley 
1211d123abd9SMatthew G. Knepley   Input Parameters:
1212d123abd9SMatthew G. Knepley + label - the DMLabel
121397bb3fdcSJose E. Roman - value - the value
1214d123abd9SMatthew G. Knepley 
121501d2d390SJose E. Roman   Output Parameter:
1216d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1217d123abd9SMatthew G. Knepley 
1218d123abd9SMatthew G. Knepley   Level: intermediate
1219d123abd9SMatthew G. Knepley 
1220db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1221d123abd9SMatthew G. Knepley @*/
1222d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1223d71ae5a4SJacob Faibussowitsch {
1224d123abd9SMatthew G. Knepley   PetscInt v;
1225d123abd9SMatthew G. Knepley 
1226d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1227d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1228dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 3);
1229d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
12309371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
12319371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1232d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1233d123abd9SMatthew G. Knepley   else *index = v;
1234d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1235d123abd9SMatthew G. Knepley }
1236d123abd9SMatthew G. Knepley 
1237d123abd9SMatthew G. Knepley /*@
123884f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
123984f0b6dfSMatthew G. Knepley 
12405b5e7992SMatthew G. Knepley   Not collective
12415b5e7992SMatthew G. Knepley 
124284f0b6dfSMatthew G. Knepley   Input Parameters:
124384f0b6dfSMatthew G. Knepley + label - the DMLabel
124484f0b6dfSMatthew G. Knepley - value - the stratum value
124584f0b6dfSMatthew G. Knepley 
124601d2d390SJose E. Roman   Output Parameter:
124784f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
124884f0b6dfSMatthew G. Knepley 
124984f0b6dfSMatthew G. Knepley   Level: intermediate
125084f0b6dfSMatthew G. Knepley 
1251db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
125284f0b6dfSMatthew G. Knepley @*/
1253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1254d71ae5a4SJacob Faibussowitsch {
1255fada774cSMatthew G. Knepley   PetscInt v;
1256fada774cSMatthew G. Knepley 
1257fada774cSMatthew G. Knepley   PetscFunctionBegin;
1258d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1259dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(exists, 3);
12609566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12610c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1262fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1263fada774cSMatthew G. Knepley }
1264fada774cSMatthew G. Knepley 
126584f0b6dfSMatthew G. Knepley /*@
126684f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
126784f0b6dfSMatthew G. Knepley 
12685b5e7992SMatthew G. Knepley   Not collective
12695b5e7992SMatthew G. Knepley 
127084f0b6dfSMatthew G. Knepley   Input Parameters:
127184f0b6dfSMatthew G. Knepley + label - the DMLabel
127284f0b6dfSMatthew G. Knepley - value - the stratum value
127384f0b6dfSMatthew G. Knepley 
127401d2d390SJose E. Roman   Output Parameter:
127584f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
127684f0b6dfSMatthew G. Knepley 
127784f0b6dfSMatthew G. Knepley   Level: intermediate
127884f0b6dfSMatthew G. Knepley 
1279db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
128084f0b6dfSMatthew G. Knepley @*/
1281d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1282d71ae5a4SJacob Faibussowitsch {
1283c58f1c22SToby Isaac   PetscInt v;
1284c58f1c22SToby Isaac 
1285c58f1c22SToby Isaac   PetscFunctionBegin;
1286d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1287dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
12889566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12899566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
1290c58f1c22SToby Isaac   PetscFunctionReturn(0);
1291c58f1c22SToby Isaac }
1292c58f1c22SToby Isaac 
129384f0b6dfSMatthew G. Knepley /*@
129484f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
129584f0b6dfSMatthew G. Knepley 
12965b5e7992SMatthew G. Knepley   Not collective
12975b5e7992SMatthew G. Knepley 
129884f0b6dfSMatthew G. Knepley   Input Parameters:
129984f0b6dfSMatthew G. Knepley + label - the DMLabel
130084f0b6dfSMatthew G. Knepley - value - the stratum value
130184f0b6dfSMatthew G. Knepley 
130201d2d390SJose E. Roman   Output Parameters:
130384f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
130484f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
130584f0b6dfSMatthew G. Knepley 
130684f0b6dfSMatthew G. Knepley   Level: intermediate
130784f0b6dfSMatthew G. Knepley 
1308db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
130984f0b6dfSMatthew G. Knepley @*/
1310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1311d71ae5a4SJacob Faibussowitsch {
13120c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1313c58f1c22SToby Isaac 
1314c58f1c22SToby Isaac   PetscFunctionBegin;
1315d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13169371c9d4SSatish Balay   if (start) {
13179371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
13189371c9d4SSatish Balay     *start = -1;
13199371c9d4SSatish Balay   }
13209371c9d4SSatish Balay   if (end) {
13219371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
13229371c9d4SSatish Balay     *end = -1;
13239371c9d4SSatish Balay   }
13249566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13250c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13269566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13270c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
13289566063dSJacob Faibussowitsch   PetscCall(ISGetMinMax(label->points[v], &min, &max));
1329d6cb179aSToby Isaac   if (start) *start = min;
1330d6cb179aSToby Isaac   if (end) *end = max + 1;
1331c58f1c22SToby Isaac   PetscFunctionReturn(0);
1332c58f1c22SToby Isaac }
1333c58f1c22SToby Isaac 
133484f0b6dfSMatthew G. Knepley /*@
133584f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
133684f0b6dfSMatthew G. Knepley 
13375b5e7992SMatthew G. Knepley   Not collective
13385b5e7992SMatthew G. Knepley 
133984f0b6dfSMatthew G. Knepley   Input Parameters:
134084f0b6dfSMatthew G. Knepley + label - the DMLabel
134184f0b6dfSMatthew G. Knepley - value - the stratum value
134284f0b6dfSMatthew G. Knepley 
134301d2d390SJose E. Roman   Output Parameter:
134484f0b6dfSMatthew G. Knepley . points - The stratum points
134584f0b6dfSMatthew G. Knepley 
134684f0b6dfSMatthew G. Knepley   Level: intermediate
134784f0b6dfSMatthew G. Knepley 
1348593ce467SVaclav Hapla   Notes:
1349593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1350593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1351593ce467SVaclav Hapla 
1352db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
135384f0b6dfSMatthew G. Knepley @*/
1354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1355d71ae5a4SJacob Faibussowitsch {
1356c58f1c22SToby Isaac   PetscInt v;
1357c58f1c22SToby Isaac 
1358c58f1c22SToby Isaac   PetscFunctionBegin;
1359d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1360c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1361c58f1c22SToby Isaac   *points = NULL;
13629566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13630c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13649566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13659566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
1366ad8374ffSToby Isaac   *points = label->points[v];
1367c58f1c22SToby Isaac   PetscFunctionReturn(0);
1368c58f1c22SToby Isaac }
1369c58f1c22SToby Isaac 
137084f0b6dfSMatthew G. Knepley /*@
137184f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
137284f0b6dfSMatthew G. Knepley 
13735b5e7992SMatthew G. Knepley   Not collective
13745b5e7992SMatthew G. Knepley 
137584f0b6dfSMatthew G. Knepley   Input Parameters:
137684f0b6dfSMatthew G. Knepley + label - the DMLabel
137784f0b6dfSMatthew G. Knepley . value - the stratum value
137884f0b6dfSMatthew G. Knepley - points - The stratum points
137984f0b6dfSMatthew G. Knepley 
138084f0b6dfSMatthew G. Knepley   Level: intermediate
138184f0b6dfSMatthew G. Knepley 
1382db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
138384f0b6dfSMatthew G. Knepley @*/
1384d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
1385d71ae5a4SJacob Faibussowitsch {
13860c3c4a36SLisandro Dalcin   PetscInt v;
13874de306b1SToby Isaac 
13884de306b1SToby Isaac   PetscFunctionBegin;
1389d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1390d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
13919566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
13924de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
13939566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
13949566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
13959566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
13969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&(label->points[v])));
13970c3c4a36SLisandro Dalcin   label->points[v]  = is;
13980c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
13999566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
14004de306b1SToby Isaac   if (label->bt) {
14014de306b1SToby Isaac     const PetscInt *points;
14024de306b1SToby Isaac     PetscInt        p;
14034de306b1SToby Isaac 
14049566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
14054de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
14064de306b1SToby Isaac       const PetscInt point = points[p];
14074de306b1SToby Isaac 
140863a3b9bcSJacob 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);
14099566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
14104de306b1SToby Isaac     }
14114de306b1SToby Isaac   }
14124de306b1SToby Isaac   PetscFunctionReturn(0);
14134de306b1SToby Isaac }
14144de306b1SToby Isaac 
141584f0b6dfSMatthew G. Knepley /*@
141684f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14174de306b1SToby Isaac 
14185b5e7992SMatthew G. Knepley   Not collective
14195b5e7992SMatthew G. Knepley 
142084f0b6dfSMatthew G. Knepley   Input Parameters:
142184f0b6dfSMatthew G. Knepley + label - the DMLabel
142284f0b6dfSMatthew G. Knepley - value - the stratum value
142384f0b6dfSMatthew G. Knepley 
142484f0b6dfSMatthew G. Knepley   Level: intermediate
142584f0b6dfSMatthew G. Knepley 
1426db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
142784f0b6dfSMatthew G. Knepley @*/
1428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1429d71ae5a4SJacob Faibussowitsch {
1430c58f1c22SToby Isaac   PetscInt v;
1431c58f1c22SToby Isaac 
1432c58f1c22SToby Isaac   PetscFunctionBegin;
1433d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14349566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14350c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
14364de306b1SToby Isaac   if (label->validIS[v]) {
14374de306b1SToby Isaac     if (label->bt) {
1438c58f1c22SToby Isaac       PetscInt        i;
1439ad8374ffSToby Isaac       const PetscInt *points;
1440c58f1c22SToby Isaac 
14419566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1442c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1443ad8374ffSToby Isaac         const PetscInt point = points[i];
1444c58f1c22SToby Isaac 
144563a3b9bcSJacob 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);
14469566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1447c58f1c22SToby Isaac       }
14489566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1449c58f1c22SToby Isaac     }
1450c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
14519566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
14529566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
14539566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
14549566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1455c58f1c22SToby Isaac   } else {
14569566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1457c58f1c22SToby Isaac   }
1458c58f1c22SToby Isaac   PetscFunctionReturn(0);
1459c58f1c22SToby Isaac }
1460c58f1c22SToby Isaac 
146184f0b6dfSMatthew G. Knepley /*@
1462412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1463412e9a14SMatthew G. Knepley 
1464412e9a14SMatthew G. Knepley   Not collective
1465412e9a14SMatthew G. Knepley 
1466412e9a14SMatthew G. Knepley   Input Parameters:
1467412e9a14SMatthew G. Knepley + label  - The DMLabel
1468412e9a14SMatthew G. Knepley . value  - The label value for all points
1469412e9a14SMatthew G. Knepley . pStart - The first point
1470412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1471412e9a14SMatthew G. Knepley 
1472412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1473412e9a14SMatthew G. Knepley 
1474412e9a14SMatthew G. Knepley   Level: intermediate
1475412e9a14SMatthew G. Knepley 
1476db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1477412e9a14SMatthew G. Knepley @*/
1478d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1479d71ae5a4SJacob Faibussowitsch {
1480412e9a14SMatthew G. Knepley   IS pIS;
1481412e9a14SMatthew G. Knepley 
1482412e9a14SMatthew G. Knepley   PetscFunctionBegin;
14839566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
14849566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
14859566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
1486412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1487412e9a14SMatthew G. Knepley }
1488412e9a14SMatthew G. Knepley 
1489412e9a14SMatthew G. Knepley /*@
1490d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1491d123abd9SMatthew G. Knepley 
1492d123abd9SMatthew G. Knepley   Not collective
1493d123abd9SMatthew G. Knepley 
1494d123abd9SMatthew G. Knepley   Input Parameters:
1495d123abd9SMatthew G. Knepley + label  - The DMLabel
1496d123abd9SMatthew G. Knepley . value  - The label value
1497d123abd9SMatthew G. Knepley - p      - A point with this value
1498d123abd9SMatthew G. Knepley 
1499d123abd9SMatthew G. Knepley   Output Parameter:
1500d123abd9SMatthew 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
1501d123abd9SMatthew G. Knepley 
1502d123abd9SMatthew G. Knepley   Level: intermediate
1503d123abd9SMatthew G. Knepley 
1504db781477SPatrick Sanan .seealso: `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1505d123abd9SMatthew G. Knepley @*/
1506d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1507d71ae5a4SJacob Faibussowitsch {
1508d123abd9SMatthew G. Knepley   const PetscInt *indices;
1509d123abd9SMatthew G. Knepley   PetscInt        v;
1510d123abd9SMatthew G. Knepley 
1511d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1512d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1513dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 4);
1514d123abd9SMatthew G. Knepley   *index = -1;
15159566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1516d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
15179566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
15189566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(label->points[v], &indices));
15199566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
15209566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(label->points[v], &indices));
1521d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1522d123abd9SMatthew G. Knepley }
1523d123abd9SMatthew G. Knepley 
1524d123abd9SMatthew G. Knepley /*@
152584f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
152684f0b6dfSMatthew G. Knepley 
15275b5e7992SMatthew G. Knepley   Not collective
15285b5e7992SMatthew G. Knepley 
152984f0b6dfSMatthew G. Knepley   Input Parameters:
153084f0b6dfSMatthew G. Knepley + label - the DMLabel
153122cd2cdaSVaclav Hapla . start - the first point kept
153222cd2cdaSVaclav Hapla - end - one more than the last point kept
153384f0b6dfSMatthew G. Knepley 
153484f0b6dfSMatthew G. Knepley   Level: intermediate
153584f0b6dfSMatthew G. Knepley 
1536db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
153784f0b6dfSMatthew G. Knepley @*/
1538d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1539d71ae5a4SJacob Faibussowitsch {
1540c58f1c22SToby Isaac   PetscInt v;
1541c58f1c22SToby Isaac 
1542c58f1c22SToby Isaac   PetscFunctionBegin;
1543d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15449566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
15459566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
154648a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; ++v) PetscCall(ISGeneralFilter(label->points[v], start, end));
15479566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
1548c58f1c22SToby Isaac   PetscFunctionReturn(0);
1549c58f1c22SToby Isaac }
1550c58f1c22SToby Isaac 
155184f0b6dfSMatthew G. Knepley /*@
155284f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
155384f0b6dfSMatthew G. Knepley 
15545b5e7992SMatthew G. Knepley   Not collective
15555b5e7992SMatthew G. Knepley 
155684f0b6dfSMatthew G. Knepley   Input Parameters:
155784f0b6dfSMatthew G. Knepley + label - the DMLabel
155884f0b6dfSMatthew G. Knepley - permutation - the point permutation
155984f0b6dfSMatthew G. Knepley 
156084f0b6dfSMatthew G. Knepley   Output Parameter:
156184f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
156284f0b6dfSMatthew G. Knepley 
156384f0b6dfSMatthew G. Knepley   Level: intermediate
156484f0b6dfSMatthew G. Knepley 
1565db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
156684f0b6dfSMatthew G. Knepley @*/
1567d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1568d71ae5a4SJacob Faibussowitsch {
1569c58f1c22SToby Isaac   const PetscInt *perm;
1570c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1571c58f1c22SToby Isaac 
1572c58f1c22SToby Isaac   PetscFunctionBegin;
1573d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1574d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
15759566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
15769566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
15779566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
15789566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
15799566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1580c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1581c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1582ad8374ffSToby Isaac     const PetscInt *points;
1583ad8374ffSToby Isaac     PetscInt       *pointsNew;
1584c58f1c22SToby Isaac 
15859566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
15869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &pointsNew));
1587c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1588ad8374ffSToby Isaac       const PetscInt point = points[q];
1589c58f1c22SToby Isaac 
159063a3b9bcSJacob 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);
1591ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1592c58f1c22SToby Isaac     }
15939566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
15949566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
15959566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1596fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
15979566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
15989566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1599fa8e8ae5SToby Isaac     } else {
16009566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1601fa8e8ae5SToby Isaac     }
16029566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1603c58f1c22SToby Isaac   }
16049566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1605c58f1c22SToby Isaac   if (label->bt) {
16069566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
16079566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1608c58f1c22SToby Isaac   }
1609c58f1c22SToby Isaac   PetscFunctionReturn(0);
1610c58f1c22SToby Isaac }
1611c58f1c22SToby Isaac 
1612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
1613d71ae5a4SJacob Faibussowitsch {
161426c55118SMichael Lange   MPI_Comm     comm;
1615eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
161626c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
161726c55118SMichael Lange   PetscSection rootSection;
161826c55118SMichael Lange   PetscSF      labelSF;
161926c55118SMichael Lange 
162026c55118SMichael Lange   PetscFunctionBegin;
16219566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
16229566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
162326c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
162426c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
16259566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
16269566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
16279566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
162826c55118SMichael Lange   if (label) {
162926c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1630ad8374ffSToby Isaac       const PetscInt *points;
1631ad8374ffSToby Isaac 
16329566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
163348a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
16349566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
163526c55118SMichael Lange     }
163626c55118SMichael Lange   }
16379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
163826c55118SMichael Lange   /* Create a point-wise array of stratum values */
16399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
16409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
16419566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
164226c55118SMichael Lange   if (label) {
164326c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1644ad8374ffSToby Isaac       const PetscInt *points;
1645ad8374ffSToby Isaac 
16469566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
164726c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1648ad8374ffSToby Isaac         const PetscInt p = points[l];
16499566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
165026c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
165126c55118SMichael Lange       }
16529566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
165326c55118SMichael Lange     }
165426c55118SMichael Lange   }
165526c55118SMichael Lange   /* Build SF that maps label points to remote processes */
16569566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
16579566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
16589566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
16599566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
166026c55118SMichael Lange   /* Send the strata for each point over the derived SF */
16619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
16629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
16639566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
16649566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
166526c55118SMichael Lange   /* Clean up */
16669566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
16679566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
16689566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
16699566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
167026c55118SMichael Lange   PetscFunctionReturn(0);
167126c55118SMichael Lange }
167226c55118SMichael Lange 
167384f0b6dfSMatthew G. Knepley /*@
167484f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
167584f0b6dfSMatthew G. Knepley 
16765b5e7992SMatthew G. Knepley   Collective on sf
16775b5e7992SMatthew G. Knepley 
167884f0b6dfSMatthew G. Knepley   Input Parameters:
167984f0b6dfSMatthew G. Knepley + label - the DMLabel
168084f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
168184f0b6dfSMatthew G. Knepley 
168284f0b6dfSMatthew G. Knepley   Output Parameter:
168384f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
168484f0b6dfSMatthew G. Knepley 
168584f0b6dfSMatthew G. Knepley   Level: intermediate
168684f0b6dfSMatthew G. Knepley 
1687db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
168884f0b6dfSMatthew G. Knepley @*/
1689d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1690d71ae5a4SJacob Faibussowitsch {
1691c58f1c22SToby Isaac   MPI_Comm     comm;
169226c55118SMichael Lange   PetscSection leafSection;
169326c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
169426c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1695ad8374ffSToby Isaac   PetscInt   **points;
1696d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1697c58f1c22SToby Isaac   char        *name;
1698c58f1c22SToby Isaac   PetscInt     nameSize;
1699e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1700c58f1c22SToby Isaac   size_t       len = 0;
170126c55118SMichael Lange   PetscMPIInt  rank;
1702c58f1c22SToby Isaac 
1703c58f1c22SToby Isaac   PetscFunctionBegin;
1704d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1705f018e600SMatthew G. Knepley   if (label) {
1706f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17079566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1708f018e600SMatthew G. Knepley   }
17099566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1711c58f1c22SToby Isaac   /* Bcast name */
1712dd400576SPatrick Sanan   if (rank == 0) {
17139566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
17149566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1715d67d17b1SMatthew G. Knepley   }
1716c58f1c22SToby Isaac   nameSize = len;
17179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
17199566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
17209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
17219566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17229566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
172377d236dfSMichael Lange   /* Bcast defaultValue */
1724dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
17259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
172626c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
17279566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
17285cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
17299566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
17309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
17319566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
17329566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
17339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1734ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
17359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
17365cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
17375cbdf6fcSMichael Lange   offset = 0;
17389566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
17399566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
174048a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
17415cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1742231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
17439371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
17449371c9d4SSatish Balay         leafStrata[p] = s;
17459371c9d4SSatish Balay         break;
17469371c9d4SSatish Balay       }
17475cbdf6fcSMichael Lange     }
17485cbdf6fcSMichael Lange   }
1749c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
17509566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
17519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1752c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
17539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1755ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1756c58f1c22SToby Isaac   }
17579566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
17589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->points));
17599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &points));
1760c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17619566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
17629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1763c58f1c22SToby Isaac   }
1764c58f1c22SToby Isaac   /* Insert points into new strata */
17659566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
17669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1767c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
17689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17699566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1770c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1771c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1772ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1773c58f1c22SToby Isaac     }
1774c58f1c22SToby Isaac   }
1775ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
17769566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &(points[s][0]), PETSC_OWN_POINTER, &((*labelNew)->points[s])));
17779566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1778ad8374ffSToby Isaac   }
17799566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
17809566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
17819566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
17829566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
17839566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
1784c58f1c22SToby Isaac   PetscFunctionReturn(0);
1785c58f1c22SToby Isaac }
1786c58f1c22SToby Isaac 
17877937d9ceSMichael Lange /*@
17887937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
17897937d9ceSMichael Lange 
17905b5e7992SMatthew G. Knepley   Collective on sf
17915b5e7992SMatthew G. Knepley 
17927937d9ceSMichael Lange   Input Parameters:
17937937d9ceSMichael Lange + label - the DMLabel
179484f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
17957937d9ceSMichael Lange 
179684f0b6dfSMatthew G. Knepley   Output Parameters:
179784f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
17987937d9ceSMichael Lange 
17997937d9ceSMichael Lange   Level: developer
18007937d9ceSMichael Lange 
18017937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
18027937d9ceSMichael Lange 
1803db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
18047937d9ceSMichael Lange @*/
1805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
1806d71ae5a4SJacob Faibussowitsch {
18077937d9ceSMichael Lange   MPI_Comm        comm;
18087937d9ceSMichael Lange   PetscSection    rootSection;
18097937d9ceSMichael Lange   PetscSF         sfLabel;
18107937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
18117937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18127937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18137937d9ceSMichael Lange   PetscInt       *rootStrata;
1814d67d17b1SMatthew G. Knepley   const char     *lname;
18157937d9ceSMichael Lange   char           *name;
18167937d9ceSMichael Lange   PetscInt        nameSize;
18177937d9ceSMichael Lange   size_t          len = 0;
18189852e123SBarry Smith   PetscMPIInt     rank, size;
18197937d9ceSMichael Lange 
18207937d9ceSMichael Lange   PetscFunctionBegin;
1821d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1822d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
18239566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
18249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
18259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
18267937d9ceSMichael Lange   /* Bcast name */
1827dd400576SPatrick Sanan   if (rank == 0) {
18289566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
18299566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1830d67d17b1SMatthew G. Knepley   }
18317937d9ceSMichael Lange   nameSize = len;
18329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
18339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
18349566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
18359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
18369566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
18379566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
18387937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
18397937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
18407937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
18419566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
18429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1843dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
18447937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
18458212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
18468212dd46SStefano Zampini 
18478212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
18488212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
18497937d9ceSMichael Lange   }
18509566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
18519566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
18527937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
18539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
18549566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
18559566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
18569566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
18579566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
18587937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
18599566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
18607937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
18617937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
18627937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
18639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
18649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
18659566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
18667937d9ceSMichael Lange     }
18677937d9ceSMichael Lange     idx += rootDegree[p];
18687937d9ceSMichael Lange   }
18699566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
18709566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18719566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18729566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
18737937d9ceSMichael Lange   PetscFunctionReturn(0);
18747937d9ceSMichael Lange }
18757937d9ceSMichael Lange 
1876d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1877d71ae5a4SJacob Faibussowitsch {
1878d42890abSMatthew G. Knepley   const PetscInt *degree;
1879d42890abSMatthew G. Knepley   const PetscInt *points;
1880d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1881d42890abSMatthew G. Knepley 
1882d42890abSMatthew G. Knepley   PetscFunctionBegin;
1883d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1884d42890abSMatthew G. Knepley   /* Add in leaves */
1885d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1886d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1887d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1888d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1889d42890abSMatthew G. Knepley   }
1890d42890abSMatthew G. Knepley   /* Add in shared roots */
1891d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1892d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1893d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1894d42890abSMatthew G. Knepley     if (degree[r]) {
1895d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1896d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1897d42890abSMatthew G. Knepley     }
1898d42890abSMatthew G. Knepley   }
1899d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1900d42890abSMatthew G. Knepley }
1901d42890abSMatthew G. Knepley 
1902d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1903d71ae5a4SJacob Faibussowitsch {
1904d42890abSMatthew G. Knepley   const PetscInt *degree;
1905d42890abSMatthew G. Knepley   const PetscInt *points;
1906d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1907d42890abSMatthew G. Knepley 
1908d42890abSMatthew G. Knepley   PetscFunctionBegin;
1909d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1910d42890abSMatthew G. Knepley   /* Read out leaves */
1911d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1912d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1913d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1914d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1915d42890abSMatthew G. Knepley 
1916d42890abSMatthew G. Knepley     if (cval != defVal) {
1917d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1918d42890abSMatthew G. Knepley       if (val == defVal) {
1919d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
192048a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
1921d42890abSMatthew G. Knepley       }
1922d42890abSMatthew G. Knepley     }
1923d42890abSMatthew G. Knepley   }
1924d42890abSMatthew G. Knepley   /* Read out shared roots */
1925d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1926d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1927d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1928d42890abSMatthew G. Knepley     if (degree[r]) {
1929d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
1930d42890abSMatthew G. Knepley 
1931d42890abSMatthew G. Knepley       if (cval != defVal) {
1932d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
1933d42890abSMatthew G. Knepley         if (val == defVal) {
1934d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
193548a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
1936d42890abSMatthew G. Knepley         }
1937d42890abSMatthew G. Knepley       }
1938d42890abSMatthew G. Knepley     }
1939d42890abSMatthew G. Knepley   }
1940d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1941d42890abSMatthew G. Knepley }
1942d42890abSMatthew G. Knepley 
1943d42890abSMatthew G. Knepley /*@
1944d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
1945d42890abSMatthew G. Knepley 
1946d42890abSMatthew G. Knepley   Collective on sf
1947d42890abSMatthew G. Knepley 
1948d42890abSMatthew G. Knepley   Input Parameters:
1949d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1950d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1951d42890abSMatthew G. Knepley 
1952d42890abSMatthew G. Knepley   Level: intermediate
1953d42890abSMatthew G. Knepley 
1954db781477SPatrick Sanan .seealso: `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
1955d42890abSMatthew G. Knepley @*/
1956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
1957d71ae5a4SJacob Faibussowitsch {
1958d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
1959d42890abSMatthew G. Knepley   PetscMPIInt size;
1960d42890abSMatthew G. Knepley 
1961d42890abSMatthew G. Knepley   PetscFunctionBegin;
1962d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
1963d42890abSMatthew G. Knepley   if (size > 1) {
1964d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
1965d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
1966d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
1967d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
1968d42890abSMatthew G. Knepley   }
1969d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1970d42890abSMatthew G. Knepley }
1971d42890abSMatthew G. Knepley 
1972d42890abSMatthew G. Knepley /*@
1973d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
1974d42890abSMatthew G. Knepley 
1975d42890abSMatthew G. Knepley   Collective on sf
1976d42890abSMatthew G. Knepley 
1977d42890abSMatthew G. Knepley   Input Parameters:
1978d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1979d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1980d42890abSMatthew G. Knepley 
1981d42890abSMatthew G. Knepley   Level: intermediate
1982d42890abSMatthew G. Knepley 
1983db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
1984d42890abSMatthew G. Knepley @*/
1985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
1986d71ae5a4SJacob Faibussowitsch {
1987d42890abSMatthew G. Knepley   PetscFunctionBegin;
1988d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
1989d42890abSMatthew G. Knepley   label->propArray = NULL;
1990d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1991d42890abSMatthew G. Knepley }
1992d42890abSMatthew G. Knepley 
1993d42890abSMatthew G. Knepley /*@C
1994d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
1995d42890abSMatthew G. Knepley 
1996d42890abSMatthew G. Knepley   Collective on sf
1997d42890abSMatthew G. Knepley 
1998d42890abSMatthew G. Knepley   Input Parameters:
1999d42890abSMatthew G. Knepley + label     - The DMLabel to propagate across processes
2000d42890abSMatthew G. Knepley . sf        - The SF describing parallel layout of the label points
2001ef1023bdSBarry Smith . markPoint - An optional callback that is called when a point is marked, or NULL
2002d42890abSMatthew G. Knepley - ctx       - An optional user context for the callback, or NULL
2003d42890abSMatthew G. Knepley 
2004d42890abSMatthew G. Knepley   Calling sequence of markPoint:
2005d42890abSMatthew G. Knepley $ markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
2006d42890abSMatthew G. Knepley 
2007d42890abSMatthew G. Knepley + label - The DMLabel
2008d42890abSMatthew G. Knepley . p     - The point being marked
2009d42890abSMatthew G. Knepley . val   - The label value for p
2010d42890abSMatthew G. Knepley - ctx   - An optional user context
2011d42890abSMatthew G. Knepley 
2012d42890abSMatthew G. Knepley   Level: intermediate
2013d42890abSMatthew G. Knepley 
2014db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2015d42890abSMatthew G. Knepley @*/
2016d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2017d71ae5a4SJacob Faibussowitsch {
2018c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
2019d42890abSMatthew G. Knepley   PetscMPIInt size;
2020d42890abSMatthew G. Knepley 
2021d42890abSMatthew G. Knepley   PetscFunctionBegin;
2022d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
2023c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2024c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2025d42890abSMatthew G. Knepley     /* Communicate marked edges
2026d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2027d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2028d42890abSMatthew G. Knepley 
2029d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2030d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2031d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2032d42890abSMatthew G. Knepley 
2033d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2034d42890abSMatthew 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
2035d42890abSMatthew G. Knepley        edge to the queue.
2036d42890abSMatthew G. Knepley     */
2037d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2038d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2039d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2040d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2041d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
2042d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2043d42890abSMatthew G. Knepley   }
2044d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
2045d42890abSMatthew G. Knepley }
2046d42890abSMatthew G. Knepley 
204784f0b6dfSMatthew G. Knepley /*@
204884f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
204984f0b6dfSMatthew G. Knepley 
20505b5e7992SMatthew G. Knepley   Not collective
20515b5e7992SMatthew G. Knepley 
205284f0b6dfSMatthew G. Knepley   Input Parameter:
205384f0b6dfSMatthew G. Knepley . label - the DMLabel
205484f0b6dfSMatthew G. Knepley 
205584f0b6dfSMatthew G. Knepley   Output Parameters:
205684f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
205784f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
205884f0b6dfSMatthew G. Knepley 
205984f0b6dfSMatthew G. Knepley   Level: developer
206084f0b6dfSMatthew G. Knepley 
2061db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
206284f0b6dfSMatthew G. Knepley @*/
2063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2064d71ae5a4SJacob Faibussowitsch {
2065c58f1c22SToby Isaac   IS              vIS;
2066c58f1c22SToby Isaac   const PetscInt *values;
2067c58f1c22SToby Isaac   PetscInt       *points;
2068c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2069c58f1c22SToby Isaac 
2070c58f1c22SToby Isaac   PetscFunctionBegin;
2071d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
20729566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
20739566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
20749566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
20759371c9d4SSatish Balay   if (nV) {
20769371c9d4SSatish Balay     vS = values[0];
20779371c9d4SSatish Balay     vE = values[0] + 1;
20789371c9d4SSatish Balay   }
2079c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2080c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2081c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2082c58f1c22SToby Isaac   }
20839566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
20849566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2085c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2086c58f1c22SToby Isaac     PetscInt n;
2087c58f1c22SToby Isaac 
20889566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
20899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2090c58f1c22SToby Isaac   }
20919566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
20929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
20939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2094c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2095c58f1c22SToby Isaac     IS              is;
2096c58f1c22SToby Isaac     const PetscInt *spoints;
2097c58f1c22SToby Isaac     PetscInt        dof, off, p;
2098c58f1c22SToby Isaac 
20999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
21009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
21019566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
21029566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2103c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
21049566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
21059566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2106c58f1c22SToby Isaac   }
21079566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
21089566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
21099566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
2110c58f1c22SToby Isaac   PetscFunctionReturn(0);
2111c58f1c22SToby Isaac }
2112c58f1c22SToby Isaac 
211384f0b6dfSMatthew G. Knepley /*@
2114c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2115c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
2116c58f1c22SToby Isaac 
21175b5e7992SMatthew G. Knepley   Collective on sf
21185b5e7992SMatthew G. Knepley 
2119c58f1c22SToby Isaac   Input Parameters:
2120c58f1c22SToby Isaac + s - The PetscSection for the local field layout
2121c58f1c22SToby Isaac . sf - The SF describing parallel layout of the section points
2122c58f1c22SToby Isaac . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
2123c58f1c22SToby Isaac . label - The label specifying the points
2124c58f1c22SToby Isaac - labelValue - The label stratum specifying the points
2125c58f1c22SToby Isaac 
2126c58f1c22SToby Isaac   Output Parameter:
2127c58f1c22SToby Isaac . gsection - The PetscSection for the global field layout
2128c58f1c22SToby Isaac 
2129c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
2130c58f1c22SToby Isaac 
2131c58f1c22SToby Isaac   Level: developer
2132c58f1c22SToby Isaac 
2133db781477SPatrick Sanan .seealso: `PetscSectionCreate()`
2134c58f1c22SToby Isaac @*/
2135d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2136d71ae5a4SJacob Faibussowitsch {
2137c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2138c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2139c58f1c22SToby Isaac 
2140c58f1c22SToby Isaac   PetscFunctionBegin;
2141d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2142d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2143d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
21449566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
21459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
21469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
21479566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2148c58f1c22SToby Isaac   if (nroots >= 0) {
214963a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
21509566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2151c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
21529566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2153c58f1c22SToby Isaac     } else {
2154c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2155c58f1c22SToby Isaac     }
2156c58f1c22SToby Isaac   }
2157c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2158c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2159c58f1c22SToby Isaac     PetscInt value;
2160c58f1c22SToby Isaac 
21619566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2162c58f1c22SToby Isaac     if (value != labelValue) continue;
21639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
21649566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
21659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
21669566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2167c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2168c58f1c22SToby Isaac   }
21699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2170c58f1c22SToby Isaac   if (nroots >= 0) {
21719566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
21729566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2173c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
21749371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
21759371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
21769371c9d4SSatish Balay       }
2177c58f1c22SToby Isaac     }
2178c58f1c22SToby Isaac   }
2179c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
2180c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2181c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2182c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2183c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2184c58f1c22SToby Isaac   }
21859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2186c58f1c22SToby Isaac   globalOff -= off;
2187c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2188c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2189c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2190c58f1c22SToby Isaac   }
2191c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2192c58f1c22SToby Isaac   if (nroots >= 0) {
21939566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
21949566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2195c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
21969371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
21979371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
21989371c9d4SSatish Balay       }
2199c58f1c22SToby Isaac     }
2200c58f1c22SToby Isaac   }
22019566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
22029566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
2203c58f1c22SToby Isaac   PetscFunctionReturn(0);
2204c58f1c22SToby Isaac }
2205c58f1c22SToby Isaac 
22069371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
22075fdea053SToby Isaac   DMLabel              label;
22085fdea053SToby Isaac   PetscCopyMode       *modes;
22095fdea053SToby Isaac   PetscInt            *sizes;
22105fdea053SToby Isaac   const PetscInt    ***perms;
22115fdea053SToby Isaac   const PetscScalar ***rots;
22125fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
22135fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
22145fdea053SToby Isaac } PetscSectionSym_Label;
22155fdea053SToby Isaac 
2216d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
2217d71ae5a4SJacob Faibussowitsch {
22185fdea053SToby Isaac   PetscInt               i, j;
22195fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
22205fdea053SToby Isaac 
22215fdea053SToby Isaac   PetscFunctionBegin;
22225fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
22235fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
22245fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22259566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
22269566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
22275fdea053SToby Isaac       }
22285fdea053SToby Isaac       if (sl->perms[i]) {
22295fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
22305fdea053SToby Isaac 
22319566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
22325fdea053SToby Isaac       }
22335fdea053SToby Isaac       if (sl->rots[i]) {
22345fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
22355fdea053SToby Isaac 
22369566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
22375fdea053SToby Isaac       }
22385fdea053SToby Isaac     }
22395fdea053SToby Isaac   }
22409566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
22419566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
22425fdea053SToby Isaac   sl->numStrata = 0;
22435fdea053SToby Isaac   PetscFunctionReturn(0);
22445fdea053SToby Isaac }
22455fdea053SToby Isaac 
2246d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
2247d71ae5a4SJacob Faibussowitsch {
22485fdea053SToby Isaac   PetscFunctionBegin;
22499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
22509566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
22515fdea053SToby Isaac   PetscFunctionReturn(0);
22525fdea053SToby Isaac }
22535fdea053SToby Isaac 
2254d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
2255d71ae5a4SJacob Faibussowitsch {
22565fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
22575fdea053SToby Isaac   PetscBool              isAscii;
22585fdea053SToby Isaac   DMLabel                label = sl->label;
2259d67d17b1SMatthew G. Knepley   const char            *name;
22605fdea053SToby Isaac 
22615fdea053SToby Isaac   PetscFunctionBegin;
22629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
22635fdea053SToby Isaac   if (isAscii) {
22645fdea053SToby Isaac     PetscInt          i, j, k;
22655fdea053SToby Isaac     PetscViewerFormat format;
22665fdea053SToby Isaac 
22679566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
22685fdea053SToby Isaac     if (label) {
22699566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
22705fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22719566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
22729566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
22739566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
22745fdea053SToby Isaac       } else {
22759566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
22769566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
22775fdea053SToby Isaac       }
22785fdea053SToby Isaac     } else {
22799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
22805fdea053SToby Isaac     }
22819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
22825fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
22835fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
22845fdea053SToby Isaac 
22855fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
228663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
22875fdea053SToby Isaac       } else {
228863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
22899566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
229063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
22915fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22929566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
22935fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22945fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
229563a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
22965fdea053SToby Isaac             } else {
22975fdea053SToby Isaac               PetscInt tab;
22985fdea053SToby Isaac 
229963a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
23009566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
23019566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
23025fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
23039566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
23049566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
230563a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
23069566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
23079566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
23085fdea053SToby Isaac               }
23095fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
23109566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
23119566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
23125fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
231363a3b9bcSJacob 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])));
23145fdea053SToby Isaac #else
231563a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
23165fdea053SToby Isaac #endif
23179566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
23189566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
23195fdea053SToby Isaac               }
23209566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
23215fdea053SToby Isaac             }
23225fdea053SToby Isaac           }
23239566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
23245fdea053SToby Isaac         }
23259566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
23265fdea053SToby Isaac       }
23275fdea053SToby Isaac     }
23289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
23295fdea053SToby Isaac   }
23305fdea053SToby Isaac   PetscFunctionReturn(0);
23315fdea053SToby Isaac }
23325fdea053SToby Isaac 
23335fdea053SToby Isaac /*@
23345fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
23355fdea053SToby Isaac 
23365fdea053SToby Isaac   Logically collective on sym
23375fdea053SToby Isaac 
23385fdea053SToby Isaac   Input parameters:
23395fdea053SToby Isaac + sym - the section symmetries
23405fdea053SToby Isaac - label - the DMLabel describing the types of points
23415fdea053SToby Isaac 
23425fdea053SToby Isaac   Level: developer:
23435fdea053SToby Isaac 
2344db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
23455fdea053SToby Isaac @*/
2346d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
2347d71ae5a4SJacob Faibussowitsch {
23485fdea053SToby Isaac   PetscSectionSym_Label *sl;
23495fdea053SToby Isaac 
23505fdea053SToby Isaac   PetscFunctionBegin;
23515fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
23525fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
23539566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
23545fdea053SToby Isaac   if (label) {
23555fdea053SToby Isaac     sl->label = label;
23569566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
23579566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
23589566063dSJacob 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));
23599566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
23609566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
23619566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
23629566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
23639566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
23645fdea053SToby Isaac   }
23655fdea053SToby Isaac   PetscFunctionReturn(0);
23665fdea053SToby Isaac }
23675fdea053SToby Isaac 
23685fdea053SToby Isaac /*@C
2369b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2370b004864fSMatthew G. Knepley 
2371b004864fSMatthew G. Knepley   Logically collective on sym
2372b004864fSMatthew G. Knepley 
2373b004864fSMatthew G. Knepley   Input Parameters:
2374b004864fSMatthew G. Knepley + sym       - the section symmetries
2375b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2376b004864fSMatthew G. Knepley 
2377b004864fSMatthew G. Knepley   Output Parameters:
2378b004864fSMatthew G. Knepley + size      - the number of dofs for points in the stratum of the label
2379b004864fSMatthew G. Knepley . minOrient - the smallest orientation for a point in this stratum
2380b004864fSMatthew G. Knepley . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2381b004864fSMatthew G. Knepley . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2382b004864fSMatthew 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
2383b004864fSMatthew G. Knepley 
2384b004864fSMatthew G. Knepley   Level: developer
2385b004864fSMatthew G. Knepley 
2386db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2387b004864fSMatthew G. Knepley @*/
2388d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2389d71ae5a4SJacob Faibussowitsch {
2390b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2391b004864fSMatthew G. Knepley   const char            *name;
2392b004864fSMatthew G. Knepley   PetscInt               i;
2393b004864fSMatthew G. Knepley 
2394b004864fSMatthew G. Knepley   PetscFunctionBegin;
2395b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2396b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2397b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2398b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2399b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2400b004864fSMatthew G. Knepley 
2401b004864fSMatthew G. Knepley     if (stratum == value) break;
2402b004864fSMatthew G. Knepley   }
24039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2404b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
24059371c9d4SSatish Balay   if (size) {
24069371c9d4SSatish Balay     PetscValidIntPointer(size, 3);
24079371c9d4SSatish Balay     *size = sl->sizes[i];
24089371c9d4SSatish Balay   }
24099371c9d4SSatish Balay   if (minOrient) {
24109371c9d4SSatish Balay     PetscValidIntPointer(minOrient, 4);
24119371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
24129371c9d4SSatish Balay   }
24139371c9d4SSatish Balay   if (maxOrient) {
24149371c9d4SSatish Balay     PetscValidIntPointer(maxOrient, 5);
24159371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
24169371c9d4SSatish Balay   }
24179371c9d4SSatish Balay   if (perms) {
24189371c9d4SSatish Balay     PetscValidPointer(perms, 6);
24199371c9d4SSatish Balay     *perms = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;
24209371c9d4SSatish Balay   }
24219371c9d4SSatish Balay   if (rots) {
24229371c9d4SSatish Balay     PetscValidPointer(rots, 7);
24239371c9d4SSatish Balay     *rots = sl->rots[i] ? &sl->rots[i][sl->minMaxOrients[i][0]] : NULL;
24249371c9d4SSatish Balay   }
2425b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2426b004864fSMatthew G. Knepley }
2427b004864fSMatthew G. Knepley 
2428b004864fSMatthew G. Knepley /*@C
24295fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
24305fdea053SToby Isaac 
24315b5e7992SMatthew G. Knepley   Logically collective on sym
24325fdea053SToby Isaac 
24335fdea053SToby Isaac   InputParameters:
24345b5e7992SMatthew G. Knepley + sym       - the section symmetries
24355fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
24365fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
24375fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
24385fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
24395fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
24405fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2441a2b725a8SWilliam 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
24425fdea053SToby Isaac 
24435fdea053SToby Isaac   Level: developer
24445fdea053SToby Isaac 
2445db781477SPatrick Sanan .seealso: `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
24465fdea053SToby Isaac @*/
2447d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
2448d71ae5a4SJacob Faibussowitsch {
24495fdea053SToby Isaac   PetscSectionSym_Label *sl;
2450d67d17b1SMatthew G. Knepley   const char            *name;
2451d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
24525fdea053SToby Isaac 
24535fdea053SToby Isaac   PetscFunctionBegin;
24545fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
24555fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2456b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
24575fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
24585fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
24595fdea053SToby Isaac 
24605fdea053SToby Isaac     if (stratum == value) break;
24615fdea053SToby Isaac   }
24629566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
246363a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
24645fdea053SToby Isaac   sl->sizes[i]            = size;
24655fdea053SToby Isaac   sl->modes[i]            = mode;
24665fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
24675fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
24685fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
24695fdea053SToby Isaac     if (perms) {
24705fdea053SToby Isaac       PetscInt **ownPerms;
24715fdea053SToby Isaac 
24729566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
24735fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
24745fdea053SToby Isaac         if (perms[j]) {
24759566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2476ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
24775fdea053SToby Isaac         }
24785fdea053SToby Isaac       }
24795fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
24805fdea053SToby Isaac     }
24815fdea053SToby Isaac     if (rots) {
24825fdea053SToby Isaac       PetscScalar **ownRots;
24835fdea053SToby Isaac 
24849566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
24855fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
24865fdea053SToby Isaac         if (rots[j]) {
24879566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2488ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
24895fdea053SToby Isaac         }
24905fdea053SToby Isaac       }
24915fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
24925fdea053SToby Isaac     }
24935fdea053SToby Isaac   } else {
24945fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
24955fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
24965fdea053SToby Isaac   }
24975fdea053SToby Isaac   PetscFunctionReturn(0);
24985fdea053SToby Isaac }
24995fdea053SToby Isaac 
2500d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
2501d71ae5a4SJacob Faibussowitsch {
25025fdea053SToby Isaac   PetscInt               i, j, numStrata;
25035fdea053SToby Isaac   PetscSectionSym_Label *sl;
25045fdea053SToby Isaac   DMLabel                label;
25055fdea053SToby Isaac 
25065fdea053SToby Isaac   PetscFunctionBegin;
25075fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
25085fdea053SToby Isaac   numStrata = sl->numStrata;
25095fdea053SToby Isaac   label     = sl->label;
25105fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
25115fdea053SToby Isaac     PetscInt point = points[2 * i];
25125fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
25135fdea053SToby Isaac 
25145fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
25155fdea053SToby Isaac       if (label->validIS[j]) {
25165fdea053SToby Isaac         PetscInt k;
25175fdea053SToby Isaac 
25189566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j], point, &k));
25195fdea053SToby Isaac         if (k >= 0) break;
25205fdea053SToby Isaac       } else {
25215fdea053SToby Isaac         PetscBool has;
25225fdea053SToby Isaac 
25239566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
25245fdea053SToby Isaac         if (has) break;
25255fdea053SToby Isaac       }
25265fdea053SToby Isaac     }
25279371c9d4SSatish 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],
25289371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2529ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2530ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
25315fdea053SToby Isaac   }
25325fdea053SToby Isaac   PetscFunctionReturn(0);
25335fdea053SToby Isaac }
25345fdea053SToby Isaac 
2535d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2536d71ae5a4SJacob Faibussowitsch {
2537b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2538b004864fSMatthew G. Knepley   IS                     valIS;
2539b004864fSMatthew G. Knepley   const PetscInt        *values;
2540b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2541b004864fSMatthew G. Knepley 
2542b004864fSMatthew G. Knepley   PetscFunctionBegin;
25439566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
25449566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
25459566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2546b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2547b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2548b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2549b004864fSMatthew G. Knepley     const PetscInt    **perms;
2550b004864fSMatthew G. Knepley     const PetscScalar **rots;
2551b004864fSMatthew G. Knepley 
25529566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
25539566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2554b004864fSMatthew G. Knepley   }
25559566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
2556b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2557b004864fSMatthew G. Knepley }
2558b004864fSMatthew G. Knepley 
2559d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2560d71ae5a4SJacob Faibussowitsch {
2561b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2562b004864fSMatthew G. Knepley   DMLabel                dlabel;
2563b004864fSMatthew G. Knepley 
2564b004864fSMatthew G. Knepley   PetscFunctionBegin;
25659566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
25669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
25679566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
25689566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
2569b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2570b004864fSMatthew G. Knepley }
2571b004864fSMatthew G. Knepley 
2572d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
2573d71ae5a4SJacob Faibussowitsch {
25745fdea053SToby Isaac   PetscSectionSym_Label *sl;
25755fdea053SToby Isaac 
25765fdea053SToby Isaac   PetscFunctionBegin;
25774dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
25785fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2579b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2580b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
25815fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
25825fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
25835fdea053SToby Isaac   sym->data            = (void *)sl;
25845fdea053SToby Isaac   PetscFunctionReturn(0);
25855fdea053SToby Isaac }
25865fdea053SToby Isaac 
25875fdea053SToby Isaac /*@
25885fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
25895fdea053SToby Isaac 
25905fdea053SToby Isaac   Collective
25915fdea053SToby Isaac 
25925fdea053SToby Isaac   Input Parameters:
25935fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
25945fdea053SToby Isaac - label - the label defining the strata
25955fdea053SToby Isaac 
25965fdea053SToby Isaac   Output Parameters:
25975fdea053SToby Isaac . sym - the section symmetries
25985fdea053SToby Isaac 
25995fdea053SToby Isaac   Level: developer
26005fdea053SToby Isaac 
2601db781477SPatrick Sanan .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
26025fdea053SToby Isaac @*/
2603d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
2604d71ae5a4SJacob Faibussowitsch {
26055fdea053SToby Isaac   PetscFunctionBegin;
26069566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
26079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
26089566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
26099566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
26105fdea053SToby Isaac   PetscFunctionReturn(0);
26115fdea053SToby Isaac }
2612