xref: /petsc/src/dm/label/dmlabel.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
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 @*/
279371c9d4SSatish Balay PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label) {
28c58f1c22SToby Isaac   PetscFunctionBegin;
29064a246eSJacob Faibussowitsch   PetscValidPointer(label, 3);
309566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
31c58f1c22SToby Isaac 
329566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*label, DMLABEL_CLASSID, "DMLabel", "DMLabel", "DM", comm, DMLabelDestroy, DMLabelView));
33d67d17b1SMatthew G. Knepley 
34c58f1c22SToby Isaac   (*label)->numStrata     = 0;
355aa44df4SToby Isaac   (*label)->defaultValue  = -1;
36c58f1c22SToby Isaac   (*label)->stratumValues = NULL;
37ad8374ffSToby Isaac   (*label)->validIS       = NULL;
38c58f1c22SToby Isaac   (*label)->stratumSizes  = NULL;
39c58f1c22SToby Isaac   (*label)->points        = NULL;
40c58f1c22SToby Isaac   (*label)->ht            = NULL;
41c58f1c22SToby Isaac   (*label)->pStart        = -1;
42c58f1c22SToby Isaac   (*label)->pEnd          = -1;
43c58f1c22SToby Isaac   (*label)->bt            = NULL;
449566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
459566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*label, name));
46c58f1c22SToby Isaac   PetscFunctionReturn(0);
47c58f1c22SToby Isaac }
48c58f1c22SToby Isaac 
49c58f1c22SToby Isaac /*
50c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
51c58f1c22SToby Isaac 
525b5e7992SMatthew G. Knepley   Not collective
535b5e7992SMatthew G. Knepley 
54c58f1c22SToby Isaac   Input parameter:
55c58f1c22SToby Isaac + label - The DMLabel
56c58f1c22SToby Isaac - v - The stratum value
57c58f1c22SToby Isaac 
58c58f1c22SToby Isaac   Output parameter:
59c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
60c58f1c22SToby Isaac 
61c58f1c22SToby Isaac   Level: developer
62c58f1c22SToby Isaac 
63db781477SPatrick Sanan .seealso: `DMLabelCreate()`
64c58f1c22SToby Isaac */
659371c9d4SSatish Balay static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v) {
66277ea44aSLisandro Dalcin   IS       is;
67b9907514SLisandro Dalcin   PetscInt off = 0, *pointArray, p;
68c58f1c22SToby Isaac 
69b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
70c58f1c22SToby Isaac   PetscFunctionBegin;
711dca8a05SBarry 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);
729566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
749566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
759566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
769566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
77c58f1c22SToby Isaac   if (label->bt) {
78c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
79ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
8063a3b9bcSJacob 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);
819566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
82c58f1c22SToby Isaac     }
83c58f1c22SToby Isaac   }
84ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v] - 1] == pointArray[0] + label->stratumSizes[v] - 1) {
859566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
869566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
87ba2698f1SMatthew G. Knepley   } else {
889566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
89ba2698f1SMatthew G. Knepley   }
909566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)is, "indices"));
91277ea44aSLisandro Dalcin   label->points[v]  = is;
92ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
939566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
94c58f1c22SToby Isaac   PetscFunctionReturn(0);
95c58f1c22SToby Isaac }
96c58f1c22SToby Isaac 
97c58f1c22SToby Isaac /*
98c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
99c58f1c22SToby Isaac 
1005b5e7992SMatthew G. Knepley   Not collective
1015b5e7992SMatthew G. Knepley 
102c58f1c22SToby Isaac   Input parameter:
103c58f1c22SToby Isaac . label - The DMLabel
104c58f1c22SToby Isaac 
105c58f1c22SToby Isaac   Output parameter:
106c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
107c58f1c22SToby Isaac 
108c58f1c22SToby Isaac   Level: developer
109c58f1c22SToby Isaac 
110db781477SPatrick Sanan .seealso: `DMLabelCreate()`
111c58f1c22SToby Isaac */
1129371c9d4SSatish Balay static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label) {
113c58f1c22SToby Isaac   PetscInt v;
114c58f1c22SToby Isaac 
115c58f1c22SToby Isaac   PetscFunctionBegin;
11648a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeValid_Private(label, v));
117c58f1c22SToby Isaac   PetscFunctionReturn(0);
118c58f1c22SToby Isaac }
119c58f1c22SToby Isaac 
120c58f1c22SToby Isaac /*
121c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
122c58f1c22SToby Isaac 
1235b5e7992SMatthew G. Knepley   Not collective
1245b5e7992SMatthew G. Knepley 
125c58f1c22SToby Isaac   Input parameter:
126c58f1c22SToby Isaac + label - The DMLabel
127c58f1c22SToby Isaac - v - The stratum value
128c58f1c22SToby Isaac 
129c58f1c22SToby Isaac   Output parameter:
130c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
131c58f1c22SToby Isaac 
132c58f1c22SToby Isaac   Level: developer
133c58f1c22SToby Isaac 
134db781477SPatrick Sanan .seealso: `DMLabelCreate()`
135c58f1c22SToby Isaac */
1369371c9d4SSatish Balay static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v) {
137c58f1c22SToby Isaac   PetscInt        p;
138ad8374ffSToby Isaac   const PetscInt *points;
139c58f1c22SToby Isaac 
140b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
141c58f1c22SToby Isaac   PetscFunctionBegin;
1421dca8a05SBarry 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);
143ad8374ffSToby Isaac   if (label->points[v]) {
1449566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
14548a46eb9SPierre Jolivet     for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
1469566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
1479566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&(label->points[v])));
148ad8374ffSToby Isaac   }
149ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
150c58f1c22SToby Isaac   PetscFunctionReturn(0);
151c58f1c22SToby Isaac }
152c58f1c22SToby Isaac 
1539371c9d4SSatish Balay PetscErrorCode DMLabelMakeAllInvalid_Internal(DMLabel label) {
154695799ffSMatthew G. Knepley   PetscInt v;
155695799ffSMatthew G. Knepley 
156695799ffSMatthew G. Knepley   PetscFunctionBegin;
15748a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; v++) PetscCall(DMLabelMakeInvalid_Private(label, v));
158695799ffSMatthew G. Knepley   PetscFunctionReturn(0);
159695799ffSMatthew G. Knepley }
160695799ffSMatthew G. Knepley 
161b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
162b9907514SLisandro Dalcin #define DMLABEL_LOOKUP_THRESHOLD 16
163b9907514SLisandro Dalcin #endif
164b9907514SLisandro Dalcin 
1659371c9d4SSatish Balay static inline PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index) {
1660c3c4a36SLisandro Dalcin   PetscInt v;
1670e79e033SBarry Smith 
1680c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1690e79e033SBarry Smith   *index = -1;
170b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
171b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
1729371c9d4SSatish Balay       if (label->stratumValues[v] == value) {
1739371c9d4SSatish Balay         *index = v;
1749371c9d4SSatish Balay         break;
1759371c9d4SSatish Balay       }
176b9907514SLisandro Dalcin   } else {
1779566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(label->hmap, value, index));
1780e79e033SBarry Smith   }
17976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */
18090e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
1819566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(label->hmap, &len));
18208401ef6SPierre Jolivet     PetscCheck(len == label->numStrata, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
18390e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
1849566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(label->hmap, value, &loc));
18590e9b2aeSLisandro Dalcin     } else {
18690e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
1879371c9d4SSatish Balay         if (label->stratumValues[v] == value) {
1889371c9d4SSatish Balay           loc = v;
1899371c9d4SSatish Balay           break;
1909371c9d4SSatish Balay         }
19190e9b2aeSLisandro Dalcin     }
19208401ef6SPierre Jolivet     PetscCheck(loc == *index, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
19390e9b2aeSLisandro Dalcin   }
1940c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
1950c3c4a36SLisandro Dalcin }
1960c3c4a36SLisandro Dalcin 
1979371c9d4SSatish Balay static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index) {
198b9907514SLisandro Dalcin   PetscInt    v;
199b9907514SLisandro Dalcin   PetscInt   *tmpV;
200b9907514SLisandro Dalcin   PetscInt   *tmpS;
201b9907514SLisandro Dalcin   PetscHSetI *tmpH, ht;
202b9907514SLisandro Dalcin   IS         *tmpP, is;
203c58f1c22SToby Isaac   PetscBool  *tmpB;
204b9907514SLisandro Dalcin   PetscHMapI  hmap = label->hmap;
205c58f1c22SToby Isaac 
206c58f1c22SToby Isaac   PetscFunctionBegin;
207b9907514SLisandro Dalcin   v    = label->numStrata;
208b9907514SLisandro Dalcin   tmpV = label->stratumValues;
209b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
210b9907514SLisandro Dalcin   tmpH = label->ht;
211b9907514SLisandro Dalcin   tmpP = label->points;
212b9907514SLisandro Dalcin   tmpB = label->validIS;
2138e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2148e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2158e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2168e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2178e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2188e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpV), &tmpV));
2209566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpS), &tmpS));
2219566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpH), &tmpH));
2229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpP), &tmpP));
2239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v + 1) * sizeof(*tmpB), &tmpB));
2249566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpV, oldV, v));
2259566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpS, oldS, v));
2269566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpH, oldH, v));
2279566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpP, oldP, v));
2289566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpB, oldB, v));
2299566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldV));
2309566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldS));
2319566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldH));
2329566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldP));
2339566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldB));
2348e1f8cf0SLisandro Dalcin   }
235b9907514SLisandro Dalcin   label->numStrata     = v + 1;
236c58f1c22SToby Isaac   label->stratumValues = tmpV;
237c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
238c58f1c22SToby Isaac   label->ht            = tmpH;
239c58f1c22SToby Isaac   label->points        = tmpP;
240ad8374ffSToby Isaac   label->validIS       = tmpB;
2419566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
2429566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
2439566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(hmap, value, v));
244b9907514SLisandro Dalcin   tmpV[v] = value;
245b9907514SLisandro Dalcin   tmpS[v] = 0;
246b9907514SLisandro Dalcin   tmpH[v] = ht;
247b9907514SLisandro Dalcin   tmpP[v] = is;
248b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
2499566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
2500c3c4a36SLisandro Dalcin   *index = v;
2510c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2520c3c4a36SLisandro Dalcin }
2530c3c4a36SLisandro Dalcin 
2549371c9d4SSatish Balay static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index) {
255b9907514SLisandro Dalcin   PetscFunctionBegin;
2569566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, index));
2579566063dSJacob Faibussowitsch   if (*index < 0) PetscCall(DMLabelNewStratum(label, value, index));
258b9907514SLisandro Dalcin   PetscFunctionReturn(0);
259b9907514SLisandro Dalcin }
260b9907514SLisandro Dalcin 
2619371c9d4SSatish Balay static inline PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size) {
2629e63cc69SVaclav Hapla   PetscFunctionBegin;
2639e63cc69SVaclav Hapla   *size = 0;
2649e63cc69SVaclav Hapla   if (v < 0) PetscFunctionReturn(0);
2659e63cc69SVaclav Hapla   if (label->validIS[v]) {
2669e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
2679e63cc69SVaclav Hapla   } else {
2689566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(label->ht[v], size));
2699e63cc69SVaclav Hapla   }
2709e63cc69SVaclav Hapla   PetscFunctionReturn(0);
2719e63cc69SVaclav Hapla }
2729e63cc69SVaclav Hapla 
273b9907514SLisandro Dalcin /*@
274b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
275b9907514SLisandro Dalcin 
276d8d19677SJose E. Roman   Input Parameters:
277b9907514SLisandro Dalcin + label - The DMLabel
278b9907514SLisandro Dalcin - value - The stratum value
279b9907514SLisandro Dalcin 
280b9907514SLisandro Dalcin   Level: beginner
281b9907514SLisandro Dalcin 
282db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
283b9907514SLisandro Dalcin @*/
2849371c9d4SSatish Balay PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value) {
2850c3c4a36SLisandro Dalcin   PetscInt v;
2860c3c4a36SLisandro Dalcin 
2870c3c4a36SLisandro Dalcin   PetscFunctionBegin;
288d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2899566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
290b9907514SLisandro Dalcin   PetscFunctionReturn(0);
291b9907514SLisandro Dalcin }
292b9907514SLisandro Dalcin 
293b9907514SLisandro Dalcin /*@
294b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
295b9907514SLisandro Dalcin 
2965b5e7992SMatthew G. Knepley   Not collective
2975b5e7992SMatthew G. Knepley 
298d8d19677SJose E. Roman   Input Parameters:
299b9907514SLisandro Dalcin + label - The DMLabel
300b9907514SLisandro Dalcin . numStrata - The number of stratum values
301b9907514SLisandro Dalcin - stratumValues - The stratum values
302b9907514SLisandro Dalcin 
303b9907514SLisandro Dalcin   Level: beginner
304b9907514SLisandro Dalcin 
305db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
306b9907514SLisandro Dalcin @*/
3079371c9d4SSatish Balay PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[]) {
308b9907514SLisandro Dalcin   PetscInt *values, v;
309b9907514SLisandro Dalcin 
310b9907514SLisandro Dalcin   PetscFunctionBegin;
311b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
312b9907514SLisandro Dalcin   if (numStrata) PetscValidIntPointer(stratumValues, 3);
3139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numStrata, &values));
3149566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(values, stratumValues, numStrata));
3159566063dSJacob Faibussowitsch   PetscCall(PetscSortRemoveDupsInt(&numStrata, values));
316b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
317b9907514SLisandro Dalcin     PetscInt   *tmpV;
318b9907514SLisandro Dalcin     PetscInt   *tmpS;
319b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
320b9907514SLisandro Dalcin     IS         *tmpP, is;
321b9907514SLisandro Dalcin     PetscBool  *tmpB;
322b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
323b9907514SLisandro Dalcin 
3249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpV));
3259566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpS));
3269566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpH));
3279566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpP));
3289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(numStrata, &tmpB));
329b9907514SLisandro Dalcin     label->numStrata     = numStrata;
330b9907514SLisandro Dalcin     label->stratumValues = tmpV;
331b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
332b9907514SLisandro Dalcin     label->ht            = tmpH;
333b9907514SLisandro Dalcin     label->points        = tmpP;
334b9907514SLisandro Dalcin     label->validIS       = tmpB;
335b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3369566063dSJacob Faibussowitsch       PetscCall(PetscHSetICreate(&ht));
3379566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &is));
3389566063dSJacob Faibussowitsch       PetscCall(PetscHMapISet(hmap, values[v], v));
339b9907514SLisandro Dalcin       tmpV[v] = values[v];
340b9907514SLisandro Dalcin       tmpS[v] = 0;
341b9907514SLisandro Dalcin       tmpH[v] = ht;
342b9907514SLisandro Dalcin       tmpP[v] = is;
343b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
344b9907514SLisandro Dalcin     }
3459566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
346b9907514SLisandro Dalcin   } else {
34748a46eb9SPierre Jolivet     for (v = 0; v < numStrata; ++v) PetscCall(DMLabelAddStratum(label, values[v]));
348b9907514SLisandro Dalcin   }
3499566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
350b9907514SLisandro Dalcin   PetscFunctionReturn(0);
351b9907514SLisandro Dalcin }
352b9907514SLisandro Dalcin 
353b9907514SLisandro Dalcin /*@
354b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
355b9907514SLisandro Dalcin 
3565b5e7992SMatthew G. Knepley   Not collective
3575b5e7992SMatthew G. Knepley 
358d8d19677SJose E. Roman   Input Parameters:
359b9907514SLisandro Dalcin + label - The DMLabel
360b9907514SLisandro Dalcin - valueIS - Index set with stratum values
361b9907514SLisandro Dalcin 
362b9907514SLisandro Dalcin   Level: beginner
363b9907514SLisandro Dalcin 
364db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
365b9907514SLisandro Dalcin @*/
3669371c9d4SSatish Balay PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS) {
367b9907514SLisandro Dalcin   PetscInt        numStrata;
368b9907514SLisandro Dalcin   const PetscInt *stratumValues;
369b9907514SLisandro Dalcin 
370b9907514SLisandro Dalcin   PetscFunctionBegin;
371b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
372b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
3739566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(valueIS, &numStrata));
3749566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valueIS, &stratumValues));
3759566063dSJacob Faibussowitsch   PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
376c58f1c22SToby Isaac   PetscFunctionReturn(0);
377c58f1c22SToby Isaac }
378c58f1c22SToby Isaac 
3799371c9d4SSatish Balay static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer) {
380c58f1c22SToby Isaac   PetscInt    v;
381c58f1c22SToby Isaac   PetscMPIInt rank;
382c58f1c22SToby Isaac 
383c58f1c22SToby Isaac   PetscFunctionBegin;
3849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3859566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
386c58f1c22SToby Isaac   if (label) {
387d67d17b1SMatthew G. Knepley     const char *name;
388d67d17b1SMatthew G. Knepley 
3899566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
3909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
39163a3b9bcSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", label->pStart, label->pEnd));
392c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
393c58f1c22SToby Isaac       const PetscInt  value = label->stratumValues[v];
394ad8374ffSToby Isaac       const PetscInt *points;
395c58f1c22SToby Isaac       PetscInt        p;
396c58f1c22SToby Isaac 
3979566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
39848a46eb9SPierre Jolivet       for (p = 0; p < label->stratumSizes[v]; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, points[p], value));
3999566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
400c58f1c22SToby Isaac     }
401c58f1c22SToby Isaac   }
4029566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4039566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
404c58f1c22SToby Isaac   PetscFunctionReturn(0);
405c58f1c22SToby Isaac }
406c58f1c22SToby Isaac 
407c58f1c22SToby Isaac /*@C
408c58f1c22SToby Isaac   DMLabelView - View the label
409c58f1c22SToby Isaac 
4105b5e7992SMatthew G. Knepley   Collective on viewer
4115b5e7992SMatthew G. Knepley 
412c58f1c22SToby Isaac   Input Parameters:
413c58f1c22SToby Isaac + label - The DMLabel
414c58f1c22SToby Isaac - viewer - The PetscViewer
415c58f1c22SToby Isaac 
416c58f1c22SToby Isaac   Level: intermediate
417c58f1c22SToby Isaac 
418db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
419c58f1c22SToby Isaac @*/
4209371c9d4SSatish Balay PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer) {
421c58f1c22SToby Isaac   PetscBool iascii;
422c58f1c22SToby Isaac 
423c58f1c22SToby Isaac   PetscFunctionBegin;
424d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4259566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
426c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4279566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
4289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4291baa6e33SBarry Smith   if (iascii) PetscCall(DMLabelView_Ascii(label, viewer));
430c58f1c22SToby Isaac   PetscFunctionReturn(0);
431c58f1c22SToby Isaac }
432c58f1c22SToby Isaac 
43384f0b6dfSMatthew G. Knepley /*@
434d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
435d67d17b1SMatthew G. Knepley 
4365b5e7992SMatthew G. Knepley   Not collective
4375b5e7992SMatthew G. Knepley 
438d67d17b1SMatthew G. Knepley   Input Parameter:
439d67d17b1SMatthew G. Knepley . label - The DMLabel
440d67d17b1SMatthew G. Knepley 
441d67d17b1SMatthew G. Knepley   Level: beginner
442d67d17b1SMatthew G. Knepley 
443db781477SPatrick Sanan .seealso: `DMLabelDestroy()`, `DMLabelCreate()`
444d67d17b1SMatthew G. Knepley @*/
4459371c9d4SSatish Balay PetscErrorCode DMLabelReset(DMLabel label) {
446d67d17b1SMatthew G. Knepley   PetscInt v;
447d67d17b1SMatthew G. Knepley 
448d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
449d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
450d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
4519566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&label->ht[v]));
4529566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
453d67d17b1SMatthew G. Knepley   }
454b9907514SLisandro Dalcin   label->numStrata = 0;
4559566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
4569566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
4579566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
4589566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
4599566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
460f9244615SMatthew G. Knepley   label->stratumValues = NULL;
461f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
462f9244615SMatthew G. Knepley   label->ht            = NULL;
463f9244615SMatthew G. Knepley   label->points        = NULL;
464f9244615SMatthew G. Knepley   label->validIS       = NULL;
4659566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
466b9907514SLisandro Dalcin   label->pStart = -1;
467b9907514SLisandro Dalcin   label->pEnd   = -1;
4689566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
469d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
470d67d17b1SMatthew G. Knepley }
471d67d17b1SMatthew G. Knepley 
472d67d17b1SMatthew G. Knepley /*@
47384f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
47484f0b6dfSMatthew G. Knepley 
4755b5e7992SMatthew G. Knepley   Collective on label
4765b5e7992SMatthew G. Knepley 
47784f0b6dfSMatthew G. Knepley   Input Parameter:
47884f0b6dfSMatthew G. Knepley . label - The DMLabel
47984f0b6dfSMatthew G. Knepley 
48084f0b6dfSMatthew G. Knepley   Level: beginner
48184f0b6dfSMatthew G. Knepley 
482db781477SPatrick Sanan .seealso: `DMLabelReset()`, `DMLabelCreate()`
48384f0b6dfSMatthew G. Knepley @*/
4849371c9d4SSatish Balay PetscErrorCode DMLabelDestroy(DMLabel *label) {
485c58f1c22SToby Isaac   PetscFunctionBegin;
486d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
487d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label), DMLABEL_CLASSID, 1);
4889371c9d4SSatish Balay   if (--((PetscObject)(*label))->refct > 0) {
4899371c9d4SSatish Balay     *label = NULL;
4909371c9d4SSatish Balay     PetscFunctionReturn(0);
4919371c9d4SSatish Balay   }
4929566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
4939566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
4949566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
495c58f1c22SToby Isaac   PetscFunctionReturn(0);
496c58f1c22SToby Isaac }
497c58f1c22SToby Isaac 
49884f0b6dfSMatthew G. Knepley /*@
49984f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
50084f0b6dfSMatthew G. Knepley 
5015b5e7992SMatthew G. Knepley   Collective on label
5025b5e7992SMatthew G. Knepley 
50384f0b6dfSMatthew G. Knepley   Input Parameter:
50484f0b6dfSMatthew G. Knepley . label - The DMLabel
50584f0b6dfSMatthew G. Knepley 
50684f0b6dfSMatthew G. Knepley   Output Parameter:
50784f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
50884f0b6dfSMatthew G. Knepley 
50984f0b6dfSMatthew G. Knepley   Level: intermediate
51084f0b6dfSMatthew G. Knepley 
511db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
51284f0b6dfSMatthew G. Knepley @*/
5139371c9d4SSatish Balay PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew) {
514d67d17b1SMatthew G. Knepley   const char *name;
515ad8374ffSToby Isaac   PetscInt    v;
516c58f1c22SToby Isaac 
517c58f1c22SToby Isaac   PetscFunctionBegin;
518d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5199566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5209566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
5219566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)label), name, labelnew));
522c58f1c22SToby Isaac 
523c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5245aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->ht));
5289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->points));
5299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
530c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
5319566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
532c58f1c22SToby Isaac     (*labelnew)->stratumValues[v] = label->stratumValues[v];
533c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]  = label->stratumSizes[v];
5349566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)(label->points[v])));
535ad8374ffSToby Isaac     (*labelnew)->points[v]  = label->points[v];
536b9907514SLisandro Dalcin     (*labelnew)->validIS[v] = PETSC_TRUE;
537c58f1c22SToby Isaac   }
5389566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5399566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDuplicate(label->hmap, &(*labelnew)->hmap));
540c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
541c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
542c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
543c58f1c22SToby Isaac   PetscFunctionReturn(0);
544c58f1c22SToby Isaac }
545c58f1c22SToby Isaac 
546609dae6eSVaclav Hapla /*@C
547609dae6eSVaclav Hapla   DMLabelCompare - Compare two DMLabel objects
548609dae6eSVaclav Hapla 
5495efe38ccSVaclav Hapla   Collective on comm
550609dae6eSVaclav Hapla 
551609dae6eSVaclav Hapla   Input Parameters:
552f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
553f1a722f8SMatthew G. Knepley . l0 - First DMLabel
554609dae6eSVaclav Hapla - l1 - Second DMLabel
555609dae6eSVaclav Hapla 
556609dae6eSVaclav Hapla   Output Parameters
5575efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
5585efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
559609dae6eSVaclav Hapla 
560609dae6eSVaclav Hapla   Level: intermediate
561609dae6eSVaclav Hapla 
562609dae6eSVaclav Hapla   Notes:
5635efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
5645efe38ccSVaclav Hapla   If it is passed as NULL and difference is found, an error is thrown on all processes.
5655efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
566609dae6eSVaclav Hapla 
5675efe38ccSVaclav Hapla   The output message is set independently on each rank.
5685efe38ccSVaclav Hapla   It is set to NULL if no difference was found on the current rank. It must be freed by user.
5695efe38ccSVaclav Hapla   If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
5705efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
571609dae6eSVaclav Hapla 
572609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
573609dae6eSVaclav Hapla 
5745efe38ccSVaclav Hapla   The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
5755efe38ccSVaclav Hapla 
576609dae6eSVaclav Hapla   Fortran Notes:
577609dae6eSVaclav Hapla   This function is currently not available from Fortran.
578609dae6eSVaclav Hapla 
579db781477SPatrick Sanan .seealso: `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
580609dae6eSVaclav Hapla @*/
5819371c9d4SSatish Balay PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message) {
582609dae6eSVaclav Hapla   const char *name0, *name1;
583609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
5845efe38ccSVaclav Hapla   PetscBool   eq;
5855efe38ccSVaclav Hapla   PetscMPIInt rank;
586609dae6eSVaclav Hapla 
587609dae6eSVaclav Hapla   PetscFunctionBegin;
5885efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
5895efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
5905efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
5915efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
5929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5939566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
5949566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
595609dae6eSVaclav Hapla   {
596609dae6eSVaclav Hapla     PetscInt v0, v1;
597609dae6eSVaclav Hapla 
5989566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
5999566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6005efe38ccSVaclav Hapla     eq = (PetscBool)(v0 == v1);
60148a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Default value of DMLabel l0 \"%s\" = %" PetscInt_FMT " != %" PetscInt_FMT " = Default value of DMLabel l1 \"%s\"", name0, v0, v1, name1));
6029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6035efe38ccSVaclav Hapla     if (!eq) goto finish;
604609dae6eSVaclav Hapla   }
605609dae6eSVaclav Hapla   {
606609dae6eSVaclav Hapla     IS is0, is1;
607609dae6eSVaclav Hapla 
6089566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6099566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6109566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6119566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
61348a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
6149566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6155efe38ccSVaclav Hapla     if (!eq) goto finish;
616609dae6eSVaclav Hapla   }
617609dae6eSVaclav Hapla   {
618609dae6eSVaclav Hapla     PetscInt i, nValues;
619609dae6eSVaclav Hapla 
6209566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
621609dae6eSVaclav Hapla     for (i = 0; i < nValues; i++) {
622609dae6eSVaclav Hapla       const PetscInt v = l0->stratumValues[i];
623609dae6eSVaclav Hapla       PetscInt       n;
624609dae6eSVaclav Hapla       IS             is0, is1;
625609dae6eSVaclav Hapla 
6269566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
627609dae6eSVaclav Hapla       if (!n) continue;
6289566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6299566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6309566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6319566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6329566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6335efe38ccSVaclav Hapla       if (!eq) {
63463a3b9bcSJacob 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));
6355efe38ccSVaclav Hapla         break;
636609dae6eSVaclav Hapla       }
637609dae6eSVaclav Hapla     }
6389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
639609dae6eSVaclav Hapla   }
640609dae6eSVaclav Hapla finish:
6415efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
642609dae6eSVaclav Hapla   if (message) {
643609dae6eSVaclav Hapla     *message = NULL;
64448a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
6455efe38ccSVaclav Hapla   } else {
64648a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
6479566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
6485efe38ccSVaclav Hapla   }
6495efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
6505efe38ccSVaclav Hapla   if (equal) *equal = eq;
65163a3b9bcSJacob Faibussowitsch   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal", name0, name1);
652609dae6eSVaclav Hapla   PetscFunctionReturn(0);
653609dae6eSVaclav Hapla }
654609dae6eSVaclav Hapla 
655c6a43d28SMatthew G. Knepley /*@
656c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
657c6a43d28SMatthew G. Knepley 
6585b5e7992SMatthew G. Knepley   Not collective
6595b5e7992SMatthew G. Knepley 
660c6a43d28SMatthew G. Knepley   Input Parameter:
661c6a43d28SMatthew G. Knepley . label  - The DMLabel
662c6a43d28SMatthew G. Knepley 
663c6a43d28SMatthew G. Knepley   Level: intermediate
664c6a43d28SMatthew G. Knepley 
665db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
666c6a43d28SMatthew G. Knepley @*/
6679371c9d4SSatish Balay PetscErrorCode DMLabelComputeIndex(DMLabel label) {
668c6a43d28SMatthew G. Knepley   PetscInt pStart = PETSC_MAX_INT, pEnd = -1, v;
669c6a43d28SMatthew G. Knepley 
670c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
671c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6729566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
673c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
674c6a43d28SMatthew G. Knepley     const PetscInt *points;
675c6a43d28SMatthew G. Knepley     PetscInt        i;
676c6a43d28SMatthew G. Knepley 
6779566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
678c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
679c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
680c6a43d28SMatthew G. Knepley 
681c6a43d28SMatthew G. Knepley       pStart = PetscMin(point, pStart);
682c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point + 1, pEnd);
683c6a43d28SMatthew G. Knepley     }
6849566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
685c6a43d28SMatthew G. Knepley   }
686c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
687c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
6889566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
689c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
690c6a43d28SMatthew G. Knepley }
691c6a43d28SMatthew G. Knepley 
692c6a43d28SMatthew G. Knepley /*@
693c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
694c6a43d28SMatthew G. Knepley 
6955b5e7992SMatthew G. Knepley   Not collective
6965b5e7992SMatthew G. Knepley 
697c6a43d28SMatthew G. Knepley   Input Parameters:
698c6a43d28SMatthew G. Knepley + label  - The DMLabel
699c6a43d28SMatthew G. Knepley . pStart - The smallest point
700c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
701c6a43d28SMatthew G. Knepley 
702c6a43d28SMatthew G. Knepley   Level: intermediate
703c6a43d28SMatthew G. Knepley 
704db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
705c6a43d28SMatthew G. Knepley @*/
7069371c9d4SSatish Balay PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd) {
707c58f1c22SToby Isaac   PetscInt v;
708c58f1c22SToby Isaac 
709c58f1c22SToby Isaac   PetscFunctionBegin;
710d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7119566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7129566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
713c58f1c22SToby Isaac   label->pStart = pStart;
714c58f1c22SToby Isaac   label->pEnd   = pEnd;
715c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7169566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
717c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
718ad8374ffSToby Isaac     const PetscInt *points;
719c58f1c22SToby Isaac     PetscInt        i;
720c58f1c22SToby Isaac 
7219566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
722c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
723ad8374ffSToby Isaac       const PetscInt point = points[i];
724c58f1c22SToby Isaac 
72563a3b9bcSJacob 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);
7269566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
727c58f1c22SToby Isaac     }
7289566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
729c58f1c22SToby Isaac   }
730c58f1c22SToby Isaac   PetscFunctionReturn(0);
731c58f1c22SToby Isaac }
732c58f1c22SToby Isaac 
733c6a43d28SMatthew G. Knepley /*@
734c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
735c6a43d28SMatthew G. Knepley 
7365b5e7992SMatthew G. Knepley   Not collective
7375b5e7992SMatthew G. Knepley 
738c6a43d28SMatthew G. Knepley   Input Parameter:
739c6a43d28SMatthew G. Knepley . label - the DMLabel
740c6a43d28SMatthew G. Knepley 
741c6a43d28SMatthew G. Knepley   Level: intermediate
742c6a43d28SMatthew G. Knepley 
743db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
744c6a43d28SMatthew G. Knepley @*/
7459371c9d4SSatish Balay PetscErrorCode DMLabelDestroyIndex(DMLabel label) {
746c58f1c22SToby Isaac   PetscFunctionBegin;
747d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
748c58f1c22SToby Isaac   label->pStart = -1;
749c58f1c22SToby Isaac   label->pEnd   = -1;
7509566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
751c58f1c22SToby Isaac   PetscFunctionReturn(0);
752c58f1c22SToby Isaac }
753c58f1c22SToby Isaac 
754c58f1c22SToby Isaac /*@
755c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
756c6a43d28SMatthew G. Knepley 
7575b5e7992SMatthew G. Knepley   Not collective
7585b5e7992SMatthew G. Knepley 
759c6a43d28SMatthew G. Knepley   Input Parameter:
760c6a43d28SMatthew G. Knepley . label - the DMLabel
761c6a43d28SMatthew G. Knepley 
762c6a43d28SMatthew G. Knepley   Output Parameters:
763c6a43d28SMatthew G. Knepley + pStart - The smallest point
764c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
765c6a43d28SMatthew G. Knepley 
766c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
767c6a43d28SMatthew G. Knepley 
768c6a43d28SMatthew G. Knepley   Level: intermediate
769c6a43d28SMatthew G. Knepley 
770db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
771c6a43d28SMatthew G. Knepley @*/
7729371c9d4SSatish Balay PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd) {
773c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
774c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7759566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
776c6a43d28SMatthew G. Knepley   if (pStart) {
777534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
778c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
779c6a43d28SMatthew G. Knepley   }
780c6a43d28SMatthew G. Knepley   if (pEnd) {
781534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
782c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
783c6a43d28SMatthew G. Knepley   }
784c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
785c6a43d28SMatthew G. Knepley }
786c6a43d28SMatthew G. Knepley 
787c6a43d28SMatthew G. Knepley /*@
788c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
789c58f1c22SToby Isaac 
7905b5e7992SMatthew G. Knepley   Not collective
7915b5e7992SMatthew G. Knepley 
792c58f1c22SToby Isaac   Input Parameters:
793c58f1c22SToby Isaac + label - the DMLabel
794c58f1c22SToby Isaac - value - the value
795c58f1c22SToby Isaac 
796c58f1c22SToby Isaac   Output Parameter:
797c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
798c58f1c22SToby Isaac 
799c58f1c22SToby Isaac   Level: developer
800c58f1c22SToby Isaac 
801db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
802c58f1c22SToby Isaac @*/
8039371c9d4SSatish Balay PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains) {
804c58f1c22SToby Isaac   PetscInt v;
805c58f1c22SToby Isaac 
806c58f1c22SToby Isaac   PetscFunctionBegin;
807d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
808534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8099566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8100c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
811c58f1c22SToby Isaac   PetscFunctionReturn(0);
812c58f1c22SToby Isaac }
813c58f1c22SToby Isaac 
814c58f1c22SToby Isaac /*@
815c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
816c58f1c22SToby Isaac 
8175b5e7992SMatthew G. Knepley   Not collective
8185b5e7992SMatthew G. Knepley 
819c58f1c22SToby Isaac   Input Parameters:
820c58f1c22SToby Isaac + label - the DMLabel
821c58f1c22SToby Isaac - point - the point
822c58f1c22SToby Isaac 
823c58f1c22SToby Isaac   Output Parameter:
824c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
825c58f1c22SToby Isaac 
826c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
827c58f1c22SToby Isaac 
828c58f1c22SToby Isaac   Level: developer
829c58f1c22SToby Isaac 
830db781477SPatrick Sanan .seealso: `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
831c58f1c22SToby Isaac @*/
8329371c9d4SSatish Balay PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains) {
833c58f1c22SToby Isaac   PetscFunctionBeginHot;
834d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
835534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8369566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
83776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
83828b400f6SJacob Faibussowitsch     PetscCheck(label->bt, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
83963a3b9bcSJacob 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);
84076bd3646SJed Brown   }
841c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
842c58f1c22SToby Isaac   PetscFunctionReturn(0);
843c58f1c22SToby Isaac }
844c58f1c22SToby Isaac 
845c58f1c22SToby Isaac /*@
846c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
847c58f1c22SToby Isaac 
8485b5e7992SMatthew G. Knepley   Not collective
8495b5e7992SMatthew G. Knepley 
850c58f1c22SToby Isaac   Input Parameters:
851c58f1c22SToby Isaac + label - the DMLabel
852c58f1c22SToby Isaac . value - the stratum value
853c58f1c22SToby Isaac - point - the point
854c58f1c22SToby Isaac 
855c58f1c22SToby Isaac   Output Parameter:
856c58f1c22SToby Isaac . contains - true if the stratum contains the point
857c58f1c22SToby Isaac 
858c58f1c22SToby Isaac   Level: intermediate
859c58f1c22SToby Isaac 
860db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
861c58f1c22SToby Isaac @*/
8629371c9d4SSatish Balay PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains) {
8630c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
864d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
865534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
866cffad2c9SToby Isaac   if (value == label->defaultValue) {
867cffad2c9SToby Isaac     PetscInt pointVal;
8680c3c4a36SLisandro Dalcin 
869cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
870cffad2c9SToby Isaac     *contains = (PetscBool)(pointVal == value);
871cffad2c9SToby Isaac   } else {
872cffad2c9SToby Isaac     PetscInt v;
873cffad2c9SToby Isaac 
874cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
875cffad2c9SToby Isaac     if (v >= 0) {
876ad8374ffSToby Isaac       if (label->validIS[v]) {
877c58f1c22SToby Isaac         PetscInt i;
878c58f1c22SToby Isaac 
8799566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[v], point, &i));
880cffad2c9SToby Isaac         *contains = (PetscBool)(i >= 0);
881c58f1c22SToby Isaac       } else {
882cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
883cffad2c9SToby Isaac       }
884cffad2c9SToby Isaac     } else { // value is not present
885cffad2c9SToby Isaac       *contains = PETSC_FALSE;
886cffad2c9SToby Isaac     }
887c58f1c22SToby Isaac   }
888c58f1c22SToby Isaac   PetscFunctionReturn(0);
889c58f1c22SToby Isaac }
890c58f1c22SToby Isaac 
89184f0b6dfSMatthew G. Knepley /*@
8925aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8935aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8945aa44df4SToby Isaac 
8955b5e7992SMatthew G. Knepley   Not collective
8965b5e7992SMatthew G. Knepley 
8975aa44df4SToby Isaac   Input parameter:
8985aa44df4SToby Isaac . label - a DMLabel object
8995aa44df4SToby Isaac 
9005aa44df4SToby Isaac   Output parameter:
9015aa44df4SToby Isaac . defaultValue - the default value
9025aa44df4SToby Isaac 
9035aa44df4SToby Isaac   Level: beginner
9045aa44df4SToby Isaac 
905db781477SPatrick Sanan .seealso: `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
90684f0b6dfSMatthew G. Knepley @*/
9079371c9d4SSatish Balay PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue) {
9085aa44df4SToby Isaac   PetscFunctionBegin;
909d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9105aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9115aa44df4SToby Isaac   PetscFunctionReturn(0);
9125aa44df4SToby Isaac }
9135aa44df4SToby Isaac 
91484f0b6dfSMatthew G. Knepley /*@
9155aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9165aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9175aa44df4SToby Isaac 
9185b5e7992SMatthew G. Knepley   Not collective
9195b5e7992SMatthew G. Knepley 
9205aa44df4SToby Isaac   Input parameter:
9215aa44df4SToby Isaac . label - a DMLabel object
9225aa44df4SToby Isaac 
9235aa44df4SToby Isaac   Output parameter:
9245aa44df4SToby Isaac . defaultValue - the default value
9255aa44df4SToby Isaac 
9265aa44df4SToby Isaac   Level: beginner
9275aa44df4SToby Isaac 
928db781477SPatrick Sanan .seealso: `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
92984f0b6dfSMatthew G. Knepley @*/
9309371c9d4SSatish Balay PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue) {
9315aa44df4SToby Isaac   PetscFunctionBegin;
932d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9335aa44df4SToby Isaac   label->defaultValue = defaultValue;
9345aa44df4SToby Isaac   PetscFunctionReturn(0);
9355aa44df4SToby Isaac }
9365aa44df4SToby Isaac 
937c58f1c22SToby Isaac /*@
9385aa44df4SToby 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())
939c58f1c22SToby Isaac 
9405b5e7992SMatthew G. Knepley   Not collective
9415b5e7992SMatthew G. Knepley 
942c58f1c22SToby Isaac   Input Parameters:
943c58f1c22SToby Isaac + label - the DMLabel
944c58f1c22SToby Isaac - point - the point
945c58f1c22SToby Isaac 
946c58f1c22SToby Isaac   Output Parameter:
9478e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
948c58f1c22SToby Isaac 
949cffad2c9SToby 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.
950cffad2c9SToby Isaac 
951c58f1c22SToby Isaac   Level: intermediate
952c58f1c22SToby Isaac 
953db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
954c58f1c22SToby Isaac @*/
9559371c9d4SSatish Balay PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value) {
956c58f1c22SToby Isaac   PetscInt v;
957c58f1c22SToby Isaac 
9580c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
959d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
960dadcf809SJacob Faibussowitsch   PetscValidIntPointer(value, 3);
9615aa44df4SToby Isaac   *value = label->defaultValue;
962c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
963ad8374ffSToby Isaac     if (label->validIS[v]) {
964c58f1c22SToby Isaac       PetscInt i;
965c58f1c22SToby Isaac 
9669566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
967c58f1c22SToby Isaac       if (i >= 0) {
968c58f1c22SToby Isaac         *value = label->stratumValues[v];
969c58f1c22SToby Isaac         break;
970c58f1c22SToby Isaac       }
971c58f1c22SToby Isaac     } else {
972c58f1c22SToby Isaac       PetscBool has;
973c58f1c22SToby Isaac 
9749566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
975c58f1c22SToby Isaac       if (has) {
976c58f1c22SToby Isaac         *value = label->stratumValues[v];
977c58f1c22SToby Isaac         break;
978c58f1c22SToby Isaac       }
979c58f1c22SToby Isaac     }
980c58f1c22SToby Isaac   }
981c58f1c22SToby Isaac   PetscFunctionReturn(0);
982c58f1c22SToby Isaac }
983c58f1c22SToby Isaac 
984c58f1c22SToby Isaac /*@
985367003a6SStefano 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.
986c58f1c22SToby Isaac 
9875b5e7992SMatthew G. Knepley   Not collective
9885b5e7992SMatthew G. Knepley 
989c58f1c22SToby Isaac   Input Parameters:
990c58f1c22SToby Isaac + label - the DMLabel
991c58f1c22SToby Isaac . point - the point
992c58f1c22SToby Isaac - value - The point value
993c58f1c22SToby Isaac 
994c58f1c22SToby Isaac   Level: intermediate
995c58f1c22SToby Isaac 
996db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
997c58f1c22SToby Isaac @*/
9989371c9d4SSatish Balay PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value) {
999c58f1c22SToby Isaac   PetscInt v;
1000c58f1c22SToby Isaac 
1001c58f1c22SToby Isaac   PetscFunctionBegin;
1002d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10030c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10045aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
10059566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1006c58f1c22SToby Isaac   /* Set key */
10079566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10089566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
1009c58f1c22SToby Isaac   PetscFunctionReturn(0);
1010c58f1c22SToby Isaac }
1011c58f1c22SToby Isaac 
1012c58f1c22SToby Isaac /*@
1013c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1014c58f1c22SToby Isaac 
10155b5e7992SMatthew G. Knepley   Not collective
10165b5e7992SMatthew G. Knepley 
1017c58f1c22SToby Isaac   Input Parameters:
1018c58f1c22SToby Isaac + label - the DMLabel
1019c58f1c22SToby Isaac . point - the point
1020c58f1c22SToby Isaac - value - The point value
1021c58f1c22SToby Isaac 
1022c58f1c22SToby Isaac   Level: intermediate
1023c58f1c22SToby Isaac 
1024db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1025c58f1c22SToby Isaac @*/
10269371c9d4SSatish Balay PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value) {
1027ad8374ffSToby Isaac   PetscInt v;
1028c58f1c22SToby Isaac 
1029c58f1c22SToby Isaac   PetscFunctionBegin;
1030d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1031c58f1c22SToby Isaac   /* Find label value */
10329566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
10330c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
10340c3c4a36SLisandro Dalcin 
1035eeed21e7SToby Isaac   if (label->bt) {
103663a3b9bcSJacob 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);
10379566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1038eeed21e7SToby Isaac   }
10390c3c4a36SLisandro Dalcin 
10400c3c4a36SLisandro Dalcin   /* Delete key */
10419566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10429566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
1043c58f1c22SToby Isaac   PetscFunctionReturn(0);
1044c58f1c22SToby Isaac }
1045c58f1c22SToby Isaac 
1046c58f1c22SToby Isaac /*@
1047c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
1048c58f1c22SToby Isaac 
10495b5e7992SMatthew G. Knepley   Not collective
10505b5e7992SMatthew G. Knepley 
1051c58f1c22SToby Isaac   Input Parameters:
1052c58f1c22SToby Isaac + label - the DMLabel
1053c58f1c22SToby Isaac . is    - the point IS
1054c58f1c22SToby Isaac - value - The point value
1055c58f1c22SToby Isaac 
1056c58f1c22SToby Isaac   Level: intermediate
1057c58f1c22SToby Isaac 
1058db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1059c58f1c22SToby Isaac @*/
10609371c9d4SSatish Balay PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value) {
10610c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1062c58f1c22SToby Isaac   const PetscInt *points;
1063c58f1c22SToby Isaac 
1064c58f1c22SToby Isaac   PetscFunctionBegin;
1065d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1066c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
10670c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10680c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
10699566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
10700c3c4a36SLisandro Dalcin   /* Set keys */
10719566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10729566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
10739566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
10749566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
10759566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
1076c58f1c22SToby Isaac   PetscFunctionReturn(0);
1077c58f1c22SToby Isaac }
1078c58f1c22SToby Isaac 
107984f0b6dfSMatthew G. Knepley /*@
108084f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
108184f0b6dfSMatthew G. Knepley 
10825b5e7992SMatthew G. Knepley   Not collective
10835b5e7992SMatthew G. Knepley 
108484f0b6dfSMatthew G. Knepley   Input Parameter:
108584f0b6dfSMatthew G. Knepley . label - the DMLabel
108684f0b6dfSMatthew G. Knepley 
108701d2d390SJose E. Roman   Output Parameter:
108884f0b6dfSMatthew G. Knepley . numValues - the number of values
108984f0b6dfSMatthew G. Knepley 
109084f0b6dfSMatthew G. Knepley   Level: intermediate
109184f0b6dfSMatthew G. Knepley 
1092db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
109384f0b6dfSMatthew G. Knepley @*/
10949371c9d4SSatish Balay PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues) {
1095c58f1c22SToby Isaac   PetscFunctionBegin;
1096d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1097dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numValues, 2);
1098c58f1c22SToby Isaac   *numValues = label->numStrata;
1099c58f1c22SToby Isaac   PetscFunctionReturn(0);
1100c58f1c22SToby Isaac }
1101c58f1c22SToby Isaac 
110284f0b6dfSMatthew G. Knepley /*@
110384f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
110484f0b6dfSMatthew G. Knepley 
11055b5e7992SMatthew G. Knepley   Not collective
11065b5e7992SMatthew G. Knepley 
110784f0b6dfSMatthew G. Knepley   Input Parameter:
110884f0b6dfSMatthew G. Knepley . label - the DMLabel
110984f0b6dfSMatthew G. Knepley 
111001d2d390SJose E. Roman   Output Parameter:
111184f0b6dfSMatthew G. Knepley . is    - the value IS
111284f0b6dfSMatthew G. Knepley 
111384f0b6dfSMatthew G. Knepley   Level: intermediate
111484f0b6dfSMatthew G. Knepley 
11151d04cbbeSVaclav Hapla   Notes:
11161d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11171d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
11181d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
11191d04cbbeSVaclav Hapla 
1120db781477SPatrick Sanan .seealso: `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
112184f0b6dfSMatthew G. Knepley @*/
11229371c9d4SSatish Balay PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values) {
1123c58f1c22SToby Isaac   PetscFunctionBegin;
1124d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1125c58f1c22SToby Isaac   PetscValidPointer(values, 2);
11269566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1127c58f1c22SToby Isaac   PetscFunctionReturn(0);
1128c58f1c22SToby Isaac }
1129c58f1c22SToby Isaac 
113084f0b6dfSMatthew G. Knepley /*@
11311d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
11321d04cbbeSVaclav Hapla 
11331d04cbbeSVaclav Hapla   Not collective
11341d04cbbeSVaclav Hapla 
11351d04cbbeSVaclav Hapla   Input Parameter:
11361d04cbbeSVaclav Hapla . label - the DMLabel
11371d04cbbeSVaclav Hapla 
11381d04cbbeSVaclav Hapla   Output Paramater:
11391d04cbbeSVaclav Hapla . is    - the value IS
11401d04cbbeSVaclav Hapla 
11411d04cbbeSVaclav Hapla   Level: intermediate
11421d04cbbeSVaclav Hapla 
11431d04cbbeSVaclav Hapla   Notes:
11441d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11451d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
11461d04cbbeSVaclav Hapla 
1147db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
11481d04cbbeSVaclav Hapla @*/
11499371c9d4SSatish Balay PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values) {
11501d04cbbeSVaclav Hapla   PetscInt  i, j;
11511d04cbbeSVaclav Hapla   PetscInt *valuesArr;
11521d04cbbeSVaclav Hapla 
11531d04cbbeSVaclav Hapla   PetscFunctionBegin;
11541d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11551d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
11569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
11571d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
11581d04cbbeSVaclav Hapla     PetscInt n;
11591d04cbbeSVaclav Hapla 
11609566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
11611d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
11621d04cbbeSVaclav Hapla   }
11631d04cbbeSVaclav Hapla   if (j == label->numStrata) {
11649566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
11651d04cbbeSVaclav Hapla   } else {
11669566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
11671d04cbbeSVaclav Hapla   }
11689566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
11691d04cbbeSVaclav Hapla   PetscFunctionReturn(0);
11701d04cbbeSVaclav Hapla }
11711d04cbbeSVaclav Hapla 
11721d04cbbeSVaclav Hapla /*@
1173d123abd9SMatthew 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
1174d123abd9SMatthew G. Knepley 
1175d123abd9SMatthew G. Knepley   Not collective
1176d123abd9SMatthew G. Knepley 
1177d123abd9SMatthew G. Knepley   Input Parameters:
1178d123abd9SMatthew G. Knepley + label - the DMLabel
117997bb3fdcSJose E. Roman - value - the value
1180d123abd9SMatthew G. Knepley 
118101d2d390SJose E. Roman   Output Parameter:
1182d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1183d123abd9SMatthew G. Knepley 
1184d123abd9SMatthew G. Knepley   Level: intermediate
1185d123abd9SMatthew G. Knepley 
1186db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1187d123abd9SMatthew G. Knepley @*/
11889371c9d4SSatish Balay PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index) {
1189d123abd9SMatthew G. Knepley   PetscInt v;
1190d123abd9SMatthew G. Knepley 
1191d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1192d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1193dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 3);
1194d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
11959371c9d4SSatish Balay   for (v = 0; v < label->numStrata; ++v)
11969371c9d4SSatish Balay     if (label->stratumValues[v] == value) break;
1197d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1198d123abd9SMatthew G. Knepley   else *index = v;
1199d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1200d123abd9SMatthew G. Knepley }
1201d123abd9SMatthew G. Knepley 
1202d123abd9SMatthew G. Knepley /*@
120384f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
120484f0b6dfSMatthew G. Knepley 
12055b5e7992SMatthew G. Knepley   Not collective
12065b5e7992SMatthew G. Knepley 
120784f0b6dfSMatthew G. Knepley   Input Parameters:
120884f0b6dfSMatthew G. Knepley + label - the DMLabel
120984f0b6dfSMatthew G. Knepley - value - the stratum value
121084f0b6dfSMatthew G. Knepley 
121101d2d390SJose E. Roman   Output Parameter:
121284f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
121384f0b6dfSMatthew G. Knepley 
121484f0b6dfSMatthew G. Knepley   Level: intermediate
121584f0b6dfSMatthew G. Knepley 
1216db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
121784f0b6dfSMatthew G. Knepley @*/
12189371c9d4SSatish Balay PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists) {
1219fada774cSMatthew G. Knepley   PetscInt v;
1220fada774cSMatthew G. Knepley 
1221fada774cSMatthew G. Knepley   PetscFunctionBegin;
1222d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1223dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(exists, 3);
12249566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12250c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1226fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1227fada774cSMatthew G. Knepley }
1228fada774cSMatthew G. Knepley 
122984f0b6dfSMatthew G. Knepley /*@
123084f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
123184f0b6dfSMatthew G. Knepley 
12325b5e7992SMatthew G. Knepley   Not collective
12335b5e7992SMatthew G. Knepley 
123484f0b6dfSMatthew G. Knepley   Input Parameters:
123584f0b6dfSMatthew G. Knepley + label - the DMLabel
123684f0b6dfSMatthew G. Knepley - value - the stratum value
123784f0b6dfSMatthew G. Knepley 
123801d2d390SJose E. Roman   Output Parameter:
123984f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
124084f0b6dfSMatthew G. Knepley 
124184f0b6dfSMatthew G. Knepley   Level: intermediate
124284f0b6dfSMatthew G. Knepley 
1243db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
124484f0b6dfSMatthew G. Knepley @*/
12459371c9d4SSatish Balay PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size) {
1246c58f1c22SToby Isaac   PetscInt v;
1247c58f1c22SToby Isaac 
1248c58f1c22SToby Isaac   PetscFunctionBegin;
1249d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1250dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
12519566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12529566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
1253c58f1c22SToby Isaac   PetscFunctionReturn(0);
1254c58f1c22SToby Isaac }
1255c58f1c22SToby Isaac 
125684f0b6dfSMatthew G. Knepley /*@
125784f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
125884f0b6dfSMatthew G. Knepley 
12595b5e7992SMatthew G. Knepley   Not collective
12605b5e7992SMatthew G. Knepley 
126184f0b6dfSMatthew G. Knepley   Input Parameters:
126284f0b6dfSMatthew G. Knepley + label - the DMLabel
126384f0b6dfSMatthew G. Knepley - value - the stratum value
126484f0b6dfSMatthew G. Knepley 
126501d2d390SJose E. Roman   Output Parameters:
126684f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
126784f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
126884f0b6dfSMatthew G. Knepley 
126984f0b6dfSMatthew G. Knepley   Level: intermediate
127084f0b6dfSMatthew G. Knepley 
1271db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
127284f0b6dfSMatthew G. Knepley @*/
12739371c9d4SSatish Balay PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end) {
12740c3c4a36SLisandro Dalcin   PetscInt v, min, max;
1275c58f1c22SToby Isaac 
1276c58f1c22SToby Isaac   PetscFunctionBegin;
1277d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12789371c9d4SSatish Balay   if (start) {
12799371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
12809371c9d4SSatish Balay     *start = -1;
12819371c9d4SSatish Balay   }
12829371c9d4SSatish Balay   if (end) {
12839371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
12849371c9d4SSatish Balay     *end = -1;
12859371c9d4SSatish Balay   }
12869566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12870c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
12889566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
12890c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
12909566063dSJacob Faibussowitsch   PetscCall(ISGetMinMax(label->points[v], &min, &max));
1291d6cb179aSToby Isaac   if (start) *start = min;
1292d6cb179aSToby Isaac   if (end) *end = max + 1;
1293c58f1c22SToby Isaac   PetscFunctionReturn(0);
1294c58f1c22SToby Isaac }
1295c58f1c22SToby Isaac 
129684f0b6dfSMatthew G. Knepley /*@
129784f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
129884f0b6dfSMatthew G. Knepley 
12995b5e7992SMatthew G. Knepley   Not collective
13005b5e7992SMatthew G. Knepley 
130184f0b6dfSMatthew G. Knepley   Input Parameters:
130284f0b6dfSMatthew G. Knepley + label - the DMLabel
130384f0b6dfSMatthew G. Knepley - value - the stratum value
130484f0b6dfSMatthew G. Knepley 
130501d2d390SJose E. Roman   Output Parameter:
130684f0b6dfSMatthew G. Knepley . points - The stratum points
130784f0b6dfSMatthew G. Knepley 
130884f0b6dfSMatthew G. Knepley   Level: intermediate
130984f0b6dfSMatthew G. Knepley 
1310593ce467SVaclav Hapla   Notes:
1311593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1312593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1313593ce467SVaclav Hapla 
1314db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
131584f0b6dfSMatthew G. Knepley @*/
13169371c9d4SSatish Balay PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points) {
1317c58f1c22SToby Isaac   PetscInt v;
1318c58f1c22SToby Isaac 
1319c58f1c22SToby Isaac   PetscFunctionBegin;
1320d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1321c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1322c58f1c22SToby Isaac   *points = NULL;
13239566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13240c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13259566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13269566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label->points[v]));
1327ad8374ffSToby Isaac   *points = label->points[v];
1328c58f1c22SToby Isaac   PetscFunctionReturn(0);
1329c58f1c22SToby Isaac }
1330c58f1c22SToby Isaac 
133184f0b6dfSMatthew G. Knepley /*@
133284f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
133384f0b6dfSMatthew G. Knepley 
13345b5e7992SMatthew G. Knepley   Not collective
13355b5e7992SMatthew G. Knepley 
133684f0b6dfSMatthew G. Knepley   Input Parameters:
133784f0b6dfSMatthew G. Knepley + label - the DMLabel
133884f0b6dfSMatthew G. Knepley . value - the stratum value
133984f0b6dfSMatthew G. Knepley - points - The stratum points
134084f0b6dfSMatthew G. Knepley 
134184f0b6dfSMatthew G. Knepley   Level: intermediate
134284f0b6dfSMatthew G. Knepley 
1343db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
134484f0b6dfSMatthew G. Knepley @*/
13459371c9d4SSatish Balay PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is) {
13460c3c4a36SLisandro Dalcin   PetscInt v;
13474de306b1SToby Isaac 
13484de306b1SToby Isaac   PetscFunctionBegin;
1349d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1350d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
13519566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
13524de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
13539566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
13549566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
13559566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
13569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&(label->points[v])));
13570c3c4a36SLisandro Dalcin   label->points[v]  = is;
13580c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
13599566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)label));
13604de306b1SToby Isaac   if (label->bt) {
13614de306b1SToby Isaac     const PetscInt *points;
13624de306b1SToby Isaac     PetscInt        p;
13634de306b1SToby Isaac 
13649566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &points));
13654de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
13664de306b1SToby Isaac       const PetscInt point = points[p];
13674de306b1SToby Isaac 
136863a3b9bcSJacob 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);
13699566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
13704de306b1SToby Isaac     }
13714de306b1SToby Isaac   }
13724de306b1SToby Isaac   PetscFunctionReturn(0);
13734de306b1SToby Isaac }
13744de306b1SToby Isaac 
137584f0b6dfSMatthew G. Knepley /*@
137684f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
13774de306b1SToby Isaac 
13785b5e7992SMatthew G. Knepley   Not collective
13795b5e7992SMatthew G. Knepley 
138084f0b6dfSMatthew G. Knepley   Input Parameters:
138184f0b6dfSMatthew G. Knepley + label - the DMLabel
138284f0b6dfSMatthew G. Knepley - value - the stratum value
138384f0b6dfSMatthew G. Knepley 
138484f0b6dfSMatthew G. Knepley   Level: intermediate
138584f0b6dfSMatthew G. Knepley 
1386db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
138784f0b6dfSMatthew G. Knepley @*/
13889371c9d4SSatish Balay PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value) {
1389c58f1c22SToby Isaac   PetscInt v;
1390c58f1c22SToby Isaac 
1391c58f1c22SToby Isaac   PetscFunctionBegin;
1392d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13939566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13940c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13954de306b1SToby Isaac   if (label->validIS[v]) {
13964de306b1SToby Isaac     if (label->bt) {
1397c58f1c22SToby Isaac       PetscInt        i;
1398ad8374ffSToby Isaac       const PetscInt *points;
1399c58f1c22SToby Isaac 
14009566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1401c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1402ad8374ffSToby Isaac         const PetscInt point = points[i];
1403c58f1c22SToby Isaac 
140463a3b9bcSJacob 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);
14059566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1406c58f1c22SToby Isaac       }
14079566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1408c58f1c22SToby Isaac     }
1409c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
14109566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
14119566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
14129566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)label->points[v], "indices"));
14139566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject)label));
1414c58f1c22SToby Isaac   } else {
14159566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1416c58f1c22SToby Isaac   }
1417c58f1c22SToby Isaac   PetscFunctionReturn(0);
1418c58f1c22SToby Isaac }
1419c58f1c22SToby Isaac 
142084f0b6dfSMatthew G. Knepley /*@
1421412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1422412e9a14SMatthew G. Knepley 
1423412e9a14SMatthew G. Knepley   Not collective
1424412e9a14SMatthew G. Knepley 
1425412e9a14SMatthew G. Knepley   Input Parameters:
1426412e9a14SMatthew G. Knepley + label  - The DMLabel
1427412e9a14SMatthew G. Knepley . value  - The label value for all points
1428412e9a14SMatthew G. Knepley . pStart - The first point
1429412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1430412e9a14SMatthew G. Knepley 
1431412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1432412e9a14SMatthew G. Knepley 
1433412e9a14SMatthew G. Knepley   Level: intermediate
1434412e9a14SMatthew G. Knepley 
1435db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1436412e9a14SMatthew G. Knepley @*/
14379371c9d4SSatish Balay PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd) {
1438412e9a14SMatthew G. Knepley   IS pIS;
1439412e9a14SMatthew G. Knepley 
1440412e9a14SMatthew G. Knepley   PetscFunctionBegin;
14419566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
14429566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
14439566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
1444412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1445412e9a14SMatthew G. Knepley }
1446412e9a14SMatthew G. Knepley 
1447412e9a14SMatthew G. Knepley /*@
1448d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1449d123abd9SMatthew G. Knepley 
1450d123abd9SMatthew G. Knepley   Not collective
1451d123abd9SMatthew G. Knepley 
1452d123abd9SMatthew G. Knepley   Input Parameters:
1453d123abd9SMatthew G. Knepley + label  - The DMLabel
1454d123abd9SMatthew G. Knepley . value  - The label value
1455d123abd9SMatthew G. Knepley - p      - A point with this value
1456d123abd9SMatthew G. Knepley 
1457d123abd9SMatthew G. Knepley   Output Parameter:
1458d123abd9SMatthew 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
1459d123abd9SMatthew G. Knepley 
1460d123abd9SMatthew G. Knepley   Level: intermediate
1461d123abd9SMatthew G. Knepley 
1462db781477SPatrick Sanan .seealso: `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1463d123abd9SMatthew G. Knepley @*/
14649371c9d4SSatish Balay PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index) {
1465d123abd9SMatthew G. Knepley   const PetscInt *indices;
1466d123abd9SMatthew G. Knepley   PetscInt        v;
1467d123abd9SMatthew G. Knepley 
1468d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1469d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1470dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 4);
1471d123abd9SMatthew G. Knepley   *index = -1;
14729566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1473d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
14749566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
14759566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(label->points[v], &indices));
14769566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
14779566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(label->points[v], &indices));
1478d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1479d123abd9SMatthew G. Knepley }
1480d123abd9SMatthew G. Knepley 
1481d123abd9SMatthew G. Knepley /*@
148284f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
148384f0b6dfSMatthew G. Knepley 
14845b5e7992SMatthew G. Knepley   Not collective
14855b5e7992SMatthew G. Knepley 
148684f0b6dfSMatthew G. Knepley   Input Parameters:
148784f0b6dfSMatthew G. Knepley + label - the DMLabel
148822cd2cdaSVaclav Hapla . start - the first point kept
148922cd2cdaSVaclav Hapla - end - one more than the last point kept
149084f0b6dfSMatthew G. Knepley 
149184f0b6dfSMatthew G. Knepley   Level: intermediate
149284f0b6dfSMatthew G. Knepley 
1493db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
149484f0b6dfSMatthew G. Knepley @*/
14959371c9d4SSatish Balay PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end) {
1496c58f1c22SToby Isaac   PetscInt v;
1497c58f1c22SToby Isaac 
1498c58f1c22SToby Isaac   PetscFunctionBegin;
1499d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15009566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
15019566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
150248a46eb9SPierre Jolivet   for (v = 0; v < label->numStrata; ++v) PetscCall(ISGeneralFilter(label->points[v], start, end));
15039566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
1504c58f1c22SToby Isaac   PetscFunctionReturn(0);
1505c58f1c22SToby Isaac }
1506c58f1c22SToby Isaac 
150784f0b6dfSMatthew G. Knepley /*@
150884f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
150984f0b6dfSMatthew G. Knepley 
15105b5e7992SMatthew G. Knepley   Not collective
15115b5e7992SMatthew G. Knepley 
151284f0b6dfSMatthew G. Knepley   Input Parameters:
151384f0b6dfSMatthew G. Knepley + label - the DMLabel
151484f0b6dfSMatthew G. Knepley - permutation - the point permutation
151584f0b6dfSMatthew G. Knepley 
151684f0b6dfSMatthew G. Knepley   Output Parameter:
151784f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
151884f0b6dfSMatthew G. Knepley 
151984f0b6dfSMatthew G. Knepley   Level: intermediate
152084f0b6dfSMatthew G. Knepley 
1521db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
152284f0b6dfSMatthew G. Knepley @*/
15239371c9d4SSatish Balay PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew) {
1524c58f1c22SToby Isaac   const PetscInt *perm;
1525c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1526c58f1c22SToby Isaac 
1527c58f1c22SToby Isaac   PetscFunctionBegin;
1528d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1529d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
15309566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
15319566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
15329566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
15339566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
15349566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1535c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1536c58f1c22SToby Isaac     const PetscInt  size = (*labelNew)->stratumSizes[v];
1537ad8374ffSToby Isaac     const PetscInt *points;
1538ad8374ffSToby Isaac     PetscInt       *pointsNew;
1539c58f1c22SToby Isaac 
15409566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v], &points));
15419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &pointsNew));
1542c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1543ad8374ffSToby Isaac       const PetscInt point = points[q];
1544c58f1c22SToby Isaac 
154563a3b9bcSJacob 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);
1546ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1547c58f1c22SToby Isaac     }
15489566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v], &points));
15499566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
15509566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1551fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
15529566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, size, pointsNew[0], 1, &((*labelNew)->points[v])));
15539566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1554fa8e8ae5SToby Isaac     } else {
15559566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, pointsNew, PETSC_OWN_POINTER, &((*labelNew)->points[v])));
1556fa8e8ae5SToby Isaac     }
15579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[v]), "indices"));
1558c58f1c22SToby Isaac   }
15599566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1560c58f1c22SToby Isaac   if (label->bt) {
15619566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
15629566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1563c58f1c22SToby Isaac   }
1564c58f1c22SToby Isaac   PetscFunctionReturn(0);
1565c58f1c22SToby Isaac }
1566c58f1c22SToby Isaac 
15679371c9d4SSatish Balay PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata) {
156826c55118SMichael Lange   MPI_Comm     comm;
1569eb30be1eSVaclav Hapla   PetscInt     s, l, nroots, nleaves, offset, size;
157026c55118SMichael Lange   PetscInt    *remoteOffsets, *rootStrata, *rootIdx;
157126c55118SMichael Lange   PetscSection rootSection;
157226c55118SMichael Lange   PetscSF      labelSF;
157326c55118SMichael Lange 
157426c55118SMichael Lange   PetscFunctionBegin;
15759566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
15769566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
157726c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
157826c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
15799566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
15809566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
15819566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
158226c55118SMichael Lange   if (label) {
158326c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1584ad8374ffSToby Isaac       const PetscInt *points;
1585ad8374ffSToby Isaac 
15869566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
158748a46eb9SPierre Jolivet       for (l = 0; l < label->stratumSizes[s]; l++) PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
15889566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
158926c55118SMichael Lange     }
159026c55118SMichael Lange   }
15919566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
159226c55118SMichael Lange   /* Create a point-wise array of stratum values */
15939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
15949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
15959566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
159626c55118SMichael Lange   if (label) {
159726c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1598ad8374ffSToby Isaac       const PetscInt *points;
1599ad8374ffSToby Isaac 
16009566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
160126c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1602ad8374ffSToby Isaac         const PetscInt p = points[l];
16039566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
160426c55118SMichael Lange         rootStrata[offset + rootIdx[p]++] = label->stratumValues[s];
160526c55118SMichael Lange       }
16069566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
160726c55118SMichael Lange     }
160826c55118SMichael Lange   }
160926c55118SMichael Lange   /* Build SF that maps label points to remote processes */
16109566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
16119566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
16129566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
16139566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
161426c55118SMichael Lange   /* Send the strata for each point over the derived SF */
16159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
16169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
16179566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
16189566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata, MPI_REPLACE));
161926c55118SMichael Lange   /* Clean up */
16209566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
16219566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
16229566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
16239566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
162426c55118SMichael Lange   PetscFunctionReturn(0);
162526c55118SMichael Lange }
162626c55118SMichael Lange 
162784f0b6dfSMatthew G. Knepley /*@
162884f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
162984f0b6dfSMatthew G. Knepley 
16305b5e7992SMatthew G. Knepley   Collective on sf
16315b5e7992SMatthew G. Knepley 
163284f0b6dfSMatthew G. Knepley   Input Parameters:
163384f0b6dfSMatthew G. Knepley + label - the DMLabel
163484f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
163584f0b6dfSMatthew G. Knepley 
163684f0b6dfSMatthew G. Knepley   Output Parameter:
163784f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
163884f0b6dfSMatthew G. Knepley 
163984f0b6dfSMatthew G. Knepley   Level: intermediate
164084f0b6dfSMatthew G. Knepley 
1641db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
164284f0b6dfSMatthew G. Knepley @*/
16439371c9d4SSatish Balay PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew) {
1644c58f1c22SToby Isaac   MPI_Comm     comm;
164526c55118SMichael Lange   PetscSection leafSection;
164626c55118SMichael Lange   PetscInt     p, pStart, pEnd, s, size, dof, offset, stratum;
164726c55118SMichael Lange   PetscInt    *leafStrata, *strataIdx;
1648ad8374ffSToby Isaac   PetscInt   **points;
1649d67d17b1SMatthew G. Knepley   const char  *lname = NULL;
1650c58f1c22SToby Isaac   char        *name;
1651c58f1c22SToby Isaac   PetscInt     nameSize;
1652e8f14785SLisandro Dalcin   PetscHSetI   stratumHash;
1653c58f1c22SToby Isaac   size_t       len = 0;
165426c55118SMichael Lange   PetscMPIInt  rank;
1655c58f1c22SToby Isaac 
1656c58f1c22SToby Isaac   PetscFunctionBegin;
1657d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1658f018e600SMatthew G. Knepley   if (label) {
1659f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16609566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1661f018e600SMatthew G. Knepley   }
16629566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
16639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1664c58f1c22SToby Isaac   /* Bcast name */
1665dd400576SPatrick Sanan   if (rank == 0) {
16669566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
16679566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1668d67d17b1SMatthew G. Knepley   }
1669c58f1c22SToby Isaac   nameSize = len;
16709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
16719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
16729566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
16739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
16749566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
16759566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
167677d236dfSMichael Lange   /* Bcast defaultValue */
1677dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
16789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
167926c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
16809566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
16815cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
16829566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
16839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
16849566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
16859566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
16869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1687ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
16889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
16895cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
16905cbdf6fcSMichael Lange   offset = 0;
16919566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
16929566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata, (*labelNew)->stratumValues));
169348a46eb9SPierre Jolivet   for (s = 0; s < (*labelNew)->numStrata; ++s) PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
16945cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1695231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
16969371c9d4SSatish Balay       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {
16979371c9d4SSatish Balay         leafStrata[p] = s;
16989371c9d4SSatish Balay         break;
16999371c9d4SSatish Balay       }
17005cbdf6fcSMichael Lange     }
17015cbdf6fcSMichael Lange   }
1702c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
17039566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->stratumSizes));
17049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1705c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
17069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1708ad540459SPierre Jolivet     for (s = 0; s < dof; s++) (*labelNew)->stratumSizes[leafStrata[offset + s]]++;
1709c58f1c22SToby Isaac   }
17109566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &(*labelNew)->ht));
17119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->points));
17129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &points));
1713c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17149566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
17159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1716c58f1c22SToby Isaac   }
1717c58f1c22SToby Isaac   /* Insert points into new strata */
17189566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
17199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1720c58f1c22SToby Isaac   for (p = pStart; p < pEnd; p++) {
17219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1723c58f1c22SToby Isaac     for (s = 0; s < dof; s++) {
1724c58f1c22SToby Isaac       stratum                               = leafStrata[offset + s];
1725ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1726c58f1c22SToby Isaac     }
1727c58f1c22SToby Isaac   }
1728ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
17299566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (*labelNew)->stratumSizes[s], &(points[s][0]), PETSC_OWN_POINTER, &((*labelNew)->points[s])));
17309566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]), "indices"));
1731ad8374ffSToby Isaac   }
17329566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
17339566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
17349566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
17359566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
17369566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
1737c58f1c22SToby Isaac   PetscFunctionReturn(0);
1738c58f1c22SToby Isaac }
1739c58f1c22SToby Isaac 
17407937d9ceSMichael Lange /*@
17417937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
17427937d9ceSMichael Lange 
17435b5e7992SMatthew G. Knepley   Collective on sf
17445b5e7992SMatthew G. Knepley 
17457937d9ceSMichael Lange   Input Parameters:
17467937d9ceSMichael Lange + label - the DMLabel
174784f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
17487937d9ceSMichael Lange 
174984f0b6dfSMatthew G. Knepley   Output Parameters:
175084f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
17517937d9ceSMichael Lange 
17527937d9ceSMichael Lange   Level: developer
17537937d9ceSMichael Lange 
17547937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
17557937d9ceSMichael Lange 
1756db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
17577937d9ceSMichael Lange @*/
17589371c9d4SSatish Balay PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew) {
17597937d9ceSMichael Lange   MPI_Comm        comm;
17607937d9ceSMichael Lange   PetscSection    rootSection;
17617937d9ceSMichael Lange   PetscSF         sfLabel;
17627937d9ceSMichael Lange   PetscSFNode    *rootPoints, *leafPoints;
17637937d9ceSMichael Lange   PetscInt        p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
17647937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
17657937d9ceSMichael Lange   PetscInt       *rootStrata;
1766d67d17b1SMatthew G. Knepley   const char     *lname;
17677937d9ceSMichael Lange   char           *name;
17687937d9ceSMichael Lange   PetscInt        nameSize;
17697937d9ceSMichael Lange   size_t          len = 0;
17709852e123SBarry Smith   PetscMPIInt     rank, size;
17717937d9ceSMichael Lange 
17727937d9ceSMichael Lange   PetscFunctionBegin;
1773d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1774d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
17779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
17787937d9ceSMichael Lange   /* Bcast name */
1779dd400576SPatrick Sanan   if (rank == 0) {
17809566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &lname));
17819566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1782d67d17b1SMatthew G. Knepley   }
17837937d9ceSMichael Lange   nameSize = len;
17849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize + 1, &name));
17869566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize + 1));
17879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize + 1, MPI_CHAR, 0, comm));
17889566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17899566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
17907937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
17917937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
17927937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
17939566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
17949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1795dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
17967937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
17978212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
17988212dd46SStefano Zampini 
17998212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
18008212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
18017937d9ceSMichael Lange   }
18029566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
18039566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
18047937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
18059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
18069566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
18079566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
18089566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &sfLabel));
18099566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
18107937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
18119566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
18127937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
18137937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
18147937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
18159566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx + d, &dof));
18169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx + d, &offset));
18179566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset + s]));
18187937d9ceSMichael Lange     }
18197937d9ceSMichael Lange     idx += rootDegree[p];
18207937d9ceSMichael Lange   }
18219566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
18229566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18239566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18249566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
18257937d9ceSMichael Lange   PetscFunctionReturn(0);
18267937d9ceSMichael Lange }
18277937d9ceSMichael Lange 
18289371c9d4SSatish Balay static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[]) {
1829d42890abSMatthew G. Knepley   const PetscInt *degree;
1830d42890abSMatthew G. Knepley   const PetscInt *points;
1831d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1832d42890abSMatthew G. Knepley 
1833d42890abSMatthew G. Knepley   PetscFunctionBegin;
1834d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1835d42890abSMatthew G. Knepley   /* Add in leaves */
1836d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1837d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1838d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1839d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1840d42890abSMatthew G. Knepley   }
1841d42890abSMatthew G. Knepley   /* Add in shared roots */
1842d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1843d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1844d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1845d42890abSMatthew G. Knepley     if (degree[r]) {
1846d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1847d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1848d42890abSMatthew G. Knepley     }
1849d42890abSMatthew G. Knepley   }
1850d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1851d42890abSMatthew G. Knepley }
1852d42890abSMatthew G. Knepley 
18539371c9d4SSatish Balay static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx) {
1854d42890abSMatthew G. Knepley   const PetscInt *degree;
1855d42890abSMatthew G. Knepley   const PetscInt *points;
1856d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1857d42890abSMatthew G. Knepley 
1858d42890abSMatthew G. Knepley   PetscFunctionBegin;
1859d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1860d42890abSMatthew G. Knepley   /* Read out leaves */
1861d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1862d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1863d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1864d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1865d42890abSMatthew G. Knepley 
1866d42890abSMatthew G. Knepley     if (cval != defVal) {
1867d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1868d42890abSMatthew G. Knepley       if (val == defVal) {
1869d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
187048a46eb9SPierre Jolivet         if (markPoint) PetscCall((*markPoint)(label, p, cval, ctx));
1871d42890abSMatthew G. Knepley       }
1872d42890abSMatthew G. Knepley     }
1873d42890abSMatthew G. Knepley   }
1874d42890abSMatthew G. Knepley   /* Read out shared roots */
1875d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1876d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1877d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1878d42890abSMatthew G. Knepley     if (degree[r]) {
1879d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
1880d42890abSMatthew G. Knepley 
1881d42890abSMatthew G. Knepley       if (cval != defVal) {
1882d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
1883d42890abSMatthew G. Knepley         if (val == defVal) {
1884d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
188548a46eb9SPierre Jolivet           if (markPoint) PetscCall((*markPoint)(label, r, cval, ctx));
1886d42890abSMatthew G. Knepley         }
1887d42890abSMatthew G. Knepley       }
1888d42890abSMatthew G. Knepley     }
1889d42890abSMatthew G. Knepley   }
1890d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1891d42890abSMatthew G. Knepley }
1892d42890abSMatthew G. Knepley 
1893d42890abSMatthew G. Knepley /*@
1894d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
1895d42890abSMatthew G. Knepley 
1896d42890abSMatthew G. Knepley   Collective on sf
1897d42890abSMatthew G. Knepley 
1898d42890abSMatthew G. Knepley   Input Parameters:
1899d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1900d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1901d42890abSMatthew G. Knepley 
1902d42890abSMatthew G. Knepley   Level: intermediate
1903d42890abSMatthew G. Knepley 
1904db781477SPatrick Sanan .seealso: `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
1905d42890abSMatthew G. Knepley @*/
19069371c9d4SSatish Balay PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf) {
1907d42890abSMatthew G. Knepley   PetscInt    Nr, r, defVal;
1908d42890abSMatthew G. Knepley   PetscMPIInt size;
1909d42890abSMatthew G. Knepley 
1910d42890abSMatthew G. Knepley   PetscFunctionBegin;
1911d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sf), &size));
1912d42890abSMatthew G. Knepley   if (size > 1) {
1913d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
1914d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
1915d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
1916d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
1917d42890abSMatthew G. Knepley   }
1918d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1919d42890abSMatthew G. Knepley }
1920d42890abSMatthew G. Knepley 
1921d42890abSMatthew G. Knepley /*@
1922d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
1923d42890abSMatthew G. Knepley 
1924d42890abSMatthew G. Knepley   Collective on sf
1925d42890abSMatthew G. Knepley 
1926d42890abSMatthew G. Knepley   Input Parameters:
1927d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1928d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1929d42890abSMatthew G. Knepley 
1930d42890abSMatthew G. Knepley   Level: intermediate
1931d42890abSMatthew G. Knepley 
1932db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
1933d42890abSMatthew G. Knepley @*/
19349371c9d4SSatish Balay PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF) {
1935d42890abSMatthew G. Knepley   PetscFunctionBegin;
1936d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
1937d42890abSMatthew G. Knepley   label->propArray = NULL;
1938d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1939d42890abSMatthew G. Knepley }
1940d42890abSMatthew G. Knepley 
1941d42890abSMatthew G. Knepley /*@C
1942d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
1943d42890abSMatthew G. Knepley 
1944d42890abSMatthew G. Knepley   Collective on sf
1945d42890abSMatthew G. Knepley 
1946d42890abSMatthew G. Knepley   Input Parameters:
1947d42890abSMatthew G. Knepley + label     - The DMLabel to propagate across processes
1948d42890abSMatthew G. Knepley . sf        - The SF describing parallel layout of the label points
1949ef1023bdSBarry Smith . markPoint - An optional callback that is called when a point is marked, or NULL
1950d42890abSMatthew G. Knepley - ctx       - An optional user context for the callback, or NULL
1951d42890abSMatthew G. Knepley 
1952d42890abSMatthew G. Knepley   Calling sequence of markPoint:
1953d42890abSMatthew G. Knepley $ markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
1954d42890abSMatthew G. Knepley 
1955d42890abSMatthew G. Knepley + label - The DMLabel
1956d42890abSMatthew G. Knepley . p     - The point being marked
1957d42890abSMatthew G. Knepley . val   - The label value for p
1958d42890abSMatthew G. Knepley - ctx   - An optional user context
1959d42890abSMatthew G. Knepley 
1960d42890abSMatthew G. Knepley   Level: intermediate
1961d42890abSMatthew G. Knepley 
1962db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
1963d42890abSMatthew G. Knepley @*/
19649371c9d4SSatish Balay PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx) {
1965c50b2d26SMatthew G. Knepley   PetscInt   *valArray = label->propArray, Nr;
1966d42890abSMatthew G. Knepley   PetscMPIInt size;
1967d42890abSMatthew G. Knepley 
1968d42890abSMatthew G. Knepley   PetscFunctionBegin;
1969d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pointSF), &size));
1970c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
1971c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
1972d42890abSMatthew G. Knepley     /* Communicate marked edges
1973d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
1974d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
1975d42890abSMatthew G. Knepley 
1976d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
1977d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
1978d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
1979d42890abSMatthew G. Knepley 
1980d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
1981d42890abSMatthew 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
1982d42890abSMatthew G. Knepley        edge to the queue.
1983d42890abSMatthew G. Knepley     */
1984d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
1985d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
1986d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
1987d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
1988d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray, MPI_REPLACE));
1989d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
1990d42890abSMatthew G. Knepley   }
1991d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1992d42890abSMatthew G. Knepley }
1993d42890abSMatthew G. Knepley 
199484f0b6dfSMatthew G. Knepley /*@
199584f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
199684f0b6dfSMatthew G. Knepley 
19975b5e7992SMatthew G. Knepley   Not collective
19985b5e7992SMatthew G. Knepley 
199984f0b6dfSMatthew G. Knepley   Input Parameter:
200084f0b6dfSMatthew G. Knepley . label - the DMLabel
200184f0b6dfSMatthew G. Knepley 
200284f0b6dfSMatthew G. Knepley   Output Parameters:
200384f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
200484f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
200584f0b6dfSMatthew G. Knepley 
200684f0b6dfSMatthew G. Knepley   Level: developer
200784f0b6dfSMatthew G. Knepley 
2008db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
200984f0b6dfSMatthew G. Knepley @*/
20109371c9d4SSatish Balay PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is) {
2011c58f1c22SToby Isaac   IS              vIS;
2012c58f1c22SToby Isaac   const PetscInt *values;
2013c58f1c22SToby Isaac   PetscInt       *points;
2014c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2015c58f1c22SToby Isaac 
2016c58f1c22SToby Isaac   PetscFunctionBegin;
2017d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
20189566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
20199566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
20209566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
20219371c9d4SSatish Balay   if (nV) {
20229371c9d4SSatish Balay     vS = values[0];
20239371c9d4SSatish Balay     vE = values[0] + 1;
20249371c9d4SSatish Balay   }
2025c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2026c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2027c58f1c22SToby Isaac     vE = PetscMax(vE, values[v] + 1);
2028c58f1c22SToby Isaac   }
20299566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
20309566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2031c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2032c58f1c22SToby Isaac     PetscInt n;
2033c58f1c22SToby Isaac 
20349566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
20359566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2036c58f1c22SToby Isaac   }
20379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
20389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
20399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2040c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2041c58f1c22SToby Isaac     IS              is;
2042c58f1c22SToby Isaac     const PetscInt *spoints;
2043c58f1c22SToby Isaac     PetscInt        dof, off, p;
2044c58f1c22SToby Isaac 
20459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
20469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
20479566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
20489566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2049c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off + p] = spoints[p];
20509566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
20519566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2052c58f1c22SToby Isaac   }
20539566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
20549566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
20559566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
2056c58f1c22SToby Isaac   PetscFunctionReturn(0);
2057c58f1c22SToby Isaac }
2058c58f1c22SToby Isaac 
205984f0b6dfSMatthew G. Knepley /*@
2060c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2061c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
2062c58f1c22SToby Isaac 
20635b5e7992SMatthew G. Knepley   Collective on sf
20645b5e7992SMatthew G. Knepley 
2065c58f1c22SToby Isaac   Input Parameters:
2066c58f1c22SToby Isaac + s - The PetscSection for the local field layout
2067c58f1c22SToby Isaac . sf - The SF describing parallel layout of the section points
2068c58f1c22SToby Isaac . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
2069c58f1c22SToby Isaac . label - The label specifying the points
2070c58f1c22SToby Isaac - labelValue - The label stratum specifying the points
2071c58f1c22SToby Isaac 
2072c58f1c22SToby Isaac   Output Parameter:
2073c58f1c22SToby Isaac . gsection - The PetscSection for the global field layout
2074c58f1c22SToby Isaac 
2075c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
2076c58f1c22SToby Isaac 
2077c58f1c22SToby Isaac   Level: developer
2078c58f1c22SToby Isaac 
2079db781477SPatrick Sanan .seealso: `PetscSectionCreate()`
2080c58f1c22SToby Isaac @*/
20819371c9d4SSatish Balay PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) {
2082c58f1c22SToby Isaac   PetscInt *neg = NULL, *tmpOff = NULL;
2083c58f1c22SToby Isaac   PetscInt  pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2084c58f1c22SToby Isaac 
2085c58f1c22SToby Isaac   PetscFunctionBegin;
2086d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2087d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2088d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
20899566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)s), gsection));
20909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
20919566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
20929566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2093c58f1c22SToby Isaac   if (nroots >= 0) {
209463a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd - pStart);
20959566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2096c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
20979566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2098c58f1c22SToby Isaac     } else {
2099c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2100c58f1c22SToby Isaac     }
2101c58f1c22SToby Isaac   }
2102c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2103c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2104c58f1c22SToby Isaac     PetscInt value;
2105c58f1c22SToby Isaac 
21069566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2107c58f1c22SToby Isaac     if (value != labelValue) continue;
21089566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
21099566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
21109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
21119566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2112c58f1c22SToby Isaac     if (neg) neg[p] = -(dof + 1);
2113c58f1c22SToby Isaac   }
21149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2115c58f1c22SToby Isaac   if (nroots >= 0) {
21169566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
21179566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2118c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
21199371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
21209371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasDof[p - pStart] = tmpOff[p];
21219371c9d4SSatish Balay       }
2122c58f1c22SToby Isaac     }
2123c58f1c22SToby Isaac   }
2124c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
2125c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2126c58f1c22SToby Isaac     cdof                     = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2127c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2128c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p] - cdof : 0;
2129c58f1c22SToby Isaac   }
21309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)s)));
2131c58f1c22SToby Isaac   globalOff -= off;
2132c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd - pStart; ++p) {
2133c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2134c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p] + 1);
2135c58f1c22SToby Isaac   }
2136c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2137c58f1c22SToby Isaac   if (nroots >= 0) {
21389566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
21399566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff, MPI_REPLACE));
2140c58f1c22SToby Isaac     if (nroots > pEnd - pStart) {
21419371c9d4SSatish Balay       for (p = pStart; p < pEnd; ++p) {
21429371c9d4SSatish Balay         if (tmpOff[p] < 0) (*gsection)->atlasOff[p - pStart] = tmpOff[p];
21439371c9d4SSatish Balay       }
2144c58f1c22SToby Isaac     }
2145c58f1c22SToby Isaac   }
21469566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd - pStart) PetscCall(PetscFree(tmpOff));
21479566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
2148c58f1c22SToby Isaac   PetscFunctionReturn(0);
2149c58f1c22SToby Isaac }
2150c58f1c22SToby Isaac 
21519371c9d4SSatish Balay typedef struct _n_PetscSectionSym_Label {
21525fdea053SToby Isaac   DMLabel              label;
21535fdea053SToby Isaac   PetscCopyMode       *modes;
21545fdea053SToby Isaac   PetscInt            *sizes;
21555fdea053SToby Isaac   const PetscInt    ***perms;
21565fdea053SToby Isaac   const PetscScalar ***rots;
21575fdea053SToby Isaac   PetscInt (*minMaxOrients)[2];
21585fdea053SToby Isaac   PetscInt numStrata; /* numStrata is only increasing, functions as a state */
21595fdea053SToby Isaac } PetscSectionSym_Label;
21605fdea053SToby Isaac 
21619371c9d4SSatish Balay static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym) {
21625fdea053SToby Isaac   PetscInt               i, j;
21635fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
21645fdea053SToby Isaac 
21655fdea053SToby Isaac   PetscFunctionBegin;
21665fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
21675fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
21685fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
21699566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
21709566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
21715fdea053SToby Isaac       }
21725fdea053SToby Isaac       if (sl->perms[i]) {
21735fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
21745fdea053SToby Isaac 
21759566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
21765fdea053SToby Isaac       }
21775fdea053SToby Isaac       if (sl->rots[i]) {
21785fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
21795fdea053SToby Isaac 
21809566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
21815fdea053SToby Isaac       }
21825fdea053SToby Isaac     }
21835fdea053SToby Isaac   }
21849566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes, sl->sizes, sl->perms, sl->rots, sl->minMaxOrients));
21859566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
21865fdea053SToby Isaac   sl->numStrata = 0;
21875fdea053SToby Isaac   PetscFunctionReturn(0);
21885fdea053SToby Isaac }
21895fdea053SToby Isaac 
21909371c9d4SSatish Balay static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym) {
21915fdea053SToby Isaac   PetscFunctionBegin;
21929566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
21939566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
21945fdea053SToby Isaac   PetscFunctionReturn(0);
21955fdea053SToby Isaac }
21965fdea053SToby Isaac 
21979371c9d4SSatish Balay static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer) {
21985fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
21995fdea053SToby Isaac   PetscBool              isAscii;
22005fdea053SToby Isaac   DMLabel                label = sl->label;
2201d67d17b1SMatthew G. Knepley   const char            *name;
22025fdea053SToby Isaac 
22035fdea053SToby Isaac   PetscFunctionBegin;
22049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
22055fdea053SToby Isaac   if (isAscii) {
22065fdea053SToby Isaac     PetscInt          i, j, k;
22075fdea053SToby Isaac     PetscViewerFormat format;
22085fdea053SToby Isaac 
22099566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
22105fdea053SToby Isaac     if (label) {
22119566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer, &format));
22125fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22139566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
22149566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
22159566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
22165fdea053SToby Isaac       } else {
22179566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
22189566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Label '%s'\n", name));
22195fdea053SToby Isaac       }
22205fdea053SToby Isaac     } else {
22219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
22225fdea053SToby Isaac     }
22239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
22245fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
22255fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
22265fdea053SToby Isaac 
22275fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
222863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
22295fdea053SToby Isaac       } else {
223063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
22319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
223263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
22335fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22349566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
22355fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22365fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
223763a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n", j));
22385fdea053SToby Isaac             } else {
22395fdea053SToby Isaac               PetscInt tab;
22405fdea053SToby Isaac 
224163a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n", j));
22429566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
22439566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
22445fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
22459566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Permutation:"));
22469566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
224763a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sl->perms[i][j][k]));
22489566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
22499566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
22505fdea053SToby Isaac               }
22515fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
22529566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "Rotations:  "));
22539566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, 0));
22545fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
225563a3b9bcSJacob 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])));
22565fdea053SToby Isaac #else
225763a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer, " %+g", (double)sl->rots[i][j][k]));
22585fdea053SToby Isaac #endif
22599566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
22609566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer, tab));
22615fdea053SToby Isaac               }
22629566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
22635fdea053SToby Isaac             }
22645fdea053SToby Isaac           }
22659566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
22665fdea053SToby Isaac         }
22679566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
22685fdea053SToby Isaac       }
22695fdea053SToby Isaac     }
22709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
22715fdea053SToby Isaac   }
22725fdea053SToby Isaac   PetscFunctionReturn(0);
22735fdea053SToby Isaac }
22745fdea053SToby Isaac 
22755fdea053SToby Isaac /*@
22765fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
22775fdea053SToby Isaac 
22785fdea053SToby Isaac   Logically collective on sym
22795fdea053SToby Isaac 
22805fdea053SToby Isaac   Input parameters:
22815fdea053SToby Isaac + sym - the section symmetries
22825fdea053SToby Isaac - label - the DMLabel describing the types of points
22835fdea053SToby Isaac 
22845fdea053SToby Isaac   Level: developer:
22855fdea053SToby Isaac 
2286db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
22875fdea053SToby Isaac @*/
22889371c9d4SSatish Balay PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label) {
22895fdea053SToby Isaac   PetscSectionSym_Label *sl;
22905fdea053SToby Isaac 
22915fdea053SToby Isaac   PetscFunctionBegin;
22925fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
22935fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
22949566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
22955fdea053SToby Isaac   if (label) {
22965fdea053SToby Isaac     sl->label = label;
22979566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)label));
22989566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &sl->numStrata));
22999566063dSJacob 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));
23009566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->modes, (sl->numStrata + 1) * sizeof(PetscCopyMode)));
23019566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->sizes, (sl->numStrata + 1) * sizeof(PetscInt)));
23029566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->perms, (sl->numStrata + 1) * sizeof(const PetscInt **)));
23039566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->rots, (sl->numStrata + 1) * sizeof(const PetscScalar **)));
23049566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *)sl->minMaxOrients, (sl->numStrata + 1) * sizeof(PetscInt[2])));
23055fdea053SToby Isaac   }
23065fdea053SToby Isaac   PetscFunctionReturn(0);
23075fdea053SToby Isaac }
23085fdea053SToby Isaac 
23095fdea053SToby Isaac /*@C
2310b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2311b004864fSMatthew G. Knepley 
2312b004864fSMatthew G. Knepley   Logically collective on sym
2313b004864fSMatthew G. Knepley 
2314b004864fSMatthew G. Knepley   Input Parameters:
2315b004864fSMatthew G. Knepley + sym       - the section symmetries
2316b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2317b004864fSMatthew G. Knepley 
2318b004864fSMatthew G. Knepley   Output Parameters:
2319b004864fSMatthew G. Knepley + size      - the number of dofs for points in the stratum of the label
2320b004864fSMatthew G. Knepley . minOrient - the smallest orientation for a point in this stratum
2321b004864fSMatthew G. Knepley . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2322b004864fSMatthew G. Knepley . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2323b004864fSMatthew 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
2324b004864fSMatthew G. Knepley 
2325b004864fSMatthew G. Knepley   Level: developer
2326b004864fSMatthew G. Knepley 
2327db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2328b004864fSMatthew G. Knepley @*/
23299371c9d4SSatish Balay PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots) {
2330b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2331b004864fSMatthew G. Knepley   const char            *name;
2332b004864fSMatthew G. Knepley   PetscInt               i;
2333b004864fSMatthew G. Knepley 
2334b004864fSMatthew G. Knepley   PetscFunctionBegin;
2335b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
2336b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *)sym->data;
2337b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2338b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2339b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2340b004864fSMatthew G. Knepley 
2341b004864fSMatthew G. Knepley     if (stratum == value) break;
2342b004864fSMatthew G. Knepley   }
23439566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
2344b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
23459371c9d4SSatish Balay   if (size) {
23469371c9d4SSatish Balay     PetscValidIntPointer(size, 3);
23479371c9d4SSatish Balay     *size = sl->sizes[i];
23489371c9d4SSatish Balay   }
23499371c9d4SSatish Balay   if (minOrient) {
23509371c9d4SSatish Balay     PetscValidIntPointer(minOrient, 4);
23519371c9d4SSatish Balay     *minOrient = sl->minMaxOrients[i][0];
23529371c9d4SSatish Balay   }
23539371c9d4SSatish Balay   if (maxOrient) {
23549371c9d4SSatish Balay     PetscValidIntPointer(maxOrient, 5);
23559371c9d4SSatish Balay     *maxOrient = sl->minMaxOrients[i][1];
23569371c9d4SSatish Balay   }
23579371c9d4SSatish Balay   if (perms) {
23589371c9d4SSatish Balay     PetscValidPointer(perms, 6);
23599371c9d4SSatish Balay     *perms = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;
23609371c9d4SSatish Balay   }
23619371c9d4SSatish Balay   if (rots) {
23629371c9d4SSatish Balay     PetscValidPointer(rots, 7);
23639371c9d4SSatish Balay     *rots = sl->rots[i] ? &sl->rots[i][sl->minMaxOrients[i][0]] : NULL;
23649371c9d4SSatish Balay   }
2365b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2366b004864fSMatthew G. Knepley }
2367b004864fSMatthew G. Knepley 
2368b004864fSMatthew G. Knepley /*@C
23695fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
23705fdea053SToby Isaac 
23715b5e7992SMatthew G. Knepley   Logically collective on sym
23725fdea053SToby Isaac 
23735fdea053SToby Isaac   InputParameters:
23745b5e7992SMatthew G. Knepley + sym       - the section symmetries
23755fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
23765fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
23775fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
23785fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
23795fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
23805fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2381a2b725a8SWilliam 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
23825fdea053SToby Isaac 
23835fdea053SToby Isaac   Level: developer
23845fdea053SToby Isaac 
2385db781477SPatrick Sanan .seealso: `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
23865fdea053SToby Isaac @*/
23879371c9d4SSatish Balay PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots) {
23885fdea053SToby Isaac   PetscSectionSym_Label *sl;
2389d67d17b1SMatthew G. Knepley   const char            *name;
2390d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
23915fdea053SToby Isaac 
23925fdea053SToby Isaac   PetscFunctionBegin;
23935fdea053SToby Isaac   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID, 1);
23945fdea053SToby Isaac   sl = (PetscSectionSym_Label *)sym->data;
2395b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
23965fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
23975fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
23985fdea053SToby Isaac 
23995fdea053SToby Isaac     if (stratum == value) break;
24005fdea053SToby Isaac   }
24019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)sl->label, &name));
240263a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject)sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
24035fdea053SToby Isaac   sl->sizes[i]            = size;
24045fdea053SToby Isaac   sl->modes[i]            = mode;
24055fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
24065fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
24075fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
24085fdea053SToby Isaac     if (perms) {
24095fdea053SToby Isaac       PetscInt **ownPerms;
24105fdea053SToby Isaac 
24119566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownPerms));
24125fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
24135fdea053SToby Isaac         if (perms[j]) {
24149566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownPerms[j]));
2415ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownPerms[j][k] = perms[j][k];
24165fdea053SToby Isaac         }
24175fdea053SToby Isaac       }
24185fdea053SToby Isaac       sl->perms[i] = (const PetscInt **)&ownPerms[-minOrient];
24195fdea053SToby Isaac     }
24205fdea053SToby Isaac     if (rots) {
24215fdea053SToby Isaac       PetscScalar **ownRots;
24225fdea053SToby Isaac 
24239566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient, &ownRots));
24245fdea053SToby Isaac       for (j = 0; j < maxOrient - minOrient; j++) {
24255fdea053SToby Isaac         if (rots[j]) {
24269566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &ownRots[j]));
2427ad540459SPierre Jolivet           for (k = 0; k < size; k++) ownRots[j][k] = rots[j][k];
24285fdea053SToby Isaac         }
24295fdea053SToby Isaac       }
24305fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **)&ownRots[-minOrient];
24315fdea053SToby Isaac     }
24325fdea053SToby Isaac   } else {
24335fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
24345fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
24355fdea053SToby Isaac   }
24365fdea053SToby Isaac   PetscFunctionReturn(0);
24375fdea053SToby Isaac }
24385fdea053SToby Isaac 
24399371c9d4SSatish Balay static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots) {
24405fdea053SToby Isaac   PetscInt               i, j, numStrata;
24415fdea053SToby Isaac   PetscSectionSym_Label *sl;
24425fdea053SToby Isaac   DMLabel                label;
24435fdea053SToby Isaac 
24445fdea053SToby Isaac   PetscFunctionBegin;
24455fdea053SToby Isaac   sl        = (PetscSectionSym_Label *)sym->data;
24465fdea053SToby Isaac   numStrata = sl->numStrata;
24475fdea053SToby Isaac   label     = sl->label;
24485fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
24495fdea053SToby Isaac     PetscInt point = points[2 * i];
24505fdea053SToby Isaac     PetscInt ornt  = points[2 * i + 1];
24515fdea053SToby Isaac 
24525fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
24535fdea053SToby Isaac       if (label->validIS[j]) {
24545fdea053SToby Isaac         PetscInt k;
24555fdea053SToby Isaac 
24569566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j], point, &k));
24575fdea053SToby Isaac         if (k >= 0) break;
24585fdea053SToby Isaac       } else {
24595fdea053SToby Isaac         PetscBool has;
24605fdea053SToby Isaac 
24619566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
24625fdea053SToby Isaac         if (has) break;
24635fdea053SToby Isaac       }
24645fdea053SToby Isaac     }
24659371c9d4SSatish Balay     PetscCheck(!(sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) || !(ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1]), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "point %" PetscInt_FMT " orientation %" PetscInt_FMT " not in range [%" PetscInt_FMT ", %" PetscInt_FMT ") for stratum %" PetscInt_FMT, point, ornt, sl->minMaxOrients[j][0], sl->minMaxOrients[j][1],
24669371c9d4SSatish Balay                j < numStrata ? label->stratumValues[j] : label->defaultValue);
2467ad540459SPierre Jolivet     if (perms) perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;
2468ad540459SPierre Jolivet     if (rots) rots[i] = sl->rots[j] ? sl->rots[j][ornt] : NULL;
24695fdea053SToby Isaac   }
24705fdea053SToby Isaac   PetscFunctionReturn(0);
24715fdea053SToby Isaac }
24725fdea053SToby Isaac 
24739371c9d4SSatish Balay static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym) {
2474b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)nsym->data;
2475b004864fSMatthew G. Knepley   IS                     valIS;
2476b004864fSMatthew G. Knepley   const PetscInt        *values;
2477b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2478b004864fSMatthew G. Knepley 
2479b004864fSMatthew G. Knepley   PetscFunctionBegin;
24809566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
24819566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
24829566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2483b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2484b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2485b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2486b004864fSMatthew G. Knepley     const PetscInt    **perms;
2487b004864fSMatthew G. Knepley     const PetscScalar **rots;
2488b004864fSMatthew G. Knepley 
24899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym, val, &size, &minOrient, &maxOrient, &perms, &rots));
24909566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val, size, minOrient, maxOrient, PETSC_COPY_VALUES, perms, rots));
2491b004864fSMatthew G. Knepley   }
24929566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
2493b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2494b004864fSMatthew G. Knepley }
2495b004864fSMatthew G. Knepley 
24969371c9d4SSatish Balay static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym) {
2497b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *)sym->data;
2498b004864fSMatthew G. Knepley   DMLabel                dlabel;
2499b004864fSMatthew G. Knepley 
2500b004864fSMatthew G. Knepley   PetscFunctionBegin;
25019566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
25029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)sym), dlabel, dsym));
25039566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
25049566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
2505b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2506b004864fSMatthew G. Knepley }
2507b004864fSMatthew G. Knepley 
25089371c9d4SSatish Balay PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym) {
25095fdea053SToby Isaac   PetscSectionSym_Label *sl;
25105fdea053SToby Isaac 
25115fdea053SToby Isaac   PetscFunctionBegin;
2512*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&sl));
25135fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2514b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2515b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
25165fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
25175fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
25185fdea053SToby Isaac   sym->data            = (void *)sl;
25195fdea053SToby Isaac   PetscFunctionReturn(0);
25205fdea053SToby Isaac }
25215fdea053SToby Isaac 
25225fdea053SToby Isaac /*@
25235fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
25245fdea053SToby Isaac 
25255fdea053SToby Isaac   Collective
25265fdea053SToby Isaac 
25275fdea053SToby Isaac   Input Parameters:
25285fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
25295fdea053SToby Isaac - label - the label defining the strata
25305fdea053SToby Isaac 
25315fdea053SToby Isaac   Output Parameters:
25325fdea053SToby Isaac . sym - the section symmetries
25335fdea053SToby Isaac 
25345fdea053SToby Isaac   Level: developer
25355fdea053SToby Isaac 
2536db781477SPatrick Sanan .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
25375fdea053SToby Isaac @*/
25389371c9d4SSatish Balay PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym) {
25395fdea053SToby Isaac   PetscFunctionBegin;
25409566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
25419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm, sym));
25429566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym, PETSCSECTIONSYMLABEL));
25439566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym, label));
25445fdea053SToby Isaac   PetscFunctionReturn(0);
25455fdea053SToby Isaac }
2546