xref: /petsc/src/dm/label/dmlabel.c (revision ef1023bda9d7138933c4c6fa7b7cf4a26d60c86d)
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 @*/
27d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
28c58f1c22SToby Isaac {
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 */
66c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
67c58f1c22SToby Isaac {
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 */
114c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
115c58f1c22SToby Isaac {
116c58f1c22SToby Isaac   PetscInt       v;
117c58f1c22SToby Isaac 
118c58f1c22SToby Isaac   PetscFunctionBegin;
119c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; v++) {
1209566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeValid_Private(label, v));
121c58f1c22SToby Isaac   }
122c58f1c22SToby Isaac   PetscFunctionReturn(0);
123c58f1c22SToby Isaac }
124c58f1c22SToby Isaac 
125c58f1c22SToby Isaac /*
126c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
127c58f1c22SToby Isaac 
1285b5e7992SMatthew G. Knepley   Not collective
1295b5e7992SMatthew G. Knepley 
130c58f1c22SToby Isaac   Input parameter:
131c58f1c22SToby Isaac + label - The DMLabel
132c58f1c22SToby Isaac - v - The stratum value
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Output parameter:
135c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
136c58f1c22SToby Isaac 
137c58f1c22SToby Isaac   Level: developer
138c58f1c22SToby Isaac 
139db781477SPatrick Sanan .seealso: `DMLabelCreate()`
140c58f1c22SToby Isaac */
141c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
142c58f1c22SToby Isaac {
143c58f1c22SToby Isaac   PetscInt       p;
144ad8374ffSToby Isaac   const PetscInt *points;
145c58f1c22SToby Isaac 
146b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
147c58f1c22SToby Isaac   PetscFunctionBegin;
1481dca8a05SBarry 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);
149ad8374ffSToby Isaac   if (label->points[v]) {
1509566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
151e8f14785SLisandro Dalcin     for (p = 0; p < label->stratumSizes[v]; ++p) {
1529566063dSJacob Faibussowitsch       PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
153e8f14785SLisandro Dalcin     }
1549566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v],&points));
1559566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&(label->points[v])));
156ad8374ffSToby Isaac   }
157ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
158c58f1c22SToby Isaac   PetscFunctionReturn(0);
159c58f1c22SToby Isaac }
160c58f1c22SToby Isaac 
161695799ffSMatthew G. Knepley PetscErrorCode DMLabelMakeAllInvalid_Internal(DMLabel label)
162695799ffSMatthew G. Knepley {
163695799ffSMatthew G. Knepley   PetscInt v;
164695799ffSMatthew G. Knepley 
165695799ffSMatthew G. Knepley   PetscFunctionBegin;
166695799ffSMatthew G. Knepley   for (v = 0; v < label->numStrata; v++) {
167695799ffSMatthew G. Knepley     PetscCall(DMLabelMakeInvalid_Private(label, v));
168695799ffSMatthew G. Knepley   }
169695799ffSMatthew G. Knepley   PetscFunctionReturn(0);
170695799ffSMatthew G. Knepley }
171695799ffSMatthew G. Knepley 
172b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
173b9907514SLisandro Dalcin #define DMLABEL_LOOKUP_THRESHOLD 16
174b9907514SLisandro Dalcin #endif
175b9907514SLisandro Dalcin 
1769fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
1770c3c4a36SLisandro Dalcin {
1780c3c4a36SLisandro Dalcin   PetscInt       v;
1790e79e033SBarry Smith 
1800c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1810e79e033SBarry Smith   *index = -1;
182b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
183b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
184b9907514SLisandro Dalcin       if (label->stratumValues[v] == value) {*index = v; break;}
185b9907514SLisandro Dalcin   } else {
1869566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(label->hmap, value, index));
1870e79e033SBarry Smith   }
18876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */
18990e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
1909566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(label->hmap, &len));
19108401ef6SPierre Jolivet     PetscCheck(len == label->numStrata,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
19290e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
1939566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(label->hmap, value, &loc));
19490e9b2aeSLisandro Dalcin     } else {
19590e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
19690e9b2aeSLisandro Dalcin         if (label->stratumValues[v] == value) {loc = v; break;}
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 
2039fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
204c58f1c22SToby Isaac {
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 
2619fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
262b9907514SLisandro Dalcin {
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 
2699fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
2709e63cc69SVaclav Hapla {
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 @*/
2930c3c4a36SLisandro Dalcin PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
2940c3c4a36SLisandro Dalcin {
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 @*/
317b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
318b9907514SLisandro Dalcin {
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 {
358b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3599566063dSJacob Faibussowitsch       PetscCall(DMLabelAddStratum(label, values[v]));
360b9907514SLisandro Dalcin     }
361b9907514SLisandro Dalcin   }
3629566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
363b9907514SLisandro Dalcin   PetscFunctionReturn(0);
364b9907514SLisandro Dalcin }
365b9907514SLisandro Dalcin 
366b9907514SLisandro Dalcin /*@
367b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
368b9907514SLisandro Dalcin 
3695b5e7992SMatthew G. Knepley   Not collective
3705b5e7992SMatthew G. Knepley 
371d8d19677SJose E. Roman   Input Parameters:
372b9907514SLisandro Dalcin + label - The DMLabel
373b9907514SLisandro Dalcin - valueIS - Index set with stratum values
374b9907514SLisandro Dalcin 
375b9907514SLisandro Dalcin   Level: beginner
376b9907514SLisandro Dalcin 
377db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
378b9907514SLisandro Dalcin @*/
379b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
380b9907514SLisandro Dalcin {
381b9907514SLisandro Dalcin   PetscInt       numStrata;
382b9907514SLisandro Dalcin   const PetscInt *stratumValues;
383b9907514SLisandro Dalcin 
384b9907514SLisandro Dalcin   PetscFunctionBegin;
385b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
386b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
3879566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(valueIS, &numStrata));
3889566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valueIS, &stratumValues));
3899566063dSJacob Faibussowitsch   PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
390c58f1c22SToby Isaac   PetscFunctionReturn(0);
391c58f1c22SToby Isaac }
392c58f1c22SToby Isaac 
393c58f1c22SToby Isaac static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer)
394c58f1c22SToby Isaac {
395c58f1c22SToby Isaac   PetscInt       v;
396c58f1c22SToby Isaac   PetscMPIInt    rank;
397c58f1c22SToby Isaac 
398c58f1c22SToby Isaac   PetscFunctionBegin;
3999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
4009566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
401c58f1c22SToby Isaac   if (label) {
402d67d17b1SMatthew G. Knepley     const char *name;
403d67d17b1SMatthew G. Knepley 
4049566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &name));
4059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
40663a3b9bcSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", label->pStart, label->pEnd));
407c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
408c58f1c22SToby Isaac       const PetscInt value = label->stratumValues[v];
409ad8374ffSToby Isaac       const PetscInt *points;
410c58f1c22SToby Isaac       PetscInt       p;
411c58f1c22SToby Isaac 
4129566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
413c58f1c22SToby Isaac       for (p = 0; p < label->stratumSizes[v]; ++p) {
41463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, points[p], value));
415c58f1c22SToby Isaac       }
4169566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v],&points));
417c58f1c22SToby Isaac     }
418c58f1c22SToby Isaac   }
4199566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4209566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
421c58f1c22SToby Isaac   PetscFunctionReturn(0);
422c58f1c22SToby Isaac }
423c58f1c22SToby Isaac 
424c58f1c22SToby Isaac /*@C
425c58f1c22SToby Isaac   DMLabelView - View the label
426c58f1c22SToby Isaac 
4275b5e7992SMatthew G. Knepley   Collective on viewer
4285b5e7992SMatthew G. Knepley 
429c58f1c22SToby Isaac   Input Parameters:
430c58f1c22SToby Isaac + label - The DMLabel
431c58f1c22SToby Isaac - viewer - The PetscViewer
432c58f1c22SToby Isaac 
433c58f1c22SToby Isaac   Level: intermediate
434c58f1c22SToby Isaac 
435db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
436c58f1c22SToby Isaac @*/
437c58f1c22SToby Isaac PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
438c58f1c22SToby Isaac {
439c58f1c22SToby Isaac   PetscBool      iascii;
440c58f1c22SToby Isaac 
441c58f1c22SToby Isaac   PetscFunctionBegin;
442d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4439566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
444c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4459566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
4469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
4471baa6e33SBarry Smith   if (iascii) PetscCall(DMLabelView_Ascii(label, viewer));
448c58f1c22SToby Isaac   PetscFunctionReturn(0);
449c58f1c22SToby Isaac }
450c58f1c22SToby Isaac 
45184f0b6dfSMatthew G. Knepley /*@
452d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
453d67d17b1SMatthew G. Knepley 
4545b5e7992SMatthew G. Knepley   Not collective
4555b5e7992SMatthew G. Knepley 
456d67d17b1SMatthew G. Knepley   Input Parameter:
457d67d17b1SMatthew G. Knepley . label - The DMLabel
458d67d17b1SMatthew G. Knepley 
459d67d17b1SMatthew G. Knepley   Level: beginner
460d67d17b1SMatthew G. Knepley 
461db781477SPatrick Sanan .seealso: `DMLabelDestroy()`, `DMLabelCreate()`
462d67d17b1SMatthew G. Knepley @*/
463d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelReset(DMLabel label)
464d67d17b1SMatthew G. Knepley {
465d67d17b1SMatthew G. Knepley   PetscInt       v;
466d67d17b1SMatthew G. Knepley 
467d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
468d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
469d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
4709566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&label->ht[v]));
4719566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
472d67d17b1SMatthew G. Knepley   }
473b9907514SLisandro Dalcin   label->numStrata = 0;
4749566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
4759566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
4769566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
4779566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
4789566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
479f9244615SMatthew G. Knepley   label->stratumValues = NULL;
480f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
481f9244615SMatthew G. Knepley   label->ht            = NULL;
482f9244615SMatthew G. Knepley   label->points        = NULL;
483f9244615SMatthew G. Knepley   label->validIS       = NULL;
4849566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
485b9907514SLisandro Dalcin   label->pStart = -1;
486b9907514SLisandro Dalcin   label->pEnd   = -1;
4879566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
488d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
489d67d17b1SMatthew G. Knepley }
490d67d17b1SMatthew G. Knepley 
491d67d17b1SMatthew G. Knepley /*@
49284f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
49384f0b6dfSMatthew G. Knepley 
4945b5e7992SMatthew G. Knepley   Collective on label
4955b5e7992SMatthew G. Knepley 
49684f0b6dfSMatthew G. Knepley   Input Parameter:
49784f0b6dfSMatthew G. Knepley . label - The DMLabel
49884f0b6dfSMatthew G. Knepley 
49984f0b6dfSMatthew G. Knepley   Level: beginner
50084f0b6dfSMatthew G. Knepley 
501db781477SPatrick Sanan .seealso: `DMLabelReset()`, `DMLabelCreate()`
50284f0b6dfSMatthew G. Knepley @*/
503c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
504c58f1c22SToby Isaac {
505c58f1c22SToby Isaac   PetscFunctionBegin;
506d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
507d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1);
508b9907514SLisandro Dalcin   if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);}
5099566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5109566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5119566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
512c58f1c22SToby Isaac   PetscFunctionReturn(0);
513c58f1c22SToby Isaac }
514c58f1c22SToby Isaac 
51584f0b6dfSMatthew G. Knepley /*@
51684f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
51784f0b6dfSMatthew G. Knepley 
5185b5e7992SMatthew G. Knepley   Collective on label
5195b5e7992SMatthew G. Knepley 
52084f0b6dfSMatthew G. Knepley   Input Parameter:
52184f0b6dfSMatthew G. Knepley . label - The DMLabel
52284f0b6dfSMatthew G. Knepley 
52384f0b6dfSMatthew G. Knepley   Output Parameter:
52484f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
52584f0b6dfSMatthew G. Knepley 
52684f0b6dfSMatthew G. Knepley   Level: intermediate
52784f0b6dfSMatthew G. Knepley 
528db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
52984f0b6dfSMatthew G. Knepley @*/
530c58f1c22SToby Isaac PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
531c58f1c22SToby Isaac {
532d67d17b1SMatthew G. Knepley   const char    *name;
533ad8374ffSToby Isaac   PetscInt       v;
534c58f1c22SToby Isaac 
535c58f1c22SToby Isaac   PetscFunctionBegin;
536d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5379566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5389566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) label, &name));
5399566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew));
540c58f1c22SToby Isaac 
541c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5425aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->ht));
5469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->points));
5479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
548c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
5499566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
550c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
551c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
5529566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) (label->points[v])));
553ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
554b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
555c58f1c22SToby Isaac   }
5569566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5579566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap));
558c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
559c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
560c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
561c58f1c22SToby Isaac   PetscFunctionReturn(0);
562c58f1c22SToby Isaac }
563c58f1c22SToby Isaac 
564609dae6eSVaclav Hapla /*@C
565609dae6eSVaclav Hapla   DMLabelCompare - Compare two DMLabel objects
566609dae6eSVaclav Hapla 
5675efe38ccSVaclav Hapla   Collective on comm
568609dae6eSVaclav Hapla 
569609dae6eSVaclav Hapla   Input Parameters:
570f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
571f1a722f8SMatthew G. Knepley . l0 - First DMLabel
572609dae6eSVaclav Hapla - l1 - Second DMLabel
573609dae6eSVaclav Hapla 
574609dae6eSVaclav Hapla   Output Parameters
5755efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
5765efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
577609dae6eSVaclav Hapla 
578609dae6eSVaclav Hapla   Level: intermediate
579609dae6eSVaclav Hapla 
580609dae6eSVaclav Hapla   Notes:
5815efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
5825efe38ccSVaclav Hapla   If it is passed as NULL and difference is found, an error is thrown on all processes.
5835efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
584609dae6eSVaclav Hapla 
5855efe38ccSVaclav Hapla   The output message is set independently on each rank.
5865efe38ccSVaclav Hapla   It is set to NULL if no difference was found on the current rank. It must be freed by user.
5875efe38ccSVaclav Hapla   If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
5885efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
589609dae6eSVaclav Hapla 
590609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
591609dae6eSVaclav Hapla 
5925efe38ccSVaclav Hapla   The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
5935efe38ccSVaclav Hapla 
594609dae6eSVaclav Hapla   Fortran Notes:
595609dae6eSVaclav Hapla   This function is currently not available from Fortran.
596609dae6eSVaclav Hapla 
597db781477SPatrick Sanan .seealso: `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
598609dae6eSVaclav Hapla @*/
5995efe38ccSVaclav Hapla PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
600609dae6eSVaclav Hapla {
601609dae6eSVaclav Hapla   const char     *name0, *name1;
602609dae6eSVaclav Hapla   char            msg[PETSC_MAX_PATH_LEN] = "";
6035efe38ccSVaclav Hapla   PetscBool       eq;
6045efe38ccSVaclav Hapla   PetscMPIInt     rank;
605609dae6eSVaclav Hapla 
606609dae6eSVaclav Hapla   PetscFunctionBegin;
6075efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
6085efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6095efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
6105efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
6119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6139566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
614609dae6eSVaclav Hapla   {
615609dae6eSVaclav Hapla     PetscInt v0, v1;
616609dae6eSVaclav Hapla 
6179566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6189566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6195efe38ccSVaclav Hapla     eq = (PetscBool) (v0 == v1);
6205efe38ccSVaclav Hapla     if (!eq) {
62163a3b9bcSJacob Faibussowitsch       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));
622609dae6eSVaclav Hapla     }
6239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6245efe38ccSVaclav Hapla     if (!eq) goto finish;
625609dae6eSVaclav Hapla   }
626609dae6eSVaclav Hapla   {
627609dae6eSVaclav Hapla     IS              is0, is1;
628609dae6eSVaclav Hapla 
6299566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6309566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6319566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6329566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6339566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
6345efe38ccSVaclav Hapla     if (!eq) {
6359566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
636609dae6eSVaclav Hapla     }
6379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6385efe38ccSVaclav Hapla     if (!eq) goto finish;
639609dae6eSVaclav Hapla   }
640609dae6eSVaclav Hapla   {
641609dae6eSVaclav Hapla     PetscInt i, nValues;
642609dae6eSVaclav Hapla 
6439566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
644609dae6eSVaclav Hapla     for (i=0; i<nValues; i++) {
645609dae6eSVaclav Hapla       const PetscInt  v = l0->stratumValues[i];
646609dae6eSVaclav Hapla       PetscInt        n;
647609dae6eSVaclav Hapla       IS              is0, is1;
648609dae6eSVaclav Hapla 
6499566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
650609dae6eSVaclav Hapla       if (!n) continue;
6519566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6529566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6539566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6549566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6559566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6565efe38ccSVaclav Hapla       if (!eq) {
65763a3b9bcSJacob 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));
6585efe38ccSVaclav Hapla         break;
659609dae6eSVaclav Hapla       }
660609dae6eSVaclav Hapla     }
6619566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
662609dae6eSVaclav Hapla   }
663609dae6eSVaclav Hapla finish:
6645efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
665609dae6eSVaclav Hapla   if (message) {
666609dae6eSVaclav Hapla     *message = NULL;
667609dae6eSVaclav Hapla     if (msg[0]) {
6689566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(msg, message));
669609dae6eSVaclav Hapla     }
6705efe38ccSVaclav Hapla   } else {
6715efe38ccSVaclav Hapla     if (msg[0]) {
6729566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
673609dae6eSVaclav Hapla     }
6749566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
6755efe38ccSVaclav Hapla   }
6765efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
6775efe38ccSVaclav Hapla   if (equal) *equal = eq;
67863a3b9bcSJacob Faibussowitsch   else PetscCheck(eq,comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal",name0,name1);
679609dae6eSVaclav Hapla   PetscFunctionReturn(0);
680609dae6eSVaclav Hapla }
681609dae6eSVaclav Hapla 
682c6a43d28SMatthew G. Knepley /*@
683c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
684c6a43d28SMatthew G. Knepley 
6855b5e7992SMatthew G. Knepley   Not collective
6865b5e7992SMatthew G. Knepley 
687c6a43d28SMatthew G. Knepley   Input Parameter:
688c6a43d28SMatthew G. Knepley . label  - The DMLabel
689c6a43d28SMatthew G. Knepley 
690c6a43d28SMatthew G. Knepley   Level: intermediate
691c6a43d28SMatthew G. Knepley 
692db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
693c6a43d28SMatthew G. Knepley @*/
694c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
695c6a43d28SMatthew G. Knepley {
696c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
697c6a43d28SMatthew G. Knepley 
698c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
699c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7009566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
701c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
702c6a43d28SMatthew G. Knepley     const PetscInt *points;
703c6a43d28SMatthew G. Knepley     PetscInt       i;
704c6a43d28SMatthew G. Knepley 
7059566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
706c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
707c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
708c6a43d28SMatthew G. Knepley 
709c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
710c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
711c6a43d28SMatthew G. Knepley     }
7129566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
713c6a43d28SMatthew G. Knepley   }
714c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
715c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7169566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
717c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
718c6a43d28SMatthew G. Knepley }
719c6a43d28SMatthew G. Knepley 
720c6a43d28SMatthew G. Knepley /*@
721c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
722c6a43d28SMatthew G. Knepley 
7235b5e7992SMatthew G. Knepley   Not collective
7245b5e7992SMatthew G. Knepley 
725c6a43d28SMatthew G. Knepley   Input Parameters:
726c6a43d28SMatthew G. Knepley + label  - The DMLabel
727c6a43d28SMatthew G. Knepley . pStart - The smallest point
728c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
729c6a43d28SMatthew G. Knepley 
730c6a43d28SMatthew G. Knepley   Level: intermediate
731c6a43d28SMatthew G. Knepley 
732db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
733c6a43d28SMatthew G. Knepley @*/
734c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
735c58f1c22SToby Isaac {
736c58f1c22SToby Isaac   PetscInt       v;
737c58f1c22SToby Isaac 
738c58f1c22SToby Isaac   PetscFunctionBegin;
739d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7409566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7419566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
742c58f1c22SToby Isaac   label->pStart = pStart;
743c58f1c22SToby Isaac   label->pEnd   = pEnd;
744c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7459566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
746c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
747ad8374ffSToby Isaac     const PetscInt *points;
748c58f1c22SToby Isaac     PetscInt       i;
749c58f1c22SToby Isaac 
7509566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
751c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
752ad8374ffSToby Isaac       const PetscInt point = points[i];
753c58f1c22SToby Isaac 
75463a3b9bcSJacob 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);
7559566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
756c58f1c22SToby Isaac     }
7579566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
758c58f1c22SToby Isaac   }
759c58f1c22SToby Isaac   PetscFunctionReturn(0);
760c58f1c22SToby Isaac }
761c58f1c22SToby Isaac 
762c6a43d28SMatthew G. Knepley /*@
763c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
764c6a43d28SMatthew G. Knepley 
7655b5e7992SMatthew G. Knepley   Not collective
7665b5e7992SMatthew G. Knepley 
767c6a43d28SMatthew G. Knepley   Input Parameter:
768c6a43d28SMatthew G. Knepley . label - the DMLabel
769c6a43d28SMatthew G. Knepley 
770c6a43d28SMatthew G. Knepley   Level: intermediate
771c6a43d28SMatthew G. Knepley 
772db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
773c6a43d28SMatthew G. Knepley @*/
774c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
775c58f1c22SToby Isaac {
776c58f1c22SToby Isaac   PetscFunctionBegin;
777d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
778c58f1c22SToby Isaac   label->pStart = -1;
779c58f1c22SToby Isaac   label->pEnd   = -1;
7809566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
781c58f1c22SToby Isaac   PetscFunctionReturn(0);
782c58f1c22SToby Isaac }
783c58f1c22SToby Isaac 
784c58f1c22SToby Isaac /*@
785c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
786c6a43d28SMatthew G. Knepley 
7875b5e7992SMatthew G. Knepley   Not collective
7885b5e7992SMatthew G. Knepley 
789c6a43d28SMatthew G. Knepley   Input Parameter:
790c6a43d28SMatthew G. Knepley . label - the DMLabel
791c6a43d28SMatthew G. Knepley 
792c6a43d28SMatthew G. Knepley   Output Parameters:
793c6a43d28SMatthew G. Knepley + pStart - The smallest point
794c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
795c6a43d28SMatthew G. Knepley 
796c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
797c6a43d28SMatthew G. Knepley 
798c6a43d28SMatthew G. Knepley   Level: intermediate
799c6a43d28SMatthew G. Knepley 
800db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
801c6a43d28SMatthew G. Knepley @*/
802c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
803c6a43d28SMatthew G. Knepley {
804c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
805c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8069566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
807c6a43d28SMatthew G. Knepley   if (pStart) {
808534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
809c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
810c6a43d28SMatthew G. Knepley   }
811c6a43d28SMatthew G. Knepley   if (pEnd) {
812534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
813c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
814c6a43d28SMatthew G. Knepley   }
815c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
816c6a43d28SMatthew G. Knepley }
817c6a43d28SMatthew G. Knepley 
818c6a43d28SMatthew G. Knepley /*@
819c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
820c58f1c22SToby Isaac 
8215b5e7992SMatthew G. Knepley   Not collective
8225b5e7992SMatthew G. Knepley 
823c58f1c22SToby Isaac   Input Parameters:
824c58f1c22SToby Isaac + label - the DMLabel
825c58f1c22SToby Isaac - value - the value
826c58f1c22SToby Isaac 
827c58f1c22SToby Isaac   Output Parameter:
828c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
829c58f1c22SToby Isaac 
830c58f1c22SToby Isaac   Level: developer
831c58f1c22SToby Isaac 
832db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
833c58f1c22SToby Isaac @*/
834c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
835c58f1c22SToby Isaac {
836c58f1c22SToby Isaac   PetscInt v;
837c58f1c22SToby Isaac 
838c58f1c22SToby Isaac   PetscFunctionBegin;
839d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
840534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8419566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8420c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
843c58f1c22SToby Isaac   PetscFunctionReturn(0);
844c58f1c22SToby Isaac }
845c58f1c22SToby Isaac 
846c58f1c22SToby Isaac /*@
847c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
848c58f1c22SToby Isaac 
8495b5e7992SMatthew G. Knepley   Not collective
8505b5e7992SMatthew G. Knepley 
851c58f1c22SToby Isaac   Input Parameters:
852c58f1c22SToby Isaac + label - the DMLabel
853c58f1c22SToby Isaac - point - the point
854c58f1c22SToby Isaac 
855c58f1c22SToby Isaac   Output Parameter:
856c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
857c58f1c22SToby Isaac 
858c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
859c58f1c22SToby Isaac 
860c58f1c22SToby Isaac   Level: developer
861c58f1c22SToby Isaac 
862db781477SPatrick Sanan .seealso: `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
863c58f1c22SToby Isaac @*/
864c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
865c58f1c22SToby Isaac {
866c58f1c22SToby Isaac   PetscFunctionBeginHot;
867d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
868534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8699566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
87076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
87128b400f6SJacob Faibussowitsch     PetscCheck(label->bt,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
87263a3b9bcSJacob 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);
87376bd3646SJed Brown   }
874c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
875c58f1c22SToby Isaac   PetscFunctionReturn(0);
876c58f1c22SToby Isaac }
877c58f1c22SToby Isaac 
878c58f1c22SToby Isaac /*@
879c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
880c58f1c22SToby Isaac 
8815b5e7992SMatthew G. Knepley   Not collective
8825b5e7992SMatthew G. Knepley 
883c58f1c22SToby Isaac   Input Parameters:
884c58f1c22SToby Isaac + label - the DMLabel
885c58f1c22SToby Isaac . value - the stratum value
886c58f1c22SToby Isaac - point - the point
887c58f1c22SToby Isaac 
888c58f1c22SToby Isaac   Output Parameter:
889c58f1c22SToby Isaac . contains - true if the stratum contains the point
890c58f1c22SToby Isaac 
891c58f1c22SToby Isaac   Level: intermediate
892c58f1c22SToby Isaac 
893db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
894c58f1c22SToby Isaac @*/
895c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
896c58f1c22SToby Isaac {
8970c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
898d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
899534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
900cffad2c9SToby Isaac   if (value == label->defaultValue) {
901cffad2c9SToby Isaac     PetscInt pointVal;
9020c3c4a36SLisandro Dalcin 
903cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
904cffad2c9SToby Isaac     *contains = (PetscBool) (pointVal == value);
905cffad2c9SToby Isaac   } else {
906cffad2c9SToby Isaac     PetscInt v;
907cffad2c9SToby Isaac 
908cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
909cffad2c9SToby Isaac     if (v >= 0) {
910ad8374ffSToby Isaac       if (label->validIS[v]) {
911c58f1c22SToby Isaac         PetscInt i;
912c58f1c22SToby Isaac 
9139566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[v], point, &i));
914cffad2c9SToby Isaac         *contains = (PetscBool) (i >= 0);
915c58f1c22SToby Isaac       } else {
916cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
917cffad2c9SToby Isaac       }
918cffad2c9SToby Isaac     } else { // value is not present
919cffad2c9SToby Isaac       *contains = PETSC_FALSE;
920cffad2c9SToby Isaac     }
921c58f1c22SToby Isaac   }
922c58f1c22SToby Isaac   PetscFunctionReturn(0);
923c58f1c22SToby Isaac }
924c58f1c22SToby Isaac 
92584f0b6dfSMatthew G. Knepley /*@
9265aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9275aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9285aa44df4SToby Isaac 
9295b5e7992SMatthew G. Knepley   Not collective
9305b5e7992SMatthew G. Knepley 
9315aa44df4SToby Isaac   Input parameter:
9325aa44df4SToby Isaac . label - a DMLabel object
9335aa44df4SToby Isaac 
9345aa44df4SToby Isaac   Output parameter:
9355aa44df4SToby Isaac . defaultValue - the default value
9365aa44df4SToby Isaac 
9375aa44df4SToby Isaac   Level: beginner
9385aa44df4SToby Isaac 
939db781477SPatrick Sanan .seealso: `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
94084f0b6dfSMatthew G. Knepley @*/
9415aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
9425aa44df4SToby Isaac {
9435aa44df4SToby Isaac   PetscFunctionBegin;
944d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9455aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9465aa44df4SToby Isaac   PetscFunctionReturn(0);
9475aa44df4SToby Isaac }
9485aa44df4SToby Isaac 
94984f0b6dfSMatthew G. Knepley /*@
9505aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9515aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9525aa44df4SToby Isaac 
9535b5e7992SMatthew G. Knepley   Not collective
9545b5e7992SMatthew G. Knepley 
9555aa44df4SToby Isaac   Input parameter:
9565aa44df4SToby Isaac . label - a DMLabel object
9575aa44df4SToby Isaac 
9585aa44df4SToby Isaac   Output parameter:
9595aa44df4SToby Isaac . defaultValue - the default value
9605aa44df4SToby Isaac 
9615aa44df4SToby Isaac   Level: beginner
9625aa44df4SToby Isaac 
963db781477SPatrick Sanan .seealso: `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
96484f0b6dfSMatthew G. Knepley @*/
9655aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
9665aa44df4SToby Isaac {
9675aa44df4SToby Isaac   PetscFunctionBegin;
968d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9695aa44df4SToby Isaac   label->defaultValue = defaultValue;
9705aa44df4SToby Isaac   PetscFunctionReturn(0);
9715aa44df4SToby Isaac }
9725aa44df4SToby Isaac 
973c58f1c22SToby Isaac /*@
9745aa44df4SToby 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())
975c58f1c22SToby Isaac 
9765b5e7992SMatthew G. Knepley   Not collective
9775b5e7992SMatthew G. Knepley 
978c58f1c22SToby Isaac   Input Parameters:
979c58f1c22SToby Isaac + label - the DMLabel
980c58f1c22SToby Isaac - point - the point
981c58f1c22SToby Isaac 
982c58f1c22SToby Isaac   Output Parameter:
9838e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
984c58f1c22SToby Isaac 
985cffad2c9SToby 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.
986cffad2c9SToby Isaac 
987c58f1c22SToby Isaac   Level: intermediate
988c58f1c22SToby Isaac 
989db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
990c58f1c22SToby Isaac @*/
991c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
992c58f1c22SToby Isaac {
993c58f1c22SToby Isaac   PetscInt       v;
994c58f1c22SToby Isaac 
9950c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
996d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
997dadcf809SJacob Faibussowitsch   PetscValidIntPointer(value, 3);
9985aa44df4SToby Isaac   *value = label->defaultValue;
999c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
1000ad8374ffSToby Isaac     if (label->validIS[v]) {
1001c58f1c22SToby Isaac       PetscInt i;
1002c58f1c22SToby Isaac 
10039566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
1004c58f1c22SToby Isaac       if (i >= 0) {
1005c58f1c22SToby Isaac         *value = label->stratumValues[v];
1006c58f1c22SToby Isaac         break;
1007c58f1c22SToby Isaac       }
1008c58f1c22SToby Isaac     } else {
1009c58f1c22SToby Isaac       PetscBool has;
1010c58f1c22SToby Isaac 
10119566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1012c58f1c22SToby Isaac       if (has) {
1013c58f1c22SToby Isaac         *value = label->stratumValues[v];
1014c58f1c22SToby Isaac         break;
1015c58f1c22SToby Isaac       }
1016c58f1c22SToby Isaac     }
1017c58f1c22SToby Isaac   }
1018c58f1c22SToby Isaac   PetscFunctionReturn(0);
1019c58f1c22SToby Isaac }
1020c58f1c22SToby Isaac 
1021c58f1c22SToby Isaac /*@
1022367003a6SStefano 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.
1023c58f1c22SToby Isaac 
10245b5e7992SMatthew G. Knepley   Not collective
10255b5e7992SMatthew G. Knepley 
1026c58f1c22SToby Isaac   Input Parameters:
1027c58f1c22SToby Isaac + label - the DMLabel
1028c58f1c22SToby Isaac . point - the point
1029c58f1c22SToby Isaac - value - The point value
1030c58f1c22SToby Isaac 
1031c58f1c22SToby Isaac   Level: intermediate
1032c58f1c22SToby Isaac 
1033db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1034c58f1c22SToby Isaac @*/
1035c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1036c58f1c22SToby Isaac {
1037c58f1c22SToby Isaac   PetscInt       v;
1038c58f1c22SToby Isaac 
1039c58f1c22SToby Isaac   PetscFunctionBegin;
1040d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10410c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10425aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
10439566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1044c58f1c22SToby Isaac   /* Set key */
10459566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10469566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
1047c58f1c22SToby Isaac   PetscFunctionReturn(0);
1048c58f1c22SToby Isaac }
1049c58f1c22SToby Isaac 
1050c58f1c22SToby Isaac /*@
1051c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1052c58f1c22SToby Isaac 
10535b5e7992SMatthew G. Knepley   Not collective
10545b5e7992SMatthew G. Knepley 
1055c58f1c22SToby Isaac   Input Parameters:
1056c58f1c22SToby Isaac + label - the DMLabel
1057c58f1c22SToby Isaac . point - the point
1058c58f1c22SToby Isaac - value - The point value
1059c58f1c22SToby Isaac 
1060c58f1c22SToby Isaac   Level: intermediate
1061c58f1c22SToby Isaac 
1062db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1063c58f1c22SToby Isaac @*/
1064c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1065c58f1c22SToby Isaac {
1066ad8374ffSToby Isaac   PetscInt       v;
1067c58f1c22SToby Isaac 
1068c58f1c22SToby Isaac   PetscFunctionBegin;
1069d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1070c58f1c22SToby Isaac   /* Find label value */
10719566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
10720c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
10730c3c4a36SLisandro Dalcin 
1074eeed21e7SToby Isaac   if (label->bt) {
107563a3b9bcSJacob 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);
10769566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1077eeed21e7SToby Isaac   }
10780c3c4a36SLisandro Dalcin 
10790c3c4a36SLisandro Dalcin   /* Delete key */
10809566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10819566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
1082c58f1c22SToby Isaac   PetscFunctionReturn(0);
1083c58f1c22SToby Isaac }
1084c58f1c22SToby Isaac 
1085c58f1c22SToby Isaac /*@
1086c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
1087c58f1c22SToby Isaac 
10885b5e7992SMatthew G. Knepley   Not collective
10895b5e7992SMatthew G. Knepley 
1090c58f1c22SToby Isaac   Input Parameters:
1091c58f1c22SToby Isaac + label - the DMLabel
1092c58f1c22SToby Isaac . is    - the point IS
1093c58f1c22SToby Isaac - value - The point value
1094c58f1c22SToby Isaac 
1095c58f1c22SToby Isaac   Level: intermediate
1096c58f1c22SToby Isaac 
1097db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1098c58f1c22SToby Isaac @*/
1099c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1100c58f1c22SToby Isaac {
11010c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1102c58f1c22SToby Isaac   const PetscInt *points;
1103c58f1c22SToby Isaac 
1104c58f1c22SToby Isaac   PetscFunctionBegin;
1105d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1106c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
11070c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
11080c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
11099566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
11100c3c4a36SLisandro Dalcin   /* Set keys */
11119566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11129566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11139566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11149566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11159566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
1116c58f1c22SToby Isaac   PetscFunctionReturn(0);
1117c58f1c22SToby Isaac }
1118c58f1c22SToby Isaac 
111984f0b6dfSMatthew G. Knepley /*@
112084f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
112184f0b6dfSMatthew G. Knepley 
11225b5e7992SMatthew G. Knepley   Not collective
11235b5e7992SMatthew G. Knepley 
112484f0b6dfSMatthew G. Knepley   Input Parameter:
112584f0b6dfSMatthew G. Knepley . label - the DMLabel
112684f0b6dfSMatthew G. Knepley 
112701d2d390SJose E. Roman   Output Parameter:
112884f0b6dfSMatthew G. Knepley . numValues - the number of values
112984f0b6dfSMatthew G. Knepley 
113084f0b6dfSMatthew G. Knepley   Level: intermediate
113184f0b6dfSMatthew G. Knepley 
1132db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
113384f0b6dfSMatthew G. Knepley @*/
1134c58f1c22SToby Isaac PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1135c58f1c22SToby Isaac {
1136c58f1c22SToby Isaac   PetscFunctionBegin;
1137d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1138dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numValues, 2);
1139c58f1c22SToby Isaac   *numValues = label->numStrata;
1140c58f1c22SToby Isaac   PetscFunctionReturn(0);
1141c58f1c22SToby Isaac }
1142c58f1c22SToby Isaac 
114384f0b6dfSMatthew G. Knepley /*@
114484f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
114584f0b6dfSMatthew G. Knepley 
11465b5e7992SMatthew G. Knepley   Not collective
11475b5e7992SMatthew G. Knepley 
114884f0b6dfSMatthew G. Knepley   Input Parameter:
114984f0b6dfSMatthew G. Knepley . label - the DMLabel
115084f0b6dfSMatthew G. Knepley 
115101d2d390SJose E. Roman   Output Parameter:
115284f0b6dfSMatthew G. Knepley . is    - the value IS
115384f0b6dfSMatthew G. Knepley 
115484f0b6dfSMatthew G. Knepley   Level: intermediate
115584f0b6dfSMatthew G. Knepley 
11561d04cbbeSVaclav Hapla   Notes:
11571d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11581d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
11591d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
11601d04cbbeSVaclav Hapla 
1161db781477SPatrick Sanan .seealso: `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
116284f0b6dfSMatthew G. Knepley @*/
1163c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1164c58f1c22SToby Isaac {
1165c58f1c22SToby Isaac   PetscFunctionBegin;
1166d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1167c58f1c22SToby Isaac   PetscValidPointer(values, 2);
11689566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1169c58f1c22SToby Isaac   PetscFunctionReturn(0);
1170c58f1c22SToby Isaac }
1171c58f1c22SToby Isaac 
117284f0b6dfSMatthew G. Knepley /*@
11731d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
11741d04cbbeSVaclav Hapla 
11751d04cbbeSVaclav Hapla   Not collective
11761d04cbbeSVaclav Hapla 
11771d04cbbeSVaclav Hapla   Input Parameter:
11781d04cbbeSVaclav Hapla . label - the DMLabel
11791d04cbbeSVaclav Hapla 
11801d04cbbeSVaclav Hapla   Output Paramater:
11811d04cbbeSVaclav Hapla . is    - the value IS
11821d04cbbeSVaclav Hapla 
11831d04cbbeSVaclav Hapla   Level: intermediate
11841d04cbbeSVaclav Hapla 
11851d04cbbeSVaclav Hapla   Notes:
11861d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11871d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
11881d04cbbeSVaclav Hapla 
1189db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
11901d04cbbeSVaclav Hapla @*/
11911d04cbbeSVaclav Hapla PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
11921d04cbbeSVaclav Hapla {
11931d04cbbeSVaclav Hapla   PetscInt        i, j;
11941d04cbbeSVaclav Hapla   PetscInt       *valuesArr;
11951d04cbbeSVaclav Hapla 
11961d04cbbeSVaclav Hapla   PetscFunctionBegin;
11971d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11981d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
11999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
12001d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
12011d04cbbeSVaclav Hapla     PetscInt        n;
12021d04cbbeSVaclav Hapla 
12039566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
12041d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
12051d04cbbeSVaclav Hapla   }
12061d04cbbeSVaclav Hapla   if (j == label->numStrata) {
12079566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
12081d04cbbeSVaclav Hapla   } else {
12099566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
12101d04cbbeSVaclav Hapla   }
12119566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
12121d04cbbeSVaclav Hapla   PetscFunctionReturn(0);
12131d04cbbeSVaclav Hapla }
12141d04cbbeSVaclav Hapla 
12151d04cbbeSVaclav Hapla /*@
1216d123abd9SMatthew 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
1217d123abd9SMatthew G. Knepley 
1218d123abd9SMatthew G. Knepley   Not collective
1219d123abd9SMatthew G. Knepley 
1220d123abd9SMatthew G. Knepley   Input Parameters:
1221d123abd9SMatthew G. Knepley + label - the DMLabel
122297bb3fdcSJose E. Roman - value - the value
1223d123abd9SMatthew G. Knepley 
122401d2d390SJose E. Roman   Output Parameter:
1225d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1226d123abd9SMatthew G. Knepley 
1227d123abd9SMatthew G. Knepley   Level: intermediate
1228d123abd9SMatthew G. Knepley 
1229db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1230d123abd9SMatthew G. Knepley @*/
1231d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1232d123abd9SMatthew G. Knepley {
1233d123abd9SMatthew G. Knepley   PetscInt v;
1234d123abd9SMatthew G. Knepley 
1235d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1236d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1237dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 3);
1238d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
1239d123abd9SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) if (label->stratumValues[v] == value) break;
1240d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1241d123abd9SMatthew G. Knepley   else                       *index = v;
1242d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1243d123abd9SMatthew G. Knepley }
1244d123abd9SMatthew G. Knepley 
1245d123abd9SMatthew G. Knepley /*@
124684f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
124784f0b6dfSMatthew G. Knepley 
12485b5e7992SMatthew G. Knepley   Not collective
12495b5e7992SMatthew G. Knepley 
125084f0b6dfSMatthew G. Knepley   Input Parameters:
125184f0b6dfSMatthew G. Knepley + label - the DMLabel
125284f0b6dfSMatthew G. Knepley - value - the stratum value
125384f0b6dfSMatthew G. Knepley 
125401d2d390SJose E. Roman   Output Parameter:
125584f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
125684f0b6dfSMatthew G. Knepley 
125784f0b6dfSMatthew G. Knepley   Level: intermediate
125884f0b6dfSMatthew G. Knepley 
1259db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
126084f0b6dfSMatthew G. Knepley @*/
1261fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1262fada774cSMatthew G. Knepley {
1263fada774cSMatthew G. Knepley   PetscInt       v;
1264fada774cSMatthew G. Knepley 
1265fada774cSMatthew G. Knepley   PetscFunctionBegin;
1266d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1267dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(exists, 3);
12689566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12690c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1270fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1271fada774cSMatthew G. Knepley }
1272fada774cSMatthew G. Knepley 
127384f0b6dfSMatthew G. Knepley /*@
127484f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
127584f0b6dfSMatthew G. Knepley 
12765b5e7992SMatthew G. Knepley   Not collective
12775b5e7992SMatthew G. Knepley 
127884f0b6dfSMatthew G. Knepley   Input Parameters:
127984f0b6dfSMatthew G. Knepley + label - the DMLabel
128084f0b6dfSMatthew G. Knepley - value - the stratum value
128184f0b6dfSMatthew G. Knepley 
128201d2d390SJose E. Roman   Output Parameter:
128384f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
128484f0b6dfSMatthew G. Knepley 
128584f0b6dfSMatthew G. Knepley   Level: intermediate
128684f0b6dfSMatthew G. Knepley 
1287db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
128884f0b6dfSMatthew G. Knepley @*/
1289c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1290c58f1c22SToby Isaac {
1291c58f1c22SToby Isaac   PetscInt       v;
1292c58f1c22SToby Isaac 
1293c58f1c22SToby Isaac   PetscFunctionBegin;
1294d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1295dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
12969566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12979566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
1298c58f1c22SToby Isaac   PetscFunctionReturn(0);
1299c58f1c22SToby Isaac }
1300c58f1c22SToby Isaac 
130184f0b6dfSMatthew G. Knepley /*@
130284f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
130384f0b6dfSMatthew G. Knepley 
13045b5e7992SMatthew G. Knepley   Not collective
13055b5e7992SMatthew G. Knepley 
130684f0b6dfSMatthew G. Knepley   Input Parameters:
130784f0b6dfSMatthew G. Knepley + label - the DMLabel
130884f0b6dfSMatthew G. Knepley - value - the stratum value
130984f0b6dfSMatthew G. Knepley 
131001d2d390SJose E. Roman   Output Parameters:
131184f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
131284f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
131384f0b6dfSMatthew G. Knepley 
131484f0b6dfSMatthew G. Knepley   Level: intermediate
131584f0b6dfSMatthew G. Knepley 
1316db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
131784f0b6dfSMatthew G. Knepley @*/
1318c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1319c58f1c22SToby Isaac {
13200c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1321c58f1c22SToby Isaac 
1322c58f1c22SToby Isaac   PetscFunctionBegin;
1323d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1324dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = -1;}
1325dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = -1;}
13269566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13270c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13289566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13290c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
13309566063dSJacob Faibussowitsch   PetscCall(ISGetMinMax(label->points[v], &min, &max));
1331d6cb179aSToby Isaac   if (start) *start = min;
1332d6cb179aSToby Isaac   if (end)   *end   = max+1;
1333c58f1c22SToby Isaac   PetscFunctionReturn(0);
1334c58f1c22SToby Isaac }
1335c58f1c22SToby Isaac 
133684f0b6dfSMatthew G. Knepley /*@
133784f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
133884f0b6dfSMatthew G. Knepley 
13395b5e7992SMatthew G. Knepley   Not collective
13405b5e7992SMatthew G. Knepley 
134184f0b6dfSMatthew G. Knepley   Input Parameters:
134284f0b6dfSMatthew G. Knepley + label - the DMLabel
134384f0b6dfSMatthew G. Knepley - value - the stratum value
134484f0b6dfSMatthew G. Knepley 
134501d2d390SJose E. Roman   Output Parameter:
134684f0b6dfSMatthew G. Knepley . points - The stratum points
134784f0b6dfSMatthew G. Knepley 
134884f0b6dfSMatthew G. Knepley   Level: intermediate
134984f0b6dfSMatthew G. Knepley 
1350593ce467SVaclav Hapla   Notes:
1351593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1352593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1353593ce467SVaclav Hapla 
1354db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
135584f0b6dfSMatthew G. Knepley @*/
1356c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1357c58f1c22SToby Isaac {
1358c58f1c22SToby Isaac   PetscInt       v;
1359c58f1c22SToby Isaac 
1360c58f1c22SToby Isaac   PetscFunctionBegin;
1361d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1362c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1363c58f1c22SToby Isaac   *points = NULL;
13649566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13650c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13669566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13679566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject) label->points[v]));
1368ad8374ffSToby Isaac   *points = label->points[v];
1369c58f1c22SToby Isaac   PetscFunctionReturn(0);
1370c58f1c22SToby Isaac }
1371c58f1c22SToby Isaac 
137284f0b6dfSMatthew G. Knepley /*@
137384f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
137484f0b6dfSMatthew G. Knepley 
13755b5e7992SMatthew G. Knepley   Not collective
13765b5e7992SMatthew G. Knepley 
137784f0b6dfSMatthew G. Knepley   Input Parameters:
137884f0b6dfSMatthew G. Knepley + label - the DMLabel
137984f0b6dfSMatthew G. Knepley . value - the stratum value
138084f0b6dfSMatthew G. Knepley - points - The stratum points
138184f0b6dfSMatthew G. Knepley 
138284f0b6dfSMatthew G. Knepley   Level: intermediate
138384f0b6dfSMatthew G. Knepley 
1384db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
138584f0b6dfSMatthew G. Knepley @*/
13864de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
13874de306b1SToby Isaac {
13880c3c4a36SLisandro Dalcin   PetscInt       v;
13894de306b1SToby Isaac 
13904de306b1SToby Isaac   PetscFunctionBegin;
1391d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1392d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
13939566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
13944de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
13959566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
13969566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
13979566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
13989566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&(label->points[v])));
13990c3c4a36SLisandro Dalcin   label->points[v]  = is;
14000c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
14019566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject) label));
14024de306b1SToby Isaac   if (label->bt) {
14034de306b1SToby Isaac     const PetscInt *points;
14044de306b1SToby Isaac     PetscInt p;
14054de306b1SToby Isaac 
14069566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,&points));
14074de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
14084de306b1SToby Isaac       const PetscInt point = points[p];
14094de306b1SToby Isaac 
141063a3b9bcSJacob 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);
14119566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
14124de306b1SToby Isaac     }
14134de306b1SToby Isaac   }
14144de306b1SToby Isaac   PetscFunctionReturn(0);
14154de306b1SToby Isaac }
14164de306b1SToby Isaac 
141784f0b6dfSMatthew G. Knepley /*@
141884f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14194de306b1SToby Isaac 
14205b5e7992SMatthew G. Knepley   Not collective
14215b5e7992SMatthew G. Knepley 
142284f0b6dfSMatthew G. Knepley   Input Parameters:
142384f0b6dfSMatthew G. Knepley + label - the DMLabel
142484f0b6dfSMatthew G. Knepley - value - the stratum value
142584f0b6dfSMatthew G. Knepley 
142684f0b6dfSMatthew G. Knepley   Level: intermediate
142784f0b6dfSMatthew G. Knepley 
1428db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
142984f0b6dfSMatthew G. Knepley @*/
1430c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1431c58f1c22SToby Isaac {
1432c58f1c22SToby Isaac   PetscInt       v;
1433c58f1c22SToby Isaac 
1434c58f1c22SToby Isaac   PetscFunctionBegin;
1435d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14369566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14370c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
14384de306b1SToby Isaac   if (label->validIS[v]) {
14394de306b1SToby Isaac     if (label->bt) {
1440c58f1c22SToby Isaac       PetscInt       i;
1441ad8374ffSToby Isaac       const PetscInt *points;
1442c58f1c22SToby Isaac 
14439566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1444c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1445ad8374ffSToby Isaac         const PetscInt point = points[i];
1446c58f1c22SToby Isaac 
144763a3b9bcSJacob 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);
14489566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1449c58f1c22SToby Isaac       }
14509566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1451c58f1c22SToby Isaac     }
1452c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
14539566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
14549566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
14559566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) label->points[v], "indices"));
14569566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject) label));
1457c58f1c22SToby Isaac   } else {
14589566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1459c58f1c22SToby Isaac   }
1460c58f1c22SToby Isaac   PetscFunctionReturn(0);
1461c58f1c22SToby Isaac }
1462c58f1c22SToby Isaac 
146384f0b6dfSMatthew G. Knepley /*@
1464412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1465412e9a14SMatthew G. Knepley 
1466412e9a14SMatthew G. Knepley   Not collective
1467412e9a14SMatthew G. Knepley 
1468412e9a14SMatthew G. Knepley   Input Parameters:
1469412e9a14SMatthew G. Knepley + label  - The DMLabel
1470412e9a14SMatthew G. Knepley . value  - The label value for all points
1471412e9a14SMatthew G. Knepley . pStart - The first point
1472412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1473412e9a14SMatthew G. Knepley 
1474412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1475412e9a14SMatthew G. Knepley 
1476412e9a14SMatthew G. Knepley   Level: intermediate
1477412e9a14SMatthew G. Knepley 
1478db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1479412e9a14SMatthew G. Knepley @*/
1480412e9a14SMatthew G. Knepley PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1481412e9a14SMatthew G. Knepley {
1482412e9a14SMatthew G. Knepley   IS             pIS;
1483412e9a14SMatthew G. Knepley 
1484412e9a14SMatthew G. Knepley   PetscFunctionBegin;
14859566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
14869566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
14879566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
1488412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1489412e9a14SMatthew G. Knepley }
1490412e9a14SMatthew G. Knepley 
1491412e9a14SMatthew G. Knepley /*@
1492d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1493d123abd9SMatthew G. Knepley 
1494d123abd9SMatthew G. Knepley   Not collective
1495d123abd9SMatthew G. Knepley 
1496d123abd9SMatthew G. Knepley   Input Parameters:
1497d123abd9SMatthew G. Knepley + label  - The DMLabel
1498d123abd9SMatthew G. Knepley . value  - The label value
1499d123abd9SMatthew G. Knepley - p      - A point with this value
1500d123abd9SMatthew G. Knepley 
1501d123abd9SMatthew G. Knepley   Output Parameter:
1502d123abd9SMatthew 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
1503d123abd9SMatthew G. Knepley 
1504d123abd9SMatthew G. Knepley   Level: intermediate
1505d123abd9SMatthew G. Knepley 
1506db781477SPatrick Sanan .seealso: `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1507d123abd9SMatthew G. Knepley @*/
1508d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1509d123abd9SMatthew G. Knepley {
1510d123abd9SMatthew G. Knepley   const PetscInt *indices;
1511d123abd9SMatthew G. Knepley   PetscInt        v;
1512d123abd9SMatthew G. Knepley 
1513d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1514d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1515dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 4);
1516d123abd9SMatthew G. Knepley   *index = -1;
15179566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1518d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
15199566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
15209566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(label->points[v], &indices));
15219566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
15229566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(label->points[v], &indices));
1523d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1524d123abd9SMatthew G. Knepley }
1525d123abd9SMatthew G. Knepley 
1526d123abd9SMatthew G. Knepley /*@
152784f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
152884f0b6dfSMatthew G. Knepley 
15295b5e7992SMatthew G. Knepley   Not collective
15305b5e7992SMatthew G. Knepley 
153184f0b6dfSMatthew G. Knepley   Input Parameters:
153284f0b6dfSMatthew G. Knepley + label - the DMLabel
153322cd2cdaSVaclav Hapla . start - the first point kept
153422cd2cdaSVaclav Hapla - end - one more than the last point kept
153584f0b6dfSMatthew G. Knepley 
153684f0b6dfSMatthew G. Knepley   Level: intermediate
153784f0b6dfSMatthew G. Knepley 
1538db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
153984f0b6dfSMatthew G. Knepley @*/
1540c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1541c58f1c22SToby Isaac {
1542c58f1c22SToby Isaac   PetscInt       v;
1543c58f1c22SToby Isaac 
1544c58f1c22SToby Isaac   PetscFunctionBegin;
1545d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15469566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
15479566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
1548c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
15499566063dSJacob Faibussowitsch     PetscCall(ISGeneralFilter(label->points[v], start, end));
1550c58f1c22SToby Isaac   }
15519566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
1552c58f1c22SToby Isaac   PetscFunctionReturn(0);
1553c58f1c22SToby Isaac }
1554c58f1c22SToby Isaac 
155584f0b6dfSMatthew G. Knepley /*@
155684f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
155784f0b6dfSMatthew G. Knepley 
15585b5e7992SMatthew G. Knepley   Not collective
15595b5e7992SMatthew G. Knepley 
156084f0b6dfSMatthew G. Knepley   Input Parameters:
156184f0b6dfSMatthew G. Knepley + label - the DMLabel
156284f0b6dfSMatthew G. Knepley - permutation - the point permutation
156384f0b6dfSMatthew G. Knepley 
156484f0b6dfSMatthew G. Knepley   Output Parameter:
156584f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
156684f0b6dfSMatthew G. Knepley 
156784f0b6dfSMatthew G. Knepley   Level: intermediate
156884f0b6dfSMatthew G. Knepley 
1569db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
157084f0b6dfSMatthew G. Knepley @*/
1571c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1572c58f1c22SToby Isaac {
1573c58f1c22SToby Isaac   const PetscInt *perm;
1574c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1575c58f1c22SToby Isaac 
1576c58f1c22SToby Isaac   PetscFunctionBegin;
1577d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1578d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
15799566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
15809566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
15819566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
15829566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
15839566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1584c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1585c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1586ad8374ffSToby Isaac     const PetscInt *points;
1587ad8374ffSToby Isaac     PetscInt *pointsNew;
1588c58f1c22SToby Isaac 
15899566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v],&points));
15909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size,&pointsNew));
1591c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1592ad8374ffSToby Isaac       const PetscInt point = points[q];
1593c58f1c22SToby Isaac 
159463a3b9bcSJacob 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);
1595ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1596c58f1c22SToby Isaac     }
15979566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v],&points));
15989566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
15999566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1600fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
16019566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v])));
16029566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1603fa8e8ae5SToby Isaac     } else {
16049566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v])));
1605fa8e8ae5SToby Isaac     }
16069566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices"));
1607c58f1c22SToby Isaac   }
16089566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1609c58f1c22SToby Isaac   if (label->bt) {
16109566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
16119566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1612c58f1c22SToby Isaac   }
1613c58f1c22SToby Isaac   PetscFunctionReturn(0);
1614c58f1c22SToby Isaac }
1615c58f1c22SToby Isaac 
161626c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
161726c55118SMichael Lange {
161826c55118SMichael Lange   MPI_Comm       comm;
1619eb30be1eSVaclav Hapla   PetscInt       s, l, nroots, nleaves, offset, size;
162026c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
162126c55118SMichael Lange   PetscSection   rootSection;
162226c55118SMichael Lange   PetscSF        labelSF;
162326c55118SMichael Lange 
162426c55118SMichael Lange   PetscFunctionBegin;
16259566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
16269566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
162726c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
162826c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
16299566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
16309566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
16319566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
163226c55118SMichael Lange   if (label) {
163326c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1634ad8374ffSToby Isaac       const PetscInt *points;
1635ad8374ffSToby Isaac 
16369566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
163726c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1638eb30be1eSVaclav Hapla         PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
163926c55118SMichael Lange       }
16409566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
164126c55118SMichael Lange     }
164226c55118SMichael Lange   }
16439566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
164426c55118SMichael Lange   /* Create a point-wise array of stratum values */
16459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
16469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
16479566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
164826c55118SMichael Lange   if (label) {
164926c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1650ad8374ffSToby Isaac       const PetscInt *points;
1651ad8374ffSToby Isaac 
16529566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
165326c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1654ad8374ffSToby Isaac         const PetscInt p = points[l];
16559566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
165626c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
165726c55118SMichael Lange       }
16589566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
165926c55118SMichael Lange     }
166026c55118SMichael Lange   }
166126c55118SMichael Lange   /* Build SF that maps label points to remote processes */
16629566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
16639566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
16649566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
16659566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
166626c55118SMichael Lange   /* Send the strata for each point over the derived SF */
16679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
16689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
16699566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
16709566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
167126c55118SMichael Lange   /* Clean up */
16729566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
16739566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
16749566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
16759566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
167626c55118SMichael Lange   PetscFunctionReturn(0);
167726c55118SMichael Lange }
167826c55118SMichael Lange 
167984f0b6dfSMatthew G. Knepley /*@
168084f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
168184f0b6dfSMatthew G. Knepley 
16825b5e7992SMatthew G. Knepley   Collective on sf
16835b5e7992SMatthew G. Knepley 
168484f0b6dfSMatthew G. Knepley   Input Parameters:
168584f0b6dfSMatthew G. Knepley + label - the DMLabel
168684f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
168784f0b6dfSMatthew G. Knepley 
168884f0b6dfSMatthew G. Knepley   Output Parameter:
168984f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
169084f0b6dfSMatthew G. Knepley 
169184f0b6dfSMatthew G. Knepley   Level: intermediate
169284f0b6dfSMatthew G. Knepley 
1693db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
169484f0b6dfSMatthew G. Knepley @*/
1695c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1696c58f1c22SToby Isaac {
1697c58f1c22SToby Isaac   MPI_Comm       comm;
169826c55118SMichael Lange   PetscSection   leafSection;
169926c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
170026c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1701ad8374ffSToby Isaac   PetscInt     **points;
1702d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1703c58f1c22SToby Isaac   char          *name;
1704c58f1c22SToby Isaac   PetscInt       nameSize;
1705e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1706c58f1c22SToby Isaac   size_t         len = 0;
170726c55118SMichael Lange   PetscMPIInt    rank;
1708c58f1c22SToby Isaac 
1709c58f1c22SToby Isaac   PetscFunctionBegin;
1710d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1711f018e600SMatthew G. Knepley   if (label) {
1712f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17139566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1714f018e600SMatthew G. Knepley   }
17159566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1717c58f1c22SToby Isaac   /* Bcast name */
1718dd400576SPatrick Sanan   if (rank == 0) {
17199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &lname));
17209566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1721d67d17b1SMatthew G. Knepley   }
1722c58f1c22SToby Isaac   nameSize = len;
17239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize+1, &name));
17259566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize+1));
17269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
17279566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17289566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
172977d236dfSMichael Lange   /* Bcast defaultValue */
1730dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
17319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
173226c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
17339566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
17345cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
17359566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
17369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
17379566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
17389566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
17399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1740ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
17419566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
17425cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
17435cbdf6fcSMichael Lange   offset = 0;
17449566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
17459566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues));
174690e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17479566063dSJacob Faibussowitsch     PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
174890e9b2aeSLisandro Dalcin   }
17495cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1750231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1751231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
17525cbdf6fcSMichael Lange     }
17535cbdf6fcSMichael Lange   }
1754c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
17559566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes));
17569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1757c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1760c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1761c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1762c58f1c22SToby Isaac     }
1763c58f1c22SToby Isaac   }
17649566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht));
17659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points));
17669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata,&points));
1767c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17689566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
17699566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1770c58f1c22SToby Isaac   }
1771c58f1c22SToby Isaac   /* Insert points into new strata */
17729566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
17739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1774c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1777c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1778c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1779ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1780c58f1c22SToby Isaac     }
1781c58f1c22SToby Isaac   }
1782ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
17839566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s])));
17849566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices"));
1785ad8374ffSToby Isaac   }
17869566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
17879566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
17889566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
17899566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
17909566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
1791c58f1c22SToby Isaac   PetscFunctionReturn(0);
1792c58f1c22SToby Isaac }
1793c58f1c22SToby Isaac 
17947937d9ceSMichael Lange /*@
17957937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
17967937d9ceSMichael Lange 
17975b5e7992SMatthew G. Knepley   Collective on sf
17985b5e7992SMatthew G. Knepley 
17997937d9ceSMichael Lange   Input Parameters:
18007937d9ceSMichael Lange + label - the DMLabel
180184f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
18027937d9ceSMichael Lange 
180384f0b6dfSMatthew G. Knepley   Output Parameters:
180484f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
18057937d9ceSMichael Lange 
18067937d9ceSMichael Lange   Level: developer
18077937d9ceSMichael Lange 
18087937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
18097937d9ceSMichael Lange 
1810db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
18117937d9ceSMichael Lange @*/
18127937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
18137937d9ceSMichael Lange {
18147937d9ceSMichael Lange   MPI_Comm       comm;
18157937d9ceSMichael Lange   PetscSection   rootSection;
18167937d9ceSMichael Lange   PetscSF        sfLabel;
18177937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
18187937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18197937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18207937d9ceSMichael Lange   PetscInt       *rootStrata;
1821d67d17b1SMatthew G. Knepley   const char    *lname;
18227937d9ceSMichael Lange   char          *name;
18237937d9ceSMichael Lange   PetscInt       nameSize;
18247937d9ceSMichael Lange   size_t         len = 0;
18259852e123SBarry Smith   PetscMPIInt    rank, size;
18267937d9ceSMichael Lange 
18277937d9ceSMichael Lange   PetscFunctionBegin;
1828d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1829d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
18309566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
18319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
18329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
18337937d9ceSMichael Lange   /* Bcast name */
1834dd400576SPatrick Sanan   if (rank == 0) {
18359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &lname));
18369566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1837d67d17b1SMatthew G. Knepley   }
18387937d9ceSMichael Lange   nameSize = len;
18399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
18409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize+1, &name));
18419566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize+1));
18429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
18439566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
18449566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
18457937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
18467937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
18477937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
18489566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
18499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1850dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
18517937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
18528212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
18538212dd46SStefano Zampini 
18548212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
18558212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
18567937d9ceSMichael Lange   }
18579566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
18589566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
18597937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
18609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
18619566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
18629566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
18639566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm,& sfLabel));
18649566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
18657937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
18669566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
18677937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
18687937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
18697937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
18709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx+d, &dof));
18719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx+d, &offset));
18729566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset+s]));
18737937d9ceSMichael Lange     }
18747937d9ceSMichael Lange     idx += rootDegree[p];
18757937d9ceSMichael Lange   }
18769566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
18779566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18789566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18799566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
18807937d9ceSMichael Lange   PetscFunctionReturn(0);
18817937d9ceSMichael Lange }
18827937d9ceSMichael Lange 
1883d42890abSMatthew G. Knepley static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1884d42890abSMatthew G. Knepley {
1885d42890abSMatthew G. Knepley   const PetscInt *degree;
1886d42890abSMatthew G. Knepley   const PetscInt *points;
1887d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1888d42890abSMatthew G. Knepley 
1889d42890abSMatthew G. Knepley   PetscFunctionBegin;
1890d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1891d42890abSMatthew G. Knepley   /* Add in leaves */
1892d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1893d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1894d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1895d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1896d42890abSMatthew G. Knepley   }
1897d42890abSMatthew G. Knepley   /* Add in shared roots */
1898d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1899d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1900d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1901d42890abSMatthew G. Knepley     if (degree[r]) {
1902d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1903d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1904d42890abSMatthew G. Knepley     }
1905d42890abSMatthew G. Knepley   }
1906d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1907d42890abSMatthew G. Knepley }
1908d42890abSMatthew G. Knepley 
1909d42890abSMatthew G. Knepley static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1910d42890abSMatthew G. Knepley {
1911d42890abSMatthew G. Knepley   const PetscInt *degree;
1912d42890abSMatthew G. Knepley   const PetscInt *points;
1913d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1914d42890abSMatthew G. Knepley 
1915d42890abSMatthew G. Knepley   PetscFunctionBegin;
1916d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1917d42890abSMatthew G. Knepley   /* Read out leaves */
1918d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1919d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1920d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1921d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1922d42890abSMatthew G. Knepley 
1923d42890abSMatthew G. Knepley     if (cval != defVal) {
1924d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1925d42890abSMatthew G. Knepley       if (val == defVal) {
1926d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
1927d42890abSMatthew G. Knepley         if (markPoint) {PetscCall((*markPoint)(label, p, cval, ctx));}
1928d42890abSMatthew G. Knepley       }
1929d42890abSMatthew G. Knepley     }
1930d42890abSMatthew G. Knepley   }
1931d42890abSMatthew G. Knepley   /* Read out shared roots */
1932d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1933d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1934d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1935d42890abSMatthew G. Knepley     if (degree[r]) {
1936d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
1937d42890abSMatthew G. Knepley 
1938d42890abSMatthew G. Knepley       if (cval != defVal) {
1939d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
1940d42890abSMatthew G. Knepley         if (val == defVal) {
1941d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
1942d42890abSMatthew G. Knepley           if (markPoint) {PetscCall((*markPoint)(label, r, cval, ctx));}
1943d42890abSMatthew G. Knepley         }
1944d42890abSMatthew G. Knepley       }
1945d42890abSMatthew G. Knepley     }
1946d42890abSMatthew G. Knepley   }
1947d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1948d42890abSMatthew G. Knepley }
1949d42890abSMatthew G. Knepley 
1950d42890abSMatthew G. Knepley /*@
1951d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
1952d42890abSMatthew G. Knepley 
1953d42890abSMatthew G. Knepley   Collective on sf
1954d42890abSMatthew G. Knepley 
1955d42890abSMatthew G. Knepley   Input Parameters:
1956d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1957d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1958d42890abSMatthew G. Knepley 
1959d42890abSMatthew G. Knepley   Level: intermediate
1960d42890abSMatthew G. Knepley 
1961db781477SPatrick Sanan .seealso: `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
1962d42890abSMatthew G. Knepley @*/
1963d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
1964d42890abSMatthew G. Knepley {
1965d42890abSMatthew G. Knepley   PetscInt       Nr, r, defVal;
1966d42890abSMatthew G. Knepley   PetscMPIInt    size;
1967d42890abSMatthew G. Knepley 
1968d42890abSMatthew G. Knepley   PetscFunctionBegin;
1969d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) sf), &size));
1970d42890abSMatthew G. Knepley   if (size > 1) {
1971d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
1972d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
1973d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
1974d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
1975d42890abSMatthew G. Knepley   }
1976d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1977d42890abSMatthew G. Knepley }
1978d42890abSMatthew G. Knepley 
1979d42890abSMatthew G. Knepley /*@
1980d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
1981d42890abSMatthew G. Knepley 
1982d42890abSMatthew G. Knepley   Collective on sf
1983d42890abSMatthew G. Knepley 
1984d42890abSMatthew G. Knepley   Input Parameters:
1985d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1986d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1987d42890abSMatthew G. Knepley 
1988d42890abSMatthew G. Knepley   Level: intermediate
1989d42890abSMatthew G. Knepley 
1990db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
1991d42890abSMatthew G. Knepley @*/
1992d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
1993d42890abSMatthew G. Knepley {
1994d42890abSMatthew G. Knepley   PetscFunctionBegin;
1995d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
1996d42890abSMatthew G. Knepley   label->propArray = NULL;
1997d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1998d42890abSMatthew G. Knepley }
1999d42890abSMatthew G. Knepley 
2000d42890abSMatthew G. Knepley /*@C
2001d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
2002d42890abSMatthew G. Knepley 
2003d42890abSMatthew G. Knepley   Collective on sf
2004d42890abSMatthew G. Knepley 
2005d42890abSMatthew G. Knepley   Input Parameters:
2006d42890abSMatthew G. Knepley + label     - The DMLabel to propagate across processes
2007d42890abSMatthew G. Knepley . sf        - The SF describing parallel layout of the label points
2008*ef1023bdSBarry Smith . markPoint - An optional callback that is called when a point is marked, or NULL
2009d42890abSMatthew G. Knepley - ctx       - An optional user context for the callback, or NULL
2010d42890abSMatthew G. Knepley 
2011d42890abSMatthew G. Knepley   Calling sequence of markPoint:
2012d42890abSMatthew G. Knepley $ markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
2013d42890abSMatthew G. Knepley 
2014d42890abSMatthew G. Knepley + label - The DMLabel
2015d42890abSMatthew G. Knepley . p     - The point being marked
2016d42890abSMatthew G. Knepley . val   - The label value for p
2017d42890abSMatthew G. Knepley - ctx   - An optional user context
2018d42890abSMatthew G. Knepley 
2019d42890abSMatthew G. Knepley   Level: intermediate
2020d42890abSMatthew G. Knepley 
2021db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2022d42890abSMatthew G. Knepley @*/
2023d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2024d42890abSMatthew G. Knepley {
2025c50b2d26SMatthew G. Knepley   PetscInt      *valArray = label->propArray, Nr;
2026d42890abSMatthew G. Knepley   PetscMPIInt    size;
2027d42890abSMatthew G. Knepley 
2028d42890abSMatthew G. Knepley   PetscFunctionBegin;
2029d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) pointSF), &size));
2030c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2031c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2032d42890abSMatthew G. Knepley     /* Communicate marked edges
2033d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2034d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2035d42890abSMatthew G. Knepley 
2036d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2037d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2038d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2039d42890abSMatthew G. Knepley 
2040d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2041d42890abSMatthew 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
2042d42890abSMatthew G. Knepley        edge to the queue.
2043d42890abSMatthew G. Knepley     */
2044d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2045d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2046d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2047d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray,MPI_REPLACE));
2048d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray,MPI_REPLACE));
2049d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2050d42890abSMatthew G. Knepley   }
2051d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
2052d42890abSMatthew G. Knepley }
2053d42890abSMatthew G. Knepley 
205484f0b6dfSMatthew G. Knepley /*@
205584f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
205684f0b6dfSMatthew G. Knepley 
20575b5e7992SMatthew G. Knepley   Not collective
20585b5e7992SMatthew G. Knepley 
205984f0b6dfSMatthew G. Knepley   Input Parameter:
206084f0b6dfSMatthew G. Knepley . label - the DMLabel
206184f0b6dfSMatthew G. Knepley 
206284f0b6dfSMatthew G. Knepley   Output Parameters:
206384f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
206484f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
206584f0b6dfSMatthew G. Knepley 
206684f0b6dfSMatthew G. Knepley   Level: developer
206784f0b6dfSMatthew G. Knepley 
2068db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
206984f0b6dfSMatthew G. Knepley @*/
2070c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2071c58f1c22SToby Isaac {
2072c58f1c22SToby Isaac   IS              vIS;
2073c58f1c22SToby Isaac   const PetscInt *values;
2074c58f1c22SToby Isaac   PetscInt       *points;
2075c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2076c58f1c22SToby Isaac 
2077c58f1c22SToby Isaac   PetscFunctionBegin;
2078d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
20799566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
20809566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
20819566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
2082c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
2083c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2084c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2085c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
2086c58f1c22SToby Isaac   }
20879566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
20889566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2089c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2090c58f1c22SToby Isaac     PetscInt n;
2091c58f1c22SToby Isaac 
20929566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
20939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2094c58f1c22SToby Isaac   }
20959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
20969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
20979566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2098c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2099c58f1c22SToby Isaac     IS              is;
2100c58f1c22SToby Isaac     const PetscInt *spoints;
2101c58f1c22SToby Isaac     PetscInt        dof, off, p;
2102c58f1c22SToby Isaac 
21039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
21049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
21059566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
21069566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2107c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
21089566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
21099566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2110c58f1c22SToby Isaac   }
21119566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
21129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
21139566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
2114c58f1c22SToby Isaac   PetscFunctionReturn(0);
2115c58f1c22SToby Isaac }
2116c58f1c22SToby Isaac 
211784f0b6dfSMatthew G. Knepley /*@
2118c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2119c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
2120c58f1c22SToby Isaac 
21215b5e7992SMatthew G. Knepley   Collective on sf
21225b5e7992SMatthew G. Knepley 
2123c58f1c22SToby Isaac   Input Parameters:
2124c58f1c22SToby Isaac + s - The PetscSection for the local field layout
2125c58f1c22SToby Isaac . sf - The SF describing parallel layout of the section points
2126c58f1c22SToby Isaac . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
2127c58f1c22SToby Isaac . label - The label specifying the points
2128c58f1c22SToby Isaac - labelValue - The label stratum specifying the points
2129c58f1c22SToby Isaac 
2130c58f1c22SToby Isaac   Output Parameter:
2131c58f1c22SToby Isaac . gsection - The PetscSection for the global field layout
2132c58f1c22SToby Isaac 
2133c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
2134c58f1c22SToby Isaac 
2135c58f1c22SToby Isaac   Level: developer
2136c58f1c22SToby Isaac 
2137db781477SPatrick Sanan .seealso: `PetscSectionCreate()`
2138c58f1c22SToby Isaac @*/
2139c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2140c58f1c22SToby Isaac {
2141c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
2142c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2143c58f1c22SToby Isaac 
2144c58f1c22SToby Isaac   PetscFunctionBegin;
2145d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2146d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2147d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
21489566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection));
21499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
21509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
21519566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2152c58f1c22SToby Isaac   if (nroots >= 0) {
215363a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd-pStart,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd-pStart);
21549566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2155c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
21569566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2157c58f1c22SToby Isaac     } else {
2158c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2159c58f1c22SToby Isaac     }
2160c58f1c22SToby Isaac   }
2161c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2162c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2163c58f1c22SToby Isaac     PetscInt value;
2164c58f1c22SToby Isaac 
21659566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2166c58f1c22SToby Isaac     if (value != labelValue) continue;
21679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
21689566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
21699566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
21709566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2171c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
2172c58f1c22SToby Isaac   }
21739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2174c58f1c22SToby Isaac   if (nroots >= 0) {
21759566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
21769566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
2177c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
2178c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
2179c58f1c22SToby Isaac     }
2180c58f1c22SToby Isaac   }
2181c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
2182c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
2183c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2184c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2185c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
2186c58f1c22SToby Isaac   }
21879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s)));
2188c58f1c22SToby Isaac   globalOff -= off;
2189c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
2190c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2191c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
2192c58f1c22SToby Isaac   }
2193c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2194c58f1c22SToby Isaac   if (nroots >= 0) {
21959566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
21969566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
2197c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
2198c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
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 
22065fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
22075fdea053SToby Isaac {
22085fdea053SToby Isaac   DMLabel           label;
22095fdea053SToby Isaac   PetscCopyMode     *modes;
22105fdea053SToby Isaac   PetscInt          *sizes;
22115fdea053SToby Isaac   const PetscInt    ***perms;
22125fdea053SToby Isaac   const PetscScalar ***rots;
22135fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
22145fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
22155fdea053SToby Isaac } PetscSectionSym_Label;
22165fdea053SToby Isaac 
22175fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
22185fdea053SToby Isaac {
22195fdea053SToby Isaac   PetscInt              i, j;
22205fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
22215fdea053SToby Isaac 
22225fdea053SToby Isaac   PetscFunctionBegin;
22235fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
22245fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
22255fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22269566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
22279566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
22285fdea053SToby Isaac       }
22295fdea053SToby Isaac       if (sl->perms[i]) {
22305fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
22315fdea053SToby Isaac 
22329566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
22335fdea053SToby Isaac       }
22345fdea053SToby Isaac       if (sl->rots[i]) {
22355fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
22365fdea053SToby Isaac 
22379566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
22385fdea053SToby Isaac       }
22395fdea053SToby Isaac     }
22405fdea053SToby Isaac   }
22419566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients));
22429566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
22435fdea053SToby Isaac   sl->numStrata = 0;
22445fdea053SToby Isaac   PetscFunctionReturn(0);
22455fdea053SToby Isaac }
22465fdea053SToby Isaac 
22475fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
22485fdea053SToby Isaac {
22495fdea053SToby Isaac   PetscFunctionBegin;
22509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
22519566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
22525fdea053SToby Isaac   PetscFunctionReturn(0);
22535fdea053SToby Isaac }
22545fdea053SToby Isaac 
22555fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
22565fdea053SToby Isaac {
22575fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
22585fdea053SToby Isaac   PetscBool             isAscii;
22595fdea053SToby Isaac   DMLabel               label = sl->label;
2260d67d17b1SMatthew G. Knepley   const char           *name;
22615fdea053SToby Isaac 
22625fdea053SToby Isaac   PetscFunctionBegin;
22639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii));
22645fdea053SToby Isaac   if (isAscii) {
22655fdea053SToby Isaac     PetscInt          i, j, k;
22665fdea053SToby Isaac     PetscViewerFormat format;
22675fdea053SToby Isaac 
22689566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer,&format));
22695fdea053SToby Isaac     if (label) {
22709566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer,&format));
22715fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22729566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
22739566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
22749566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
22755fdea053SToby Isaac       } else {
22769566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
22779566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name));
22785fdea053SToby Isaac       }
22795fdea053SToby Isaac     } else {
22809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
22815fdea053SToby Isaac     }
22829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
22835fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
22845fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
22855fdea053SToby Isaac 
22865fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
228763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
22885fdea053SToby Isaac       } else {
228963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
22909566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
229163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
22925fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22939566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
22945fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22955fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
229663a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n",j));
22975fdea053SToby Isaac             } else {
22985fdea053SToby Isaac               PetscInt tab;
22995fdea053SToby Isaac 
230063a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n",j));
23019566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
23029566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer,&tab));
23035fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
23049566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"Permutation:"));
23059566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,0));
230663a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT,sl->perms[i][j][k]));
23079566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
23089566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,tab));
23095fdea053SToby Isaac               }
23105fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
23119566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"Rotations:  "));
23129566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,0));
23135fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
231463a3b9bcSJacob 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])));
23155fdea053SToby Isaac #else
231663a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %+g",(double)sl->rots[i][j][k]));
23175fdea053SToby Isaac #endif
23189566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
23199566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,tab));
23205fdea053SToby Isaac               }
23219566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
23225fdea053SToby Isaac             }
23235fdea053SToby Isaac           }
23249566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
23255fdea053SToby Isaac         }
23269566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
23275fdea053SToby Isaac       }
23285fdea053SToby Isaac     }
23299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
23305fdea053SToby Isaac   }
23315fdea053SToby Isaac   PetscFunctionReturn(0);
23325fdea053SToby Isaac }
23335fdea053SToby Isaac 
23345fdea053SToby Isaac /*@
23355fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
23365fdea053SToby Isaac 
23375fdea053SToby Isaac   Logically collective on sym
23385fdea053SToby Isaac 
23395fdea053SToby Isaac   Input parameters:
23405fdea053SToby Isaac + sym - the section symmetries
23415fdea053SToby Isaac - label - the DMLabel describing the types of points
23425fdea053SToby Isaac 
23435fdea053SToby Isaac   Level: developer:
23445fdea053SToby Isaac 
2345db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
23465fdea053SToby Isaac @*/
23475fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
23485fdea053SToby Isaac {
23495fdea053SToby Isaac   PetscSectionSym_Label *sl;
23505fdea053SToby Isaac 
23515fdea053SToby Isaac   PetscFunctionBegin;
23525fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
23535fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
23549566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
23555fdea053SToby Isaac   if (label) {
23565fdea053SToby Isaac     sl->label = label;
23579566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) label));
23589566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label,&sl->numStrata));
23599566063dSJacob 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));
23609566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode)));
23619566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt)));
23629566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **)));
23639566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **)));
23649566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2])));
23655fdea053SToby Isaac   }
23665fdea053SToby Isaac   PetscFunctionReturn(0);
23675fdea053SToby Isaac }
23685fdea053SToby Isaac 
23695fdea053SToby Isaac /*@C
2370b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2371b004864fSMatthew G. Knepley 
2372b004864fSMatthew G. Knepley   Logically collective on sym
2373b004864fSMatthew G. Knepley 
2374b004864fSMatthew G. Knepley   Input Parameters:
2375b004864fSMatthew G. Knepley + sym       - the section symmetries
2376b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2377b004864fSMatthew G. Knepley 
2378b004864fSMatthew G. Knepley   Output Parameters:
2379b004864fSMatthew G. Knepley + size      - the number of dofs for points in the stratum of the label
2380b004864fSMatthew G. Knepley . minOrient - the smallest orientation for a point in this stratum
2381b004864fSMatthew G. Knepley . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2382b004864fSMatthew G. Knepley . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2383b004864fSMatthew 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
2384b004864fSMatthew G. Knepley 
2385b004864fSMatthew G. Knepley   Level: developer
2386b004864fSMatthew G. Knepley 
2387db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2388b004864fSMatthew G. Knepley @*/
2389b004864fSMatthew G. Knepley PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2390b004864fSMatthew G. Knepley {
2391b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2392b004864fSMatthew G. Knepley   const char            *name;
2393b004864fSMatthew G. Knepley   PetscInt               i;
2394b004864fSMatthew G. Knepley 
2395b004864fSMatthew G. Knepley   PetscFunctionBegin;
2396b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
2397b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *) sym->data;
2398b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2399b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2400b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2401b004864fSMatthew G. Knepley 
2402b004864fSMatthew G. Knepley     if (stratum == value) break;
2403b004864fSMatthew G. Knepley   }
24049566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
2405b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
2406b004864fSMatthew G. Knepley   if (size)      {PetscValidIntPointer(size, 3);      *size      = sl->sizes[i];}
2407b004864fSMatthew G. Knepley   if (minOrient) {PetscValidIntPointer(minOrient, 4); *minOrient = sl->minMaxOrients[i][0];}
2408b004864fSMatthew G. Knepley   if (maxOrient) {PetscValidIntPointer(maxOrient, 5); *maxOrient = sl->minMaxOrients[i][1];}
2409b004864fSMatthew G. Knepley   if (perms)     {PetscValidPointer(perms, 6);        *perms     = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;}
2410b004864fSMatthew G. Knepley   if (rots)      {PetscValidPointer(rots, 7);         *rots      = sl->rots[i]  ? &sl->rots[i][sl->minMaxOrients[i][0]]  : NULL;}
2411b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2412b004864fSMatthew G. Knepley }
2413b004864fSMatthew G. Knepley 
2414b004864fSMatthew G. Knepley /*@C
24155fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
24165fdea053SToby Isaac 
24175b5e7992SMatthew G. Knepley   Logically collective on sym
24185fdea053SToby Isaac 
24195fdea053SToby Isaac   InputParameters:
24205b5e7992SMatthew G. Knepley + sym       - the section symmetries
24215fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
24225fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
24235fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
24245fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
24255fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
24265fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2427a2b725a8SWilliam 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
24285fdea053SToby Isaac 
24295fdea053SToby Isaac   Level: developer
24305fdea053SToby Isaac 
2431db781477SPatrick Sanan .seealso: `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
24325fdea053SToby Isaac @*/
24335fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
24345fdea053SToby Isaac {
24355fdea053SToby Isaac   PetscSectionSym_Label *sl;
2436d67d17b1SMatthew G. Knepley   const char            *name;
2437d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
24385fdea053SToby Isaac 
24395fdea053SToby Isaac   PetscFunctionBegin;
24405fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
24415fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
2442b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
24435fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
24445fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
24455fdea053SToby Isaac 
24465fdea053SToby Isaac     if (stratum == value) break;
24475fdea053SToby Isaac   }
24489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
244963a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
24505fdea053SToby Isaac   sl->sizes[i] = size;
24515fdea053SToby Isaac   sl->modes[i] = mode;
24525fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
24535fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
24545fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
24555fdea053SToby Isaac     if (perms) {
24565fdea053SToby Isaac       PetscInt    **ownPerms;
24575fdea053SToby Isaac 
24589566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient,&ownPerms));
24595fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
24605fdea053SToby Isaac         if (perms[j]) {
24619566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size,&ownPerms[j]));
24625fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
24635fdea053SToby Isaac         }
24645fdea053SToby Isaac       }
24655fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
24665fdea053SToby Isaac     }
24675fdea053SToby Isaac     if (rots) {
24685fdea053SToby Isaac       PetscScalar **ownRots;
24695fdea053SToby Isaac 
24709566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient,&ownRots));
24715fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
24725fdea053SToby Isaac         if (rots[j]) {
24739566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size,&ownRots[j]));
24745fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
24755fdea053SToby Isaac         }
24765fdea053SToby Isaac       }
24775fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
24785fdea053SToby Isaac     }
24795fdea053SToby Isaac   } else {
24805fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
24815fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
24825fdea053SToby Isaac   }
24835fdea053SToby Isaac   PetscFunctionReturn(0);
24845fdea053SToby Isaac }
24855fdea053SToby Isaac 
24865fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
24875fdea053SToby Isaac {
24885fdea053SToby Isaac   PetscInt              i, j, numStrata;
24895fdea053SToby Isaac   PetscSectionSym_Label *sl;
24905fdea053SToby Isaac   DMLabel               label;
24915fdea053SToby Isaac 
24925fdea053SToby Isaac   PetscFunctionBegin;
24935fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
24945fdea053SToby Isaac   numStrata = sl->numStrata;
24955fdea053SToby Isaac   label     = sl->label;
24965fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
24975fdea053SToby Isaac     PetscInt point = points[2*i];
24985fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
24995fdea053SToby Isaac 
25005fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
25015fdea053SToby Isaac       if (label->validIS[j]) {
25025fdea053SToby Isaac         PetscInt k;
25035fdea053SToby Isaac 
25049566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j],point,&k));
25055fdea053SToby Isaac         if (k >= 0) break;
25065fdea053SToby Isaac       } else {
25075fdea053SToby Isaac         PetscBool has;
25085fdea053SToby Isaac 
25099566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
25105fdea053SToby Isaac         if (has) break;
25115fdea053SToby Isaac       }
25125fdea053SToby Isaac     }
251363a3b9bcSJacob Faibussowitsch     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],j < numStrata ? label->stratumValues[j] : label->defaultValue);
25145fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
25155fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
25165fdea053SToby Isaac   }
25175fdea053SToby Isaac   PetscFunctionReturn(0);
25185fdea053SToby Isaac }
25195fdea053SToby Isaac 
2520b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2521b004864fSMatthew G. Knepley {
2522b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) nsym->data;
2523b004864fSMatthew G. Knepley   IS                     valIS;
2524b004864fSMatthew G. Knepley   const PetscInt        *values;
2525b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2526b004864fSMatthew G. Knepley 
2527b004864fSMatthew G. Knepley   PetscFunctionBegin;
25289566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
25299566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
25309566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2531b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2532b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2533b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2534b004864fSMatthew G. Knepley     const PetscInt    **perms;
2535b004864fSMatthew G. Knepley     const PetscScalar **rots;
2536b004864fSMatthew G. Knepley 
25379566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym,  val, &size, &minOrient, &maxOrient, &perms, &rots));
25389566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val,  size,  minOrient,  maxOrient, PETSC_COPY_VALUES, perms, rots));
2539b004864fSMatthew G. Knepley   }
25409566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
2541b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2542b004864fSMatthew G. Knepley }
2543b004864fSMatthew G. Knepley 
2544b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2545b004864fSMatthew G. Knepley {
2546b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
2547b004864fSMatthew G. Knepley   DMLabel                dlabel;
2548b004864fSMatthew G. Knepley 
2549b004864fSMatthew G. Knepley   PetscFunctionBegin;
25509566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
25519566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject) sym), dlabel, dsym));
25529566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
25539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
2554b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2555b004864fSMatthew G. Knepley }
2556b004864fSMatthew G. Knepley 
25575fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
25585fdea053SToby Isaac {
25595fdea053SToby Isaac   PetscSectionSym_Label *sl;
25605fdea053SToby Isaac 
25615fdea053SToby Isaac   PetscFunctionBegin;
25629566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(sym,&sl));
25635fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2564b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2565b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
25665fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
25675fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
25685fdea053SToby Isaac   sym->data            = (void *) sl;
25695fdea053SToby Isaac   PetscFunctionReturn(0);
25705fdea053SToby Isaac }
25715fdea053SToby Isaac 
25725fdea053SToby Isaac /*@
25735fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
25745fdea053SToby Isaac 
25755fdea053SToby Isaac   Collective
25765fdea053SToby Isaac 
25775fdea053SToby Isaac   Input Parameters:
25785fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
25795fdea053SToby Isaac - label - the label defining the strata
25805fdea053SToby Isaac 
25815fdea053SToby Isaac   Output Parameters:
25825fdea053SToby Isaac . sym - the section symmetries
25835fdea053SToby Isaac 
25845fdea053SToby Isaac   Level: developer
25855fdea053SToby Isaac 
2586db781477SPatrick Sanan .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
25875fdea053SToby Isaac @*/
25885fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
25895fdea053SToby Isaac {
25905fdea053SToby Isaac   PetscFunctionBegin;
25919566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
25929566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm,sym));
25939566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL));
25949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym,label));
25955fdea053SToby Isaac   PetscFunctionReturn(0);
25965fdea053SToby Isaac }
2597