xref: /petsc/src/dm/label/dmlabel.c (revision d42890abfe04bbb4579071e4bb69ebbfb114e02b)
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 
25c58f1c22SToby Isaac .seealso: DMLabelDestroy()
26c58f1c22SToby Isaac @*/
27d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
28c58f1c22SToby Isaac {
29c58f1c22SToby Isaac   PetscFunctionBegin;
30064a246eSJacob Faibussowitsch   PetscValidPointer(label,3);
319566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
32c58f1c22SToby Isaac 
339566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*label,DMLABEL_CLASSID,"DMLabel","DMLabel","DM",comm,DMLabelDestroy,DMLabelView));
34d67d17b1SMatthew G. Knepley 
35c58f1c22SToby Isaac   (*label)->numStrata      = 0;
365aa44df4SToby Isaac   (*label)->defaultValue   = -1;
37c58f1c22SToby Isaac   (*label)->stratumValues  = NULL;
38ad8374ffSToby Isaac   (*label)->validIS        = NULL;
39c58f1c22SToby Isaac   (*label)->stratumSizes   = NULL;
40c58f1c22SToby Isaac   (*label)->points         = NULL;
41c58f1c22SToby Isaac   (*label)->ht             = NULL;
42c58f1c22SToby Isaac   (*label)->pStart         = -1;
43c58f1c22SToby Isaac   (*label)->pEnd           = -1;
44c58f1c22SToby Isaac   (*label)->bt             = NULL;
459566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *label, name));
47c58f1c22SToby Isaac   PetscFunctionReturn(0);
48c58f1c22SToby Isaac }
49c58f1c22SToby Isaac 
50c58f1c22SToby Isaac /*
51c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
52c58f1c22SToby Isaac 
535b5e7992SMatthew G. Knepley   Not collective
545b5e7992SMatthew G. Knepley 
55c58f1c22SToby Isaac   Input parameter:
56c58f1c22SToby Isaac + label - The DMLabel
57c58f1c22SToby Isaac - v - The stratum value
58c58f1c22SToby Isaac 
59c58f1c22SToby Isaac   Output parameter:
60c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
61c58f1c22SToby Isaac 
62c58f1c22SToby Isaac   Level: developer
63c58f1c22SToby Isaac 
64c58f1c22SToby Isaac .seealso: DMLabelCreate()
65c58f1c22SToby Isaac */
66c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
67c58f1c22SToby Isaac {
68277ea44aSLisandro Dalcin   IS             is;
69b9907514SLisandro Dalcin   PetscInt       off = 0, *pointArray, p;
70c58f1c22SToby Isaac 
71b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
72c58f1c22SToby Isaac   PetscFunctionBegin;
732c71b3e2SJacob Faibussowitsch   PetscCheckFalse(v < 0 || v >= label->numStrata,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeValid_Private", v);
749566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
769566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
779566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
789566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
79c58f1c22SToby Isaac   if (label->bt) {
80c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
81ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
8208401ef6SPierre Jolivet       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
839566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
84c58f1c22SToby Isaac     }
85c58f1c22SToby Isaac   }
86ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v]-1] == pointArray[0] + label->stratumSizes[v]-1) {
879566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
889566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
89ba2698f1SMatthew G. Knepley   } else {
909566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
91ba2698f1SMatthew G. Knepley   }
929566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) is, "indices"));
93277ea44aSLisandro Dalcin   label->points[v]  = is;
94ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
959566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject) label));
96c58f1c22SToby Isaac   PetscFunctionReturn(0);
97c58f1c22SToby Isaac }
98c58f1c22SToby Isaac 
99c58f1c22SToby Isaac /*
100c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
101c58f1c22SToby Isaac 
1025b5e7992SMatthew G. Knepley   Not collective
1035b5e7992SMatthew G. Knepley 
104c58f1c22SToby Isaac   Input parameter:
105c58f1c22SToby Isaac . label - The DMLabel
106c58f1c22SToby Isaac 
107c58f1c22SToby Isaac   Output parameter:
108c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
109c58f1c22SToby Isaac 
110c58f1c22SToby Isaac   Level: developer
111c58f1c22SToby Isaac 
112c58f1c22SToby Isaac .seealso: DMLabelCreate()
113c58f1c22SToby Isaac */
114c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
115c58f1c22SToby Isaac {
116c58f1c22SToby Isaac   PetscInt       v;
117c58f1c22SToby Isaac 
118c58f1c22SToby Isaac   PetscFunctionBegin;
119c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; v++) {
1209566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeValid_Private(label, v));
121c58f1c22SToby Isaac   }
122c58f1c22SToby Isaac   PetscFunctionReturn(0);
123c58f1c22SToby Isaac }
124c58f1c22SToby Isaac 
125c58f1c22SToby Isaac /*
126c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
127c58f1c22SToby Isaac 
1285b5e7992SMatthew G. Knepley   Not collective
1295b5e7992SMatthew G. Knepley 
130c58f1c22SToby Isaac   Input parameter:
131c58f1c22SToby Isaac + label - The DMLabel
132c58f1c22SToby Isaac - v - The stratum value
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Output parameter:
135c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
136c58f1c22SToby Isaac 
137c58f1c22SToby Isaac   Level: developer
138c58f1c22SToby Isaac 
139c58f1c22SToby Isaac .seealso: DMLabelCreate()
140c58f1c22SToby Isaac */
141c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
142c58f1c22SToby Isaac {
143c58f1c22SToby Isaac   PetscInt       p;
144ad8374ffSToby Isaac   const PetscInt *points;
145c58f1c22SToby Isaac 
146b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
147c58f1c22SToby Isaac   PetscFunctionBegin;
1482c71b3e2SJacob Faibussowitsch   PetscCheckFalse(v < 0 || v >= label->numStrata,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeInvalid_Private", v);
149ad8374ffSToby Isaac   if (label->points[v]) {
1509566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
151e8f14785SLisandro Dalcin     for (p = 0; p < label->stratumSizes[v]; ++p) {
1529566063dSJacob Faibussowitsch       PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
153e8f14785SLisandro Dalcin     }
1549566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v],&points));
1559566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&(label->points[v])));
156ad8374ffSToby Isaac   }
157ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
158c58f1c22SToby Isaac   PetscFunctionReturn(0);
159c58f1c22SToby Isaac }
160c58f1c22SToby Isaac 
161b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
162b9907514SLisandro Dalcin #define DMLABEL_LOOKUP_THRESHOLD 16
163b9907514SLisandro Dalcin #endif
164b9907514SLisandro Dalcin 
1659fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
1660c3c4a36SLisandro Dalcin {
1670c3c4a36SLisandro Dalcin   PetscInt       v;
1680e79e033SBarry Smith 
1690c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1700e79e033SBarry Smith   *index = -1;
171b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
172b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
173b9907514SLisandro Dalcin       if (label->stratumValues[v] == value) {*index = v; break;}
174b9907514SLisandro Dalcin   } else {
1759566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGet(label->hmap, value, index));
1760e79e033SBarry Smith   }
17776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */
17890e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
1799566063dSJacob Faibussowitsch     PetscCall(PetscHMapIGetSize(label->hmap, &len));
18008401ef6SPierre Jolivet     PetscCheck(len == label->numStrata,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
18190e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
1829566063dSJacob Faibussowitsch       PetscCall(PetscHMapIGet(label->hmap, value, &loc));
18390e9b2aeSLisandro Dalcin     } else {
18490e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
18590e9b2aeSLisandro Dalcin         if (label->stratumValues[v] == value) {loc = v; break;}
18690e9b2aeSLisandro Dalcin     }
18708401ef6SPierre Jolivet     PetscCheck(loc == *index,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
18890e9b2aeSLisandro Dalcin   }
1890c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
1900c3c4a36SLisandro Dalcin }
1910c3c4a36SLisandro Dalcin 
1929fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
193c58f1c22SToby Isaac {
194b9907514SLisandro Dalcin   PetscInt       v;
195b9907514SLisandro Dalcin   PetscInt      *tmpV;
196b9907514SLisandro Dalcin   PetscInt      *tmpS;
197b9907514SLisandro Dalcin   PetscHSetI    *tmpH, ht;
198b9907514SLisandro Dalcin   IS            *tmpP, is;
199c58f1c22SToby Isaac   PetscBool     *tmpB;
200b9907514SLisandro Dalcin   PetscHMapI     hmap = label->hmap;
201c58f1c22SToby Isaac 
202c58f1c22SToby Isaac   PetscFunctionBegin;
203b9907514SLisandro Dalcin   v    = label->numStrata;
204b9907514SLisandro Dalcin   tmpV = label->stratumValues;
205b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
206b9907514SLisandro Dalcin   tmpH = label->ht;
207b9907514SLisandro Dalcin   tmpP = label->points;
208b9907514SLisandro Dalcin   tmpB = label->validIS;
2098e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2108e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2118e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2128e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2138e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2148e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v+1)*sizeof(*tmpV), &tmpV));
2169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v+1)*sizeof(*tmpS), &tmpS));
2179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v+1)*sizeof(*tmpH), &tmpH));
2189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v+1)*sizeof(*tmpP), &tmpP));
2199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((v+1)*sizeof(*tmpB), &tmpB));
2209566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpV, oldV, v));
2219566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpS, oldS, v));
2229566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpH, oldH, v));
2239566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpP, oldP, v));
2249566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(tmpB, oldB, v));
2259566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldV));
2269566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldS));
2279566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldH));
2289566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldP));
2299566063dSJacob Faibussowitsch     PetscCall(PetscFree(oldB));
2308e1f8cf0SLisandro Dalcin   }
231b9907514SLisandro Dalcin   label->numStrata     = v+1;
232c58f1c22SToby Isaac   label->stratumValues = tmpV;
233c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
234c58f1c22SToby Isaac   label->ht            = tmpH;
235c58f1c22SToby Isaac   label->points        = tmpP;
236ad8374ffSToby Isaac   label->validIS       = tmpB;
2379566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
2389566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF,0,0,1,&is));
2399566063dSJacob Faibussowitsch   PetscCall(PetscHMapISet(hmap, value, v));
240b9907514SLisandro Dalcin   tmpV[v] = value;
241b9907514SLisandro Dalcin   tmpS[v] = 0;
242b9907514SLisandro Dalcin   tmpH[v] = ht;
243b9907514SLisandro Dalcin   tmpP[v] = is;
244b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
2459566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject) label));
2460c3c4a36SLisandro Dalcin   *index = v;
2470c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2480c3c4a36SLisandro Dalcin }
2490c3c4a36SLisandro Dalcin 
2509fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
251b9907514SLisandro Dalcin {
252b9907514SLisandro Dalcin   PetscFunctionBegin;
2539566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, index));
2549566063dSJacob Faibussowitsch   if (*index < 0) PetscCall(DMLabelNewStratum(label, value, index));
255b9907514SLisandro Dalcin   PetscFunctionReturn(0);
256b9907514SLisandro Dalcin }
257b9907514SLisandro Dalcin 
2589fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
2599e63cc69SVaclav Hapla {
2609e63cc69SVaclav Hapla   PetscFunctionBegin;
2619e63cc69SVaclav Hapla   *size = 0;
2629e63cc69SVaclav Hapla   if (v < 0) PetscFunctionReturn(0);
2639e63cc69SVaclav Hapla   if (label->validIS[v]) {
2649e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
2659e63cc69SVaclav Hapla   } else {
2669566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(label->ht[v], size));
2679e63cc69SVaclav Hapla   }
2689e63cc69SVaclav Hapla   PetscFunctionReturn(0);
2699e63cc69SVaclav Hapla }
2709e63cc69SVaclav Hapla 
271b9907514SLisandro Dalcin /*@
272b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
273b9907514SLisandro Dalcin 
274d8d19677SJose E. Roman   Input Parameters:
275b9907514SLisandro Dalcin + label - The DMLabel
276b9907514SLisandro Dalcin - value - The stratum value
277b9907514SLisandro Dalcin 
278b9907514SLisandro Dalcin   Level: beginner
279b9907514SLisandro Dalcin 
280b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
281b9907514SLisandro Dalcin @*/
2820c3c4a36SLisandro Dalcin PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
2830c3c4a36SLisandro Dalcin {
2840c3c4a36SLisandro Dalcin   PetscInt       v;
2850c3c4a36SLisandro Dalcin 
2860c3c4a36SLisandro Dalcin   PetscFunctionBegin;
287d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2889566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
289b9907514SLisandro Dalcin   PetscFunctionReturn(0);
290b9907514SLisandro Dalcin }
291b9907514SLisandro Dalcin 
292b9907514SLisandro Dalcin /*@
293b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
294b9907514SLisandro Dalcin 
2955b5e7992SMatthew G. Knepley   Not collective
2965b5e7992SMatthew G. Knepley 
297d8d19677SJose E. Roman   Input Parameters:
298b9907514SLisandro Dalcin + label - The DMLabel
299b9907514SLisandro Dalcin . numStrata - The number of stratum values
300b9907514SLisandro Dalcin - stratumValues - The stratum values
301b9907514SLisandro Dalcin 
302b9907514SLisandro Dalcin   Level: beginner
303b9907514SLisandro Dalcin 
304b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
305b9907514SLisandro Dalcin @*/
306b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
307b9907514SLisandro Dalcin {
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 {
347b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3489566063dSJacob Faibussowitsch       PetscCall(DMLabelAddStratum(label, values[v]));
349b9907514SLisandro Dalcin     }
350b9907514SLisandro Dalcin   }
3519566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
352b9907514SLisandro Dalcin   PetscFunctionReturn(0);
353b9907514SLisandro Dalcin }
354b9907514SLisandro Dalcin 
355b9907514SLisandro Dalcin /*@
356b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
357b9907514SLisandro Dalcin 
3585b5e7992SMatthew G. Knepley   Not collective
3595b5e7992SMatthew G. Knepley 
360d8d19677SJose E. Roman   Input Parameters:
361b9907514SLisandro Dalcin + label - The DMLabel
362b9907514SLisandro Dalcin - valueIS - Index set with stratum values
363b9907514SLisandro Dalcin 
364b9907514SLisandro Dalcin   Level: beginner
365b9907514SLisandro Dalcin 
366b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
367b9907514SLisandro Dalcin @*/
368b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
369b9907514SLisandro Dalcin {
370b9907514SLisandro Dalcin   PetscInt       numStrata;
371b9907514SLisandro Dalcin   const PetscInt *stratumValues;
372b9907514SLisandro Dalcin 
373b9907514SLisandro Dalcin   PetscFunctionBegin;
374b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
375b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
3769566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(valueIS, &numStrata));
3779566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valueIS, &stratumValues));
3789566063dSJacob Faibussowitsch   PetscCall(DMLabelAddStrata(label, numStrata, stratumValues));
379c58f1c22SToby Isaac   PetscFunctionReturn(0);
380c58f1c22SToby Isaac }
381c58f1c22SToby Isaac 
382c58f1c22SToby Isaac static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer)
383c58f1c22SToby Isaac {
384c58f1c22SToby Isaac   PetscInt       v;
385c58f1c22SToby Isaac   PetscMPIInt    rank;
386c58f1c22SToby Isaac 
387c58f1c22SToby Isaac   PetscFunctionBegin;
3889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3899566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
390c58f1c22SToby Isaac   if (label) {
391d67d17b1SMatthew G. Knepley     const char *name;
392d67d17b1SMatthew G. Knepley 
3939566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &name));
3949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
3959566063dSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%D, %D)\n", label->pStart, label->pEnd));
396c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
397c58f1c22SToby Isaac       const PetscInt value = label->stratumValues[v];
398ad8374ffSToby Isaac       const PetscInt *points;
399c58f1c22SToby Isaac       PetscInt       p;
400c58f1c22SToby Isaac 
4019566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
402c58f1c22SToby Isaac       for (p = 0; p < label->stratumSizes[v]; ++p) {
4039566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D (%D)\n", rank, points[p], value));
404c58f1c22SToby Isaac       }
4059566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v],&points));
406c58f1c22SToby Isaac     }
407c58f1c22SToby Isaac   }
4089566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
4099566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
410c58f1c22SToby Isaac   PetscFunctionReturn(0);
411c58f1c22SToby Isaac }
412c58f1c22SToby Isaac 
413c58f1c22SToby Isaac /*@C
414c58f1c22SToby Isaac   DMLabelView - View the label
415c58f1c22SToby Isaac 
4165b5e7992SMatthew G. Knepley   Collective on viewer
4175b5e7992SMatthew G. Knepley 
418c58f1c22SToby Isaac   Input Parameters:
419c58f1c22SToby Isaac + label - The DMLabel
420c58f1c22SToby Isaac - viewer - The PetscViewer
421c58f1c22SToby Isaac 
422c58f1c22SToby Isaac   Level: intermediate
423c58f1c22SToby Isaac 
424c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelDestroy()
425c58f1c22SToby Isaac @*/
426c58f1c22SToby Isaac PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
427c58f1c22SToby Isaac {
428c58f1c22SToby Isaac   PetscBool      iascii;
429c58f1c22SToby Isaac 
430c58f1c22SToby Isaac   PetscFunctionBegin;
431d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4329566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
433c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4349566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
4359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
436c58f1c22SToby Isaac   if (iascii) {
4379566063dSJacob Faibussowitsch     PetscCall(DMLabelView_Ascii(label, viewer));
438c58f1c22SToby Isaac   }
439c58f1c22SToby Isaac   PetscFunctionReturn(0);
440c58f1c22SToby Isaac }
441c58f1c22SToby Isaac 
44284f0b6dfSMatthew G. Knepley /*@
443d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
444d67d17b1SMatthew G. Knepley 
4455b5e7992SMatthew G. Knepley   Not collective
4465b5e7992SMatthew G. Knepley 
447d67d17b1SMatthew G. Knepley   Input Parameter:
448d67d17b1SMatthew G. Knepley . label - The DMLabel
449d67d17b1SMatthew G. Knepley 
450d67d17b1SMatthew G. Knepley   Level: beginner
451d67d17b1SMatthew G. Knepley 
452d67d17b1SMatthew G. Knepley .seealso: DMLabelDestroy(), DMLabelCreate()
453d67d17b1SMatthew G. Knepley @*/
454d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelReset(DMLabel label)
455d67d17b1SMatthew G. Knepley {
456d67d17b1SMatthew G. Knepley   PetscInt       v;
457d67d17b1SMatthew G. Knepley 
458d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
459d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
460d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
4619566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&label->ht[v]));
4629566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
463d67d17b1SMatthew G. Knepley   }
464b9907514SLisandro Dalcin   label->numStrata = 0;
4659566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
4669566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
4679566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
4689566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
4699566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
470f9244615SMatthew G. Knepley   label->stratumValues = NULL;
471f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
472f9244615SMatthew G. Knepley   label->ht            = NULL;
473f9244615SMatthew G. Knepley   label->points        = NULL;
474f9244615SMatthew G. Knepley   label->validIS       = NULL;
4759566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
476b9907514SLisandro Dalcin   label->pStart = -1;
477b9907514SLisandro Dalcin   label->pEnd   = -1;
4789566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
479d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
480d67d17b1SMatthew G. Knepley }
481d67d17b1SMatthew G. Knepley 
482d67d17b1SMatthew G. Knepley /*@
48384f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
48484f0b6dfSMatthew G. Knepley 
4855b5e7992SMatthew G. Knepley   Collective on label
4865b5e7992SMatthew G. Knepley 
48784f0b6dfSMatthew G. Knepley   Input Parameter:
48884f0b6dfSMatthew G. Knepley . label - The DMLabel
48984f0b6dfSMatthew G. Knepley 
49084f0b6dfSMatthew G. Knepley   Level: beginner
49184f0b6dfSMatthew G. Knepley 
492d67d17b1SMatthew G. Knepley .seealso: DMLabelReset(), DMLabelCreate()
49384f0b6dfSMatthew G. Knepley @*/
494c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
495c58f1c22SToby Isaac {
496c58f1c22SToby Isaac   PetscFunctionBegin;
497d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
498d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1);
499b9907514SLisandro Dalcin   if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);}
5009566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
5019566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5029566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
503c58f1c22SToby Isaac   PetscFunctionReturn(0);
504c58f1c22SToby Isaac }
505c58f1c22SToby Isaac 
50684f0b6dfSMatthew G. Knepley /*@
50784f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
50884f0b6dfSMatthew G. Knepley 
5095b5e7992SMatthew G. Knepley   Collective on label
5105b5e7992SMatthew G. Knepley 
51184f0b6dfSMatthew G. Knepley   Input Parameter:
51284f0b6dfSMatthew G. Knepley . label - The DMLabel
51384f0b6dfSMatthew G. Knepley 
51484f0b6dfSMatthew G. Knepley   Output Parameter:
51584f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
51684f0b6dfSMatthew G. Knepley 
51784f0b6dfSMatthew G. Knepley   Level: intermediate
51884f0b6dfSMatthew G. Knepley 
51984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelDestroy()
52084f0b6dfSMatthew G. Knepley @*/
521c58f1c22SToby Isaac PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
522c58f1c22SToby Isaac {
523d67d17b1SMatthew G. Knepley   const char    *name;
524ad8374ffSToby Isaac   PetscInt       v;
525c58f1c22SToby Isaac 
526c58f1c22SToby Isaac   PetscFunctionBegin;
527d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5289566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5299566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) label, &name));
5309566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew));
531c58f1c22SToby Isaac 
532c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5335aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->ht));
5379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->points));
5389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
539c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
5409566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
541c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
542c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
5439566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) (label->points[v])));
544ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
545b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
546c58f1c22SToby Isaac   }
5479566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5489566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap));
549c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
550c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
551c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
552c58f1c22SToby Isaac   PetscFunctionReturn(0);
553c58f1c22SToby Isaac }
554c58f1c22SToby Isaac 
555609dae6eSVaclav Hapla /*@C
556609dae6eSVaclav Hapla   DMLabelCompare - Compare two DMLabel objects
557609dae6eSVaclav Hapla 
5585efe38ccSVaclav Hapla   Collective on comm
559609dae6eSVaclav Hapla 
560609dae6eSVaclav Hapla   Input Parameters:
561f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
562f1a722f8SMatthew G. Knepley . l0 - First DMLabel
563609dae6eSVaclav Hapla - l1 - Second DMLabel
564609dae6eSVaclav Hapla 
565609dae6eSVaclav Hapla   Output Parameters
5665efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
5675efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
568609dae6eSVaclav Hapla 
569609dae6eSVaclav Hapla   Level: intermediate
570609dae6eSVaclav Hapla 
571609dae6eSVaclav Hapla   Notes:
5725efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
5735efe38ccSVaclav Hapla   If it is passed as NULL and difference is found, an error is thrown on all processes.
5745efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
575609dae6eSVaclav Hapla 
5765efe38ccSVaclav Hapla   The output message is set independently on each rank.
5775efe38ccSVaclav Hapla   It is set to NULL if no difference was found on the current rank. It must be freed by user.
5785efe38ccSVaclav Hapla   If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
5795efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
580609dae6eSVaclav Hapla 
581609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
582609dae6eSVaclav Hapla 
5835efe38ccSVaclav Hapla   The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
5845efe38ccSVaclav Hapla 
585609dae6eSVaclav Hapla   Fortran Notes:
586609dae6eSVaclav Hapla   This function is currently not available from Fortran.
587609dae6eSVaclav Hapla 
588609dae6eSVaclav Hapla .seealso: DMCompareLabels(), DMLabelGetNumValues(), DMLabelGetDefaultValue(), DMLabelGetNonEmptyStratumValuesIS(), DMLabelGetStratumIS()
589609dae6eSVaclav Hapla @*/
5905efe38ccSVaclav Hapla PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
591609dae6eSVaclav Hapla {
592609dae6eSVaclav Hapla   const char     *name0, *name1;
593609dae6eSVaclav Hapla   char            msg[PETSC_MAX_PATH_LEN] = "";
5945efe38ccSVaclav Hapla   PetscBool       eq;
5955efe38ccSVaclav Hapla   PetscMPIInt     rank;
596609dae6eSVaclav Hapla 
597609dae6eSVaclav Hapla   PetscFunctionBegin;
5985efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
5995efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6005efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
6015efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
6029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6049566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
605609dae6eSVaclav Hapla   {
606609dae6eSVaclav Hapla     PetscInt v0, v1;
607609dae6eSVaclav Hapla 
6089566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6099566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6105efe38ccSVaclav Hapla     eq = (PetscBool) (v0 == v1);
6115efe38ccSVaclav Hapla     if (!eq) {
6129566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Default value of DMLabel l0 \"%s\" = %D != %D = Default value of DMLabel l1 \"%s\"", name0, v0, v1, name1));
613609dae6eSVaclav Hapla     }
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     IS              is0, is1;
619609dae6eSVaclav Hapla 
6209566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6219566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6229566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6239566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6249566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
6255efe38ccSVaclav Hapla     if (!eq) {
6269566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
627609dae6eSVaclav Hapla     }
6289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6295efe38ccSVaclav Hapla     if (!eq) goto finish;
630609dae6eSVaclav Hapla   }
631609dae6eSVaclav Hapla   {
632609dae6eSVaclav Hapla     PetscInt i, nValues;
633609dae6eSVaclav Hapla 
6349566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
635609dae6eSVaclav Hapla     for (i=0; i<nValues; i++) {
636609dae6eSVaclav Hapla       const PetscInt  v = l0->stratumValues[i];
637609dae6eSVaclav Hapla       PetscInt        n;
638609dae6eSVaclav Hapla       IS              is0, is1;
639609dae6eSVaclav Hapla 
6409566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
641609dae6eSVaclav Hapla       if (!n) continue;
6429566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6439566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6449566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6469566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6475efe38ccSVaclav Hapla       if (!eq) {
6489566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum #%D with value %D contains different points in DMLabel l0 \"%s\" and DMLabel l1 \"%s\"", i, v, name0, name1));
6495efe38ccSVaclav Hapla         break;
650609dae6eSVaclav Hapla       }
651609dae6eSVaclav Hapla     }
6529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
653609dae6eSVaclav Hapla   }
654609dae6eSVaclav Hapla finish:
6555efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
656609dae6eSVaclav Hapla   if (message) {
657609dae6eSVaclav Hapla     *message = NULL;
658609dae6eSVaclav Hapla     if (msg[0]) {
6599566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(msg, message));
660609dae6eSVaclav Hapla     }
6615efe38ccSVaclav Hapla   } else {
6625efe38ccSVaclav Hapla     if (msg[0]) {
6639566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
664609dae6eSVaclav Hapla     }
6659566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
6665efe38ccSVaclav Hapla   }
6675efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
6685efe38ccSVaclav Hapla   if (equal) *equal = eq;
66928b400f6SJacob Faibussowitsch   else PetscCheck(eq,comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal");
670609dae6eSVaclav Hapla   PetscFunctionReturn(0);
671609dae6eSVaclav Hapla }
672609dae6eSVaclav Hapla 
673c6a43d28SMatthew G. Knepley /*@
674c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
675c6a43d28SMatthew G. Knepley 
6765b5e7992SMatthew G. Knepley   Not collective
6775b5e7992SMatthew G. Knepley 
678c6a43d28SMatthew G. Knepley   Input Parameter:
679c6a43d28SMatthew G. Knepley . label  - The DMLabel
680c6a43d28SMatthew G. Knepley 
681c6a43d28SMatthew G. Knepley   Level: intermediate
682c6a43d28SMatthew G. Knepley 
683c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
684c6a43d28SMatthew G. Knepley @*/
685c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
686c6a43d28SMatthew G. Knepley {
687c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
688c6a43d28SMatthew G. Knepley 
689c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
690c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6919566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
692c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
693c6a43d28SMatthew G. Knepley     const PetscInt *points;
694c6a43d28SMatthew G. Knepley     PetscInt       i;
695c6a43d28SMatthew G. Knepley 
6969566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
697c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
698c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
699c6a43d28SMatthew G. Knepley 
700c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
701c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
702c6a43d28SMatthew G. Knepley     }
7039566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
704c6a43d28SMatthew G. Knepley   }
705c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
706c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7079566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
708c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
709c6a43d28SMatthew G. Knepley }
710c6a43d28SMatthew G. Knepley 
711c6a43d28SMatthew G. Knepley /*@
712c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
713c6a43d28SMatthew G. Knepley 
7145b5e7992SMatthew G. Knepley   Not collective
7155b5e7992SMatthew G. Knepley 
716c6a43d28SMatthew G. Knepley   Input Parameters:
717c6a43d28SMatthew G. Knepley + label  - The DMLabel
718c6a43d28SMatthew G. Knepley . pStart - The smallest point
719c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
720c6a43d28SMatthew G. Knepley 
721c6a43d28SMatthew G. Knepley   Level: intermediate
722c6a43d28SMatthew G. Knepley 
723c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelComputeIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
724c6a43d28SMatthew G. Knepley @*/
725c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
726c58f1c22SToby Isaac {
727c58f1c22SToby Isaac   PetscInt       v;
728c58f1c22SToby Isaac 
729c58f1c22SToby Isaac   PetscFunctionBegin;
730d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7319566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7329566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
733c58f1c22SToby Isaac   label->pStart = pStart;
734c58f1c22SToby Isaac   label->pEnd   = pEnd;
735c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7369566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
737c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
738ad8374ffSToby Isaac     const PetscInt *points;
739c58f1c22SToby Isaac     PetscInt       i;
740c58f1c22SToby Isaac 
7419566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
742c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
743ad8374ffSToby Isaac       const PetscInt point = points[i];
744c58f1c22SToby Isaac 
74508401ef6SPierre Jolivet       PetscCheck(!(point < pStart) && !(point >= pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, pStart, pEnd);
7469566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
747c58f1c22SToby Isaac     }
7489566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
749c58f1c22SToby Isaac   }
750c58f1c22SToby Isaac   PetscFunctionReturn(0);
751c58f1c22SToby Isaac }
752c58f1c22SToby Isaac 
753c6a43d28SMatthew G. Knepley /*@
754c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
755c6a43d28SMatthew G. Knepley 
7565b5e7992SMatthew G. Knepley   Not collective
7575b5e7992SMatthew G. Knepley 
758c6a43d28SMatthew G. Knepley   Input Parameter:
759c6a43d28SMatthew G. Knepley . label - the DMLabel
760c6a43d28SMatthew G. Knepley 
761c6a43d28SMatthew G. Knepley   Level: intermediate
762c6a43d28SMatthew G. Knepley 
763c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
764c6a43d28SMatthew G. Knepley @*/
765c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
766c58f1c22SToby Isaac {
767c58f1c22SToby Isaac   PetscFunctionBegin;
768d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
769c58f1c22SToby Isaac   label->pStart = -1;
770c58f1c22SToby Isaac   label->pEnd   = -1;
7719566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
772c58f1c22SToby Isaac   PetscFunctionReturn(0);
773c58f1c22SToby Isaac }
774c58f1c22SToby Isaac 
775c58f1c22SToby Isaac /*@
776c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
777c6a43d28SMatthew G. Knepley 
7785b5e7992SMatthew G. Knepley   Not collective
7795b5e7992SMatthew G. Knepley 
780c6a43d28SMatthew G. Knepley   Input Parameter:
781c6a43d28SMatthew G. Knepley . label - the DMLabel
782c6a43d28SMatthew G. Knepley 
783c6a43d28SMatthew G. Knepley   Output Parameters:
784c6a43d28SMatthew G. Knepley + pStart - The smallest point
785c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
786c6a43d28SMatthew G. Knepley 
787c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
788c6a43d28SMatthew G. Knepley 
789c6a43d28SMatthew G. Knepley   Level: intermediate
790c6a43d28SMatthew G. Knepley 
791c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
792c6a43d28SMatthew G. Knepley @*/
793c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
794c6a43d28SMatthew G. Knepley {
795c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
796c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7979566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
798c6a43d28SMatthew G. Knepley   if (pStart) {
799534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
800c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
801c6a43d28SMatthew G. Knepley   }
802c6a43d28SMatthew G. Knepley   if (pEnd) {
803534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
804c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
805c6a43d28SMatthew G. Knepley   }
806c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
807c6a43d28SMatthew G. Knepley }
808c6a43d28SMatthew G. Knepley 
809c6a43d28SMatthew G. Knepley /*@
810c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
811c58f1c22SToby Isaac 
8125b5e7992SMatthew G. Knepley   Not collective
8135b5e7992SMatthew G. Knepley 
814c58f1c22SToby Isaac   Input Parameters:
815c58f1c22SToby Isaac + label - the DMLabel
816c58f1c22SToby Isaac - value - the value
817c58f1c22SToby Isaac 
818c58f1c22SToby Isaac   Output Parameter:
819c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
820c58f1c22SToby Isaac 
821c58f1c22SToby Isaac   Level: developer
822c58f1c22SToby Isaac 
823c58f1c22SToby Isaac .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue()
824c58f1c22SToby Isaac @*/
825c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
826c58f1c22SToby Isaac {
827c58f1c22SToby Isaac   PetscInt v;
828c58f1c22SToby Isaac 
829c58f1c22SToby Isaac   PetscFunctionBegin;
830d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
831534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8329566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8330c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
834c58f1c22SToby Isaac   PetscFunctionReturn(0);
835c58f1c22SToby Isaac }
836c58f1c22SToby Isaac 
837c58f1c22SToby Isaac /*@
838c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
839c58f1c22SToby Isaac 
8405b5e7992SMatthew G. Knepley   Not collective
8415b5e7992SMatthew G. Knepley 
842c58f1c22SToby Isaac   Input Parameters:
843c58f1c22SToby Isaac + label - the DMLabel
844c58f1c22SToby Isaac - point - the point
845c58f1c22SToby Isaac 
846c58f1c22SToby Isaac   Output Parameter:
847c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
848c58f1c22SToby Isaac 
849c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
850c58f1c22SToby Isaac 
851c58f1c22SToby Isaac   Level: developer
852c58f1c22SToby Isaac 
853c58f1c22SToby Isaac .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
854c58f1c22SToby Isaac @*/
855c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
856c58f1c22SToby Isaac {
857c58f1c22SToby Isaac   PetscFunctionBeginHot;
858d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
859534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8609566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
86176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
86228b400f6SJacob Faibussowitsch     PetscCheck(label->bt,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
86308401ef6SPierre Jolivet     PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
86476bd3646SJed Brown   }
865c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
866c58f1c22SToby Isaac   PetscFunctionReturn(0);
867c58f1c22SToby Isaac }
868c58f1c22SToby Isaac 
869c58f1c22SToby Isaac /*@
870c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
871c58f1c22SToby Isaac 
8725b5e7992SMatthew G. Knepley   Not collective
8735b5e7992SMatthew G. Knepley 
874c58f1c22SToby Isaac   Input Parameters:
875c58f1c22SToby Isaac + label - the DMLabel
876c58f1c22SToby Isaac . value - the stratum value
877c58f1c22SToby Isaac - point - the point
878c58f1c22SToby Isaac 
879c58f1c22SToby Isaac   Output Parameter:
880c58f1c22SToby Isaac . contains - true if the stratum contains the point
881c58f1c22SToby Isaac 
882c58f1c22SToby Isaac   Level: intermediate
883c58f1c22SToby Isaac 
884c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue()
885c58f1c22SToby Isaac @*/
886c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
887c58f1c22SToby Isaac {
888c58f1c22SToby Isaac   PetscInt       v;
889c58f1c22SToby Isaac 
8900c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
891d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
892534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
893c58f1c22SToby Isaac   *contains = PETSC_FALSE;
8949566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8950c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
8960c3c4a36SLisandro Dalcin 
897ad8374ffSToby Isaac   if (label->validIS[v]) {
898c58f1c22SToby Isaac     PetscInt i;
899c58f1c22SToby Isaac 
9009566063dSJacob Faibussowitsch     PetscCall(ISLocate(label->points[v], point, &i));
9010c3c4a36SLisandro Dalcin     if (i >= 0) *contains = PETSC_TRUE;
902c58f1c22SToby Isaac   } else {
903c58f1c22SToby Isaac     PetscBool has;
904c58f1c22SToby Isaac 
9059566063dSJacob Faibussowitsch     PetscCall(PetscHSetIHas(label->ht[v], point, &has));
9060c3c4a36SLisandro Dalcin     if (has) *contains = PETSC_TRUE;
907c58f1c22SToby Isaac   }
908c58f1c22SToby Isaac   PetscFunctionReturn(0);
909c58f1c22SToby Isaac }
910c58f1c22SToby Isaac 
91184f0b6dfSMatthew G. Knepley /*@
9125aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9135aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9145aa44df4SToby Isaac 
9155b5e7992SMatthew G. Knepley   Not collective
9165b5e7992SMatthew G. Knepley 
9175aa44df4SToby Isaac   Input parameter:
9185aa44df4SToby Isaac . label - a DMLabel object
9195aa44df4SToby Isaac 
9205aa44df4SToby Isaac   Output parameter:
9215aa44df4SToby Isaac . defaultValue - the default value
9225aa44df4SToby Isaac 
9235aa44df4SToby Isaac   Level: beginner
9245aa44df4SToby Isaac 
9255aa44df4SToby Isaac .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
92684f0b6dfSMatthew G. Knepley @*/
9275aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
9285aa44df4SToby Isaac {
9295aa44df4SToby Isaac   PetscFunctionBegin;
930d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9315aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9325aa44df4SToby Isaac   PetscFunctionReturn(0);
9335aa44df4SToby Isaac }
9345aa44df4SToby Isaac 
93584f0b6dfSMatthew G. Knepley /*@
9365aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9375aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9385aa44df4SToby Isaac 
9395b5e7992SMatthew G. Knepley   Not collective
9405b5e7992SMatthew G. Knepley 
9415aa44df4SToby Isaac   Input parameter:
9425aa44df4SToby Isaac . label - a DMLabel object
9435aa44df4SToby Isaac 
9445aa44df4SToby Isaac   Output parameter:
9455aa44df4SToby Isaac . defaultValue - the default value
9465aa44df4SToby Isaac 
9475aa44df4SToby Isaac   Level: beginner
9485aa44df4SToby Isaac 
9495aa44df4SToby Isaac .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
95084f0b6dfSMatthew G. Knepley @*/
9515aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
9525aa44df4SToby Isaac {
9535aa44df4SToby Isaac   PetscFunctionBegin;
954d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9555aa44df4SToby Isaac   label->defaultValue = defaultValue;
9565aa44df4SToby Isaac   PetscFunctionReturn(0);
9575aa44df4SToby Isaac }
9585aa44df4SToby Isaac 
959c58f1c22SToby Isaac /*@
9605aa44df4SToby 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())
961c58f1c22SToby Isaac 
9625b5e7992SMatthew G. Knepley   Not collective
9635b5e7992SMatthew G. Knepley 
964c58f1c22SToby Isaac   Input Parameters:
965c58f1c22SToby Isaac + label - the DMLabel
966c58f1c22SToby Isaac - point - the point
967c58f1c22SToby Isaac 
968c58f1c22SToby Isaac   Output Parameter:
9698e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
970c58f1c22SToby Isaac 
971c58f1c22SToby Isaac   Level: intermediate
972c58f1c22SToby Isaac 
9735aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
974c58f1c22SToby Isaac @*/
975c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
976c58f1c22SToby Isaac {
977c58f1c22SToby Isaac   PetscInt       v;
978c58f1c22SToby Isaac 
9790c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
980d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
981dadcf809SJacob Faibussowitsch   PetscValidIntPointer(value, 3);
9825aa44df4SToby Isaac   *value = label->defaultValue;
983c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
984ad8374ffSToby Isaac     if (label->validIS[v]) {
985c58f1c22SToby Isaac       PetscInt i;
986c58f1c22SToby Isaac 
9879566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
988c58f1c22SToby Isaac       if (i >= 0) {
989c58f1c22SToby Isaac         *value = label->stratumValues[v];
990c58f1c22SToby Isaac         break;
991c58f1c22SToby Isaac       }
992c58f1c22SToby Isaac     } else {
993c58f1c22SToby Isaac       PetscBool has;
994c58f1c22SToby Isaac 
9959566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
996c58f1c22SToby Isaac       if (has) {
997c58f1c22SToby Isaac         *value = label->stratumValues[v];
998c58f1c22SToby Isaac         break;
999c58f1c22SToby Isaac       }
1000c58f1c22SToby Isaac     }
1001c58f1c22SToby Isaac   }
1002c58f1c22SToby Isaac   PetscFunctionReturn(0);
1003c58f1c22SToby Isaac }
1004c58f1c22SToby Isaac 
1005c58f1c22SToby Isaac /*@
1006367003a6SStefano 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.
1007c58f1c22SToby Isaac 
10085b5e7992SMatthew G. Knepley   Not collective
10095b5e7992SMatthew G. Knepley 
1010c58f1c22SToby Isaac   Input Parameters:
1011c58f1c22SToby Isaac + label - the DMLabel
1012c58f1c22SToby Isaac . point - the point
1013c58f1c22SToby Isaac - value - The point value
1014c58f1c22SToby Isaac 
1015c58f1c22SToby Isaac   Level: intermediate
1016c58f1c22SToby Isaac 
10175aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
1018c58f1c22SToby Isaac @*/
1019c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1020c58f1c22SToby Isaac {
1021c58f1c22SToby Isaac   PetscInt       v;
1022c58f1c22SToby Isaac 
1023c58f1c22SToby Isaac   PetscFunctionBegin;
1024d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10250c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10265aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
10279566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1028c58f1c22SToby Isaac   /* Set key */
10299566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10309566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
1031c58f1c22SToby Isaac   PetscFunctionReturn(0);
1032c58f1c22SToby Isaac }
1033c58f1c22SToby Isaac 
1034c58f1c22SToby Isaac /*@
1035c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1036c58f1c22SToby Isaac 
10375b5e7992SMatthew G. Knepley   Not collective
10385b5e7992SMatthew G. Knepley 
1039c58f1c22SToby Isaac   Input Parameters:
1040c58f1c22SToby Isaac + label - the DMLabel
1041c58f1c22SToby Isaac . point - the point
1042c58f1c22SToby Isaac - value - The point value
1043c58f1c22SToby Isaac 
1044c58f1c22SToby Isaac   Level: intermediate
1045c58f1c22SToby Isaac 
1046c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue()
1047c58f1c22SToby Isaac @*/
1048c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1049c58f1c22SToby Isaac {
1050ad8374ffSToby Isaac   PetscInt       v;
1051c58f1c22SToby Isaac 
1052c58f1c22SToby Isaac   PetscFunctionBegin;
1053d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1054c58f1c22SToby Isaac   /* Find label value */
10559566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
10560c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
10570c3c4a36SLisandro Dalcin 
1058eeed21e7SToby Isaac   if (label->bt) {
105908401ef6SPierre Jolivet     PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
10609566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1061eeed21e7SToby Isaac   }
10620c3c4a36SLisandro Dalcin 
10630c3c4a36SLisandro Dalcin   /* Delete key */
10649566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10659566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
1066c58f1c22SToby Isaac   PetscFunctionReturn(0);
1067c58f1c22SToby Isaac }
1068c58f1c22SToby Isaac 
1069c58f1c22SToby Isaac /*@
1070c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
1071c58f1c22SToby Isaac 
10725b5e7992SMatthew G. Knepley   Not collective
10735b5e7992SMatthew G. Knepley 
1074c58f1c22SToby Isaac   Input Parameters:
1075c58f1c22SToby Isaac + label - the DMLabel
1076c58f1c22SToby Isaac . is    - the point IS
1077c58f1c22SToby Isaac - value - The point value
1078c58f1c22SToby Isaac 
1079c58f1c22SToby Isaac   Level: intermediate
1080c58f1c22SToby Isaac 
1081c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
1082c58f1c22SToby Isaac @*/
1083c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1084c58f1c22SToby Isaac {
10850c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1086c58f1c22SToby Isaac   const PetscInt *points;
1087c58f1c22SToby Isaac 
1088c58f1c22SToby Isaac   PetscFunctionBegin;
1089d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1090c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
10910c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10920c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
10939566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
10940c3c4a36SLisandro Dalcin   /* Set keys */
10959566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10969566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
10979566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
10989566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
10999566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
1100c58f1c22SToby Isaac   PetscFunctionReturn(0);
1101c58f1c22SToby Isaac }
1102c58f1c22SToby Isaac 
110384f0b6dfSMatthew G. Knepley /*@
110484f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
110584f0b6dfSMatthew G. Knepley 
11065b5e7992SMatthew G. Knepley   Not collective
11075b5e7992SMatthew G. Knepley 
110884f0b6dfSMatthew G. Knepley   Input Parameter:
110984f0b6dfSMatthew G. Knepley . label - the DMLabel
111084f0b6dfSMatthew G. Knepley 
111101d2d390SJose E. Roman   Output Parameter:
111284f0b6dfSMatthew G. Knepley . numValues - the number of values
111384f0b6dfSMatthew G. Knepley 
111484f0b6dfSMatthew G. Knepley   Level: intermediate
111584f0b6dfSMatthew G. Knepley 
111684f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
111784f0b6dfSMatthew G. Knepley @*/
1118c58f1c22SToby Isaac PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1119c58f1c22SToby Isaac {
1120c58f1c22SToby Isaac   PetscFunctionBegin;
1121d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1122dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numValues, 2);
1123c58f1c22SToby Isaac   *numValues = label->numStrata;
1124c58f1c22SToby Isaac   PetscFunctionReturn(0);
1125c58f1c22SToby Isaac }
1126c58f1c22SToby Isaac 
112784f0b6dfSMatthew G. Knepley /*@
112884f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
112984f0b6dfSMatthew G. Knepley 
11305b5e7992SMatthew G. Knepley   Not collective
11315b5e7992SMatthew G. Knepley 
113284f0b6dfSMatthew G. Knepley   Input Parameter:
113384f0b6dfSMatthew G. Knepley . label - the DMLabel
113484f0b6dfSMatthew G. Knepley 
113501d2d390SJose E. Roman   Output Parameter:
113684f0b6dfSMatthew G. Knepley . is    - the value IS
113784f0b6dfSMatthew G. Knepley 
113884f0b6dfSMatthew G. Knepley   Level: intermediate
113984f0b6dfSMatthew G. Knepley 
11401d04cbbeSVaclav Hapla   Notes:
11411d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11421d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
11431d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
11441d04cbbeSVaclav Hapla 
11451d04cbbeSVaclav Hapla .seealso: DMLabelGetNonEmptyStratumValuesIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
114684f0b6dfSMatthew G. Knepley @*/
1147c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1148c58f1c22SToby Isaac {
1149c58f1c22SToby Isaac   PetscFunctionBegin;
1150d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1151c58f1c22SToby Isaac   PetscValidPointer(values, 2);
11529566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1153c58f1c22SToby Isaac   PetscFunctionReturn(0);
1154c58f1c22SToby Isaac }
1155c58f1c22SToby Isaac 
115684f0b6dfSMatthew G. Knepley /*@
11571d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
11581d04cbbeSVaclav Hapla 
11591d04cbbeSVaclav Hapla   Not collective
11601d04cbbeSVaclav Hapla 
11611d04cbbeSVaclav Hapla   Input Parameter:
11621d04cbbeSVaclav Hapla . label - the DMLabel
11631d04cbbeSVaclav Hapla 
11641d04cbbeSVaclav Hapla   Output Paramater:
11651d04cbbeSVaclav Hapla . is    - the value IS
11661d04cbbeSVaclav Hapla 
11671d04cbbeSVaclav Hapla   Level: intermediate
11681d04cbbeSVaclav Hapla 
11691d04cbbeSVaclav Hapla   Notes:
11701d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11711d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
11721d04cbbeSVaclav Hapla 
11731d04cbbeSVaclav Hapla .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
11741d04cbbeSVaclav Hapla @*/
11751d04cbbeSVaclav Hapla PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
11761d04cbbeSVaclav Hapla {
11771d04cbbeSVaclav Hapla   PetscInt        i, j;
11781d04cbbeSVaclav Hapla   PetscInt       *valuesArr;
11791d04cbbeSVaclav Hapla 
11801d04cbbeSVaclav Hapla   PetscFunctionBegin;
11811d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11821d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
11839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
11841d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
11851d04cbbeSVaclav Hapla     PetscInt        n;
11861d04cbbeSVaclav Hapla 
11879566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
11881d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
11891d04cbbeSVaclav Hapla   }
11901d04cbbeSVaclav Hapla   if (j == label->numStrata) {
11919566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
11921d04cbbeSVaclav Hapla   } else {
11939566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
11941d04cbbeSVaclav Hapla   }
11959566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
11961d04cbbeSVaclav Hapla   PetscFunctionReturn(0);
11971d04cbbeSVaclav Hapla }
11981d04cbbeSVaclav Hapla 
11991d04cbbeSVaclav Hapla /*@
1200d123abd9SMatthew 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
1201d123abd9SMatthew G. Knepley 
1202d123abd9SMatthew G. Knepley   Not collective
1203d123abd9SMatthew G. Knepley 
1204d123abd9SMatthew G. Knepley   Input Parameters:
1205d123abd9SMatthew G. Knepley + label - the DMLabel
120697bb3fdcSJose E. Roman - value - the value
1207d123abd9SMatthew G. Knepley 
120801d2d390SJose E. Roman   Output Parameter:
1209d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1210d123abd9SMatthew G. Knepley 
1211d123abd9SMatthew G. Knepley   Level: intermediate
1212d123abd9SMatthew G. Knepley 
1213d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
1214d123abd9SMatthew G. Knepley @*/
1215d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1216d123abd9SMatthew G. Knepley {
1217d123abd9SMatthew G. Knepley   PetscInt v;
1218d123abd9SMatthew G. Knepley 
1219d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1220d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1221dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 3);
1222d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
1223d123abd9SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) if (label->stratumValues[v] == value) break;
1224d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1225d123abd9SMatthew G. Knepley   else                       *index = v;
1226d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1227d123abd9SMatthew G. Knepley }
1228d123abd9SMatthew G. Knepley 
1229d123abd9SMatthew G. Knepley /*@
123084f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
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 . exists - Flag saying whether points exist
124084f0b6dfSMatthew G. Knepley 
124184f0b6dfSMatthew G. Knepley   Level: intermediate
124284f0b6dfSMatthew G. Knepley 
124384f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
124484f0b6dfSMatthew G. Knepley @*/
1245fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1246fada774cSMatthew G. Knepley {
1247fada774cSMatthew G. Knepley   PetscInt       v;
1248fada774cSMatthew G. Knepley 
1249fada774cSMatthew G. Knepley   PetscFunctionBegin;
1250d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1251dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(exists, 3);
12529566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12530c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1254fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1255fada774cSMatthew G. Knepley }
1256fada774cSMatthew G. Knepley 
125784f0b6dfSMatthew G. Knepley /*@
125884f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
125984f0b6dfSMatthew G. Knepley 
12605b5e7992SMatthew G. Knepley   Not collective
12615b5e7992SMatthew G. Knepley 
126284f0b6dfSMatthew G. Knepley   Input Parameters:
126384f0b6dfSMatthew G. Knepley + label - the DMLabel
126484f0b6dfSMatthew G. Knepley - value - the stratum value
126584f0b6dfSMatthew G. Knepley 
126601d2d390SJose E. Roman   Output Parameter:
126784f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
126884f0b6dfSMatthew G. Knepley 
126984f0b6dfSMatthew G. Knepley   Level: intermediate
127084f0b6dfSMatthew G. Knepley 
127184f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
127284f0b6dfSMatthew G. Knepley @*/
1273c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1274c58f1c22SToby Isaac {
1275c58f1c22SToby Isaac   PetscInt       v;
1276c58f1c22SToby Isaac 
1277c58f1c22SToby Isaac   PetscFunctionBegin;
1278d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1279dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
12809566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12819566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
1282c58f1c22SToby Isaac   PetscFunctionReturn(0);
1283c58f1c22SToby Isaac }
1284c58f1c22SToby Isaac 
128584f0b6dfSMatthew G. Knepley /*@
128684f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
128784f0b6dfSMatthew G. Knepley 
12885b5e7992SMatthew G. Knepley   Not collective
12895b5e7992SMatthew G. Knepley 
129084f0b6dfSMatthew G. Knepley   Input Parameters:
129184f0b6dfSMatthew G. Knepley + label - the DMLabel
129284f0b6dfSMatthew G. Knepley - value - the stratum value
129384f0b6dfSMatthew G. Knepley 
129401d2d390SJose E. Roman   Output Parameters:
129584f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
129684f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
129784f0b6dfSMatthew G. Knepley 
129884f0b6dfSMatthew G. Knepley   Level: intermediate
129984f0b6dfSMatthew G. Knepley 
130084f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
130184f0b6dfSMatthew G. Knepley @*/
1302c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1303c58f1c22SToby Isaac {
13040c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1305c58f1c22SToby Isaac 
1306c58f1c22SToby Isaac   PetscFunctionBegin;
1307d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1308dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = -1;}
1309dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = -1;}
13109566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13110c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13129566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13130c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
13149566063dSJacob Faibussowitsch   PetscCall(ISGetMinMax(label->points[v], &min, &max));
1315d6cb179aSToby Isaac   if (start) *start = min;
1316d6cb179aSToby Isaac   if (end)   *end   = max+1;
1317c58f1c22SToby Isaac   PetscFunctionReturn(0);
1318c58f1c22SToby Isaac }
1319c58f1c22SToby Isaac 
132084f0b6dfSMatthew G. Knepley /*@
132184f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
132284f0b6dfSMatthew G. Knepley 
13235b5e7992SMatthew G. Knepley   Not collective
13245b5e7992SMatthew G. Knepley 
132584f0b6dfSMatthew G. Knepley   Input Parameters:
132684f0b6dfSMatthew G. Knepley + label - the DMLabel
132784f0b6dfSMatthew G. Knepley - value - the stratum value
132884f0b6dfSMatthew G. Knepley 
132901d2d390SJose E. Roman   Output Parameter:
133084f0b6dfSMatthew G. Knepley . points - The stratum points
133184f0b6dfSMatthew G. Knepley 
133284f0b6dfSMatthew G. Knepley   Level: intermediate
133384f0b6dfSMatthew G. Knepley 
1334593ce467SVaclav Hapla   Notes:
1335593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1336593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1337593ce467SVaclav Hapla 
133884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
133984f0b6dfSMatthew G. Knepley @*/
1340c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1341c58f1c22SToby Isaac {
1342c58f1c22SToby Isaac   PetscInt       v;
1343c58f1c22SToby Isaac 
1344c58f1c22SToby Isaac   PetscFunctionBegin;
1345d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1346c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1347c58f1c22SToby Isaac   *points = NULL;
13489566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13490c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13509566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13519566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject) label->points[v]));
1352ad8374ffSToby Isaac   *points = label->points[v];
1353c58f1c22SToby Isaac   PetscFunctionReturn(0);
1354c58f1c22SToby Isaac }
1355c58f1c22SToby Isaac 
135684f0b6dfSMatthew G. Knepley /*@
135784f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
135884f0b6dfSMatthew G. Knepley 
13595b5e7992SMatthew G. Knepley   Not collective
13605b5e7992SMatthew G. Knepley 
136184f0b6dfSMatthew G. Knepley   Input Parameters:
136284f0b6dfSMatthew G. Knepley + label - the DMLabel
136384f0b6dfSMatthew G. Knepley . value - the stratum value
136484f0b6dfSMatthew G. Knepley - points - The stratum points
136584f0b6dfSMatthew G. Knepley 
136684f0b6dfSMatthew G. Knepley   Level: intermediate
136784f0b6dfSMatthew G. Knepley 
136884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
136984f0b6dfSMatthew G. Knepley @*/
13704de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
13714de306b1SToby Isaac {
13720c3c4a36SLisandro Dalcin   PetscInt       v;
13734de306b1SToby Isaac 
13744de306b1SToby Isaac   PetscFunctionBegin;
1375d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1376d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
13779566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
13784de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
13799566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
13809566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
13819566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
13829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&(label->points[v])));
13830c3c4a36SLisandro Dalcin   label->points[v]  = is;
13840c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
13859566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject) label));
13864de306b1SToby Isaac   if (label->bt) {
13874de306b1SToby Isaac     const PetscInt *points;
13884de306b1SToby Isaac     PetscInt p;
13894de306b1SToby Isaac 
13909566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,&points));
13914de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
13924de306b1SToby Isaac       const PetscInt point = points[p];
13934de306b1SToby Isaac 
139408401ef6SPierre Jolivet       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
13959566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
13964de306b1SToby Isaac     }
13974de306b1SToby Isaac   }
13984de306b1SToby Isaac   PetscFunctionReturn(0);
13994de306b1SToby Isaac }
14004de306b1SToby Isaac 
140184f0b6dfSMatthew G. Knepley /*@
140284f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14034de306b1SToby Isaac 
14045b5e7992SMatthew G. Knepley   Not collective
14055b5e7992SMatthew G. Knepley 
140684f0b6dfSMatthew G. Knepley   Input Parameters:
140784f0b6dfSMatthew G. Knepley + label - the DMLabel
140884f0b6dfSMatthew G. Knepley - value - the stratum value
140984f0b6dfSMatthew G. Knepley 
141084f0b6dfSMatthew G. Knepley   Level: intermediate
141184f0b6dfSMatthew G. Knepley 
141284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
141384f0b6dfSMatthew G. Knepley @*/
1414c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1415c58f1c22SToby Isaac {
1416c58f1c22SToby Isaac   PetscInt       v;
1417c58f1c22SToby Isaac 
1418c58f1c22SToby Isaac   PetscFunctionBegin;
1419d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14209566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14210c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
14224de306b1SToby Isaac   if (label->validIS[v]) {
14234de306b1SToby Isaac     if (label->bt) {
1424c58f1c22SToby Isaac       PetscInt       i;
1425ad8374ffSToby Isaac       const PetscInt *points;
1426c58f1c22SToby Isaac 
14279566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1428c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1429ad8374ffSToby Isaac         const PetscInt point = points[i];
1430c58f1c22SToby Isaac 
143108401ef6SPierre Jolivet         PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
14329566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1433c58f1c22SToby Isaac       }
14349566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1435c58f1c22SToby Isaac     }
1436c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
14379566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
14389566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
14399566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) label->points[v], "indices"));
14409566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject) label));
1441c58f1c22SToby Isaac   } else {
14429566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1443c58f1c22SToby Isaac   }
1444c58f1c22SToby Isaac   PetscFunctionReturn(0);
1445c58f1c22SToby Isaac }
1446c58f1c22SToby Isaac 
144784f0b6dfSMatthew G. Knepley /*@
1448412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1449412e9a14SMatthew G. Knepley 
1450412e9a14SMatthew G. Knepley   Not collective
1451412e9a14SMatthew G. Knepley 
1452412e9a14SMatthew G. Knepley   Input Parameters:
1453412e9a14SMatthew G. Knepley + label  - The DMLabel
1454412e9a14SMatthew G. Knepley . value  - The label value for all points
1455412e9a14SMatthew G. Knepley . pStart - The first point
1456412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1457412e9a14SMatthew G. Knepley 
1458412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1459412e9a14SMatthew G. Knepley 
1460412e9a14SMatthew G. Knepley   Level: intermediate
1461412e9a14SMatthew G. Knepley 
1462412e9a14SMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelSetStratumIS(), DMLabelGetStratumIS()
1463412e9a14SMatthew G. Knepley @*/
1464412e9a14SMatthew G. Knepley PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1465412e9a14SMatthew G. Knepley {
1466412e9a14SMatthew G. Knepley   IS             pIS;
1467412e9a14SMatthew G. Knepley 
1468412e9a14SMatthew G. Knepley   PetscFunctionBegin;
14699566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
14709566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
14719566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
1472412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1473412e9a14SMatthew G. Knepley }
1474412e9a14SMatthew G. Knepley 
1475412e9a14SMatthew G. Knepley /*@
1476d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1477d123abd9SMatthew G. Knepley 
1478d123abd9SMatthew G. Knepley   Not collective
1479d123abd9SMatthew G. Knepley 
1480d123abd9SMatthew G. Knepley   Input Parameters:
1481d123abd9SMatthew G. Knepley + label  - The DMLabel
1482d123abd9SMatthew G. Knepley . value  - The label value
1483d123abd9SMatthew G. Knepley - p      - A point with this value
1484d123abd9SMatthew G. Knepley 
1485d123abd9SMatthew G. Knepley   Output Parameter:
1486d123abd9SMatthew 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
1487d123abd9SMatthew G. Knepley 
1488d123abd9SMatthew G. Knepley   Level: intermediate
1489d123abd9SMatthew G. Knepley 
1490d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIndex(), DMLabelGetStratumIS(), DMLabelCreate()
1491d123abd9SMatthew G. Knepley @*/
1492d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1493d123abd9SMatthew G. Knepley {
1494d123abd9SMatthew G. Knepley   const PetscInt *indices;
1495d123abd9SMatthew G. Knepley   PetscInt        v;
1496d123abd9SMatthew G. Knepley 
1497d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1498d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1499dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 4);
1500d123abd9SMatthew G. Knepley   *index = -1;
15019566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1502d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
15039566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
15049566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(label->points[v], &indices));
15059566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
15069566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(label->points[v], &indices));
1507d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1508d123abd9SMatthew G. Knepley }
1509d123abd9SMatthew G. Knepley 
1510d123abd9SMatthew G. Knepley /*@
151184f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
151284f0b6dfSMatthew G. Knepley 
15135b5e7992SMatthew G. Knepley   Not collective
15145b5e7992SMatthew G. Knepley 
151584f0b6dfSMatthew G. Knepley   Input Parameters:
151684f0b6dfSMatthew G. Knepley + label - the DMLabel
151722cd2cdaSVaclav Hapla . start - the first point kept
151822cd2cdaSVaclav Hapla - end - one more than the last point kept
151984f0b6dfSMatthew G. Knepley 
152084f0b6dfSMatthew G. Knepley   Level: intermediate
152184f0b6dfSMatthew G. Knepley 
152284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
152384f0b6dfSMatthew G. Knepley @*/
1524c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1525c58f1c22SToby Isaac {
1526c58f1c22SToby Isaac   PetscInt       v;
1527c58f1c22SToby Isaac 
1528c58f1c22SToby Isaac   PetscFunctionBegin;
1529d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15309566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
15319566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
1532c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
15339566063dSJacob Faibussowitsch     PetscCall(ISGeneralFilter(label->points[v], start, end));
1534c58f1c22SToby Isaac   }
15359566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
1536c58f1c22SToby Isaac   PetscFunctionReturn(0);
1537c58f1c22SToby Isaac }
1538c58f1c22SToby Isaac 
153984f0b6dfSMatthew G. Knepley /*@
154084f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
154184f0b6dfSMatthew G. Knepley 
15425b5e7992SMatthew G. Knepley   Not collective
15435b5e7992SMatthew G. Knepley 
154484f0b6dfSMatthew G. Knepley   Input Parameters:
154584f0b6dfSMatthew G. Knepley + label - the DMLabel
154684f0b6dfSMatthew G. Knepley - permutation - the point permutation
154784f0b6dfSMatthew G. Knepley 
154884f0b6dfSMatthew G. Knepley   Output Parameter:
154984f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
155084f0b6dfSMatthew G. Knepley 
155184f0b6dfSMatthew G. Knepley   Level: intermediate
155284f0b6dfSMatthew G. Knepley 
155384f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
155484f0b6dfSMatthew G. Knepley @*/
1555c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1556c58f1c22SToby Isaac {
1557c58f1c22SToby Isaac   const PetscInt *perm;
1558c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1559c58f1c22SToby Isaac 
1560c58f1c22SToby Isaac   PetscFunctionBegin;
1561d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1562d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
15639566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
15649566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
15659566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
15669566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
15679566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1568c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1569c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1570ad8374ffSToby Isaac     const PetscInt *points;
1571ad8374ffSToby Isaac     PetscInt *pointsNew;
1572c58f1c22SToby Isaac 
15739566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v],&points));
15749566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size,&pointsNew));
1575c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1576ad8374ffSToby Isaac       const PetscInt point = points[q];
1577c58f1c22SToby Isaac 
157808401ef6SPierre Jolivet       PetscCheck(!(point < 0) && !(point >= numPoints),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [0, %D) for the remapping", point, numPoints);
1579ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1580c58f1c22SToby Isaac     }
15819566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v],&points));
15829566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
15839566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1584fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
15859566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v])));
15869566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1587fa8e8ae5SToby Isaac     } else {
15889566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v])));
1589fa8e8ae5SToby Isaac     }
15909566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices"));
1591c58f1c22SToby Isaac   }
15929566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1593c58f1c22SToby Isaac   if (label->bt) {
15949566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
15959566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1596c58f1c22SToby Isaac   }
1597c58f1c22SToby Isaac   PetscFunctionReturn(0);
1598c58f1c22SToby Isaac }
1599c58f1c22SToby Isaac 
160026c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
160126c55118SMichael Lange {
160226c55118SMichael Lange   MPI_Comm       comm;
1603eb30be1eSVaclav Hapla   PetscInt       s, l, nroots, nleaves, offset, size;
160426c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
160526c55118SMichael Lange   PetscSection   rootSection;
160626c55118SMichael Lange   PetscSF        labelSF;
160726c55118SMichael Lange 
160826c55118SMichael Lange   PetscFunctionBegin;
16099566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
16109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
161126c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
161226c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
16139566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
16149566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
16159566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
161626c55118SMichael Lange   if (label) {
161726c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1618ad8374ffSToby Isaac       const PetscInt *points;
1619ad8374ffSToby Isaac 
16209566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
162126c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1622eb30be1eSVaclav Hapla         PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
162326c55118SMichael Lange       }
16249566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
162526c55118SMichael Lange     }
162626c55118SMichael Lange   }
16279566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
162826c55118SMichael Lange   /* Create a point-wise array of stratum values */
16299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
16309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
16319566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
163226c55118SMichael Lange   if (label) {
163326c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1634ad8374ffSToby Isaac       const PetscInt *points;
1635ad8374ffSToby Isaac 
16369566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
163726c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1638ad8374ffSToby Isaac         const PetscInt p = points[l];
16399566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
164026c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
164126c55118SMichael Lange       }
16429566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
164326c55118SMichael Lange     }
164426c55118SMichael Lange   }
164526c55118SMichael Lange   /* Build SF that maps label points to remote processes */
16469566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
16479566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
16489566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
16499566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
165026c55118SMichael Lange   /* Send the strata for each point over the derived SF */
16519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
16529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
16539566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
16549566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
165526c55118SMichael Lange   /* Clean up */
16569566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
16579566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
16589566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
16599566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
166026c55118SMichael Lange   PetscFunctionReturn(0);
166126c55118SMichael Lange }
166226c55118SMichael Lange 
166384f0b6dfSMatthew G. Knepley /*@
166484f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
166584f0b6dfSMatthew G. Knepley 
16665b5e7992SMatthew G. Knepley   Collective on sf
16675b5e7992SMatthew G. Knepley 
166884f0b6dfSMatthew G. Knepley   Input Parameters:
166984f0b6dfSMatthew G. Knepley + label - the DMLabel
167084f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
167184f0b6dfSMatthew G. Knepley 
167284f0b6dfSMatthew G. Knepley   Output Parameter:
167384f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
167484f0b6dfSMatthew G. Knepley 
167584f0b6dfSMatthew G. Knepley   Level: intermediate
167684f0b6dfSMatthew G. Knepley 
167784f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
167884f0b6dfSMatthew G. Knepley @*/
1679c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1680c58f1c22SToby Isaac {
1681c58f1c22SToby Isaac   MPI_Comm       comm;
168226c55118SMichael Lange   PetscSection   leafSection;
168326c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
168426c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1685ad8374ffSToby Isaac   PetscInt     **points;
1686d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1687c58f1c22SToby Isaac   char          *name;
1688c58f1c22SToby Isaac   PetscInt       nameSize;
1689e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1690c58f1c22SToby Isaac   size_t         len = 0;
169126c55118SMichael Lange   PetscMPIInt    rank;
1692c58f1c22SToby Isaac 
1693c58f1c22SToby Isaac   PetscFunctionBegin;
1694d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1695f018e600SMatthew G. Knepley   if (label) {
1696f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16979566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1698f018e600SMatthew G. Knepley   }
16999566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1701c58f1c22SToby Isaac   /* Bcast name */
1702dd400576SPatrick Sanan   if (rank == 0) {
17039566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &lname));
17049566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1705d67d17b1SMatthew G. Knepley   }
1706c58f1c22SToby Isaac   nameSize = len;
17079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize+1, &name));
17099566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize+1));
17109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
17119566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17129566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
171377d236dfSMichael Lange   /* Bcast defaultValue */
1714dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
17159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
171626c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
17179566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
17185cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
17199566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
17209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
17219566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
17229566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
17239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1724ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
17259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
17265cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
17275cbdf6fcSMichael Lange   offset = 0;
17289566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
17299566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues));
173090e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17319566063dSJacob Faibussowitsch     PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
173290e9b2aeSLisandro Dalcin   }
17335cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1734231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1735231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
17365cbdf6fcSMichael Lange     }
17375cbdf6fcSMichael Lange   }
1738c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
17399566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes));
17409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1741c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1744c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1745c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1746c58f1c22SToby Isaac     }
1747c58f1c22SToby Isaac   }
17489566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht));
17499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points));
17509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata,&points));
1751c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17529566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
17539566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1754c58f1c22SToby Isaac   }
1755c58f1c22SToby Isaac   /* Insert points into new strata */
17569566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
17579566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1758c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1761c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1762c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1763ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1764c58f1c22SToby Isaac     }
1765c58f1c22SToby Isaac   }
1766ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
17679566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s])));
17689566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices"));
1769ad8374ffSToby Isaac   }
17709566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
17719566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
17729566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
17739566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
17749566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
1775c58f1c22SToby Isaac   PetscFunctionReturn(0);
1776c58f1c22SToby Isaac }
1777c58f1c22SToby Isaac 
17787937d9ceSMichael Lange /*@
17797937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
17807937d9ceSMichael Lange 
17815b5e7992SMatthew G. Knepley   Collective on sf
17825b5e7992SMatthew G. Knepley 
17837937d9ceSMichael Lange   Input Parameters:
17847937d9ceSMichael Lange + label - the DMLabel
178584f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
17867937d9ceSMichael Lange 
178784f0b6dfSMatthew G. Knepley   Output Parameters:
178884f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
17897937d9ceSMichael Lange 
17907937d9ceSMichael Lange   Level: developer
17917937d9ceSMichael Lange 
17927937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
17937937d9ceSMichael Lange 
17947937d9ceSMichael Lange .seealso: DMLabelDistribute()
17957937d9ceSMichael Lange @*/
17967937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
17977937d9ceSMichael Lange {
17987937d9ceSMichael Lange   MPI_Comm       comm;
17997937d9ceSMichael Lange   PetscSection   rootSection;
18007937d9ceSMichael Lange   PetscSF        sfLabel;
18017937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
18027937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18037937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18047937d9ceSMichael Lange   PetscInt       *rootStrata;
1805d67d17b1SMatthew G. Knepley   const char    *lname;
18067937d9ceSMichael Lange   char          *name;
18077937d9ceSMichael Lange   PetscInt       nameSize;
18087937d9ceSMichael Lange   size_t         len = 0;
18099852e123SBarry Smith   PetscMPIInt    rank, size;
18107937d9ceSMichael Lange 
18117937d9ceSMichael Lange   PetscFunctionBegin;
1812d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1813d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
18149566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
18159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
18169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
18177937d9ceSMichael Lange   /* Bcast name */
1818dd400576SPatrick Sanan   if (rank == 0) {
18199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &lname));
18209566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1821d67d17b1SMatthew G. Knepley   }
18227937d9ceSMichael Lange   nameSize = len;
18239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
18249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize+1, &name));
18259566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize+1));
18269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
18279566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
18289566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
18297937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
18307937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
18317937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
18329566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
18339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1834dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
18357937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
18368212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
18378212dd46SStefano Zampini 
18388212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
18398212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
18407937d9ceSMichael Lange   }
18419566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
18429566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
18437937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
18449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
18459566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
18469566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
18479566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm,& sfLabel));
18489566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
18497937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
18509566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
18517937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
18527937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
18537937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
18549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx+d, &dof));
18559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx+d, &offset));
18569566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset+s]));
18577937d9ceSMichael Lange     }
18587937d9ceSMichael Lange     idx += rootDegree[p];
18597937d9ceSMichael Lange   }
18609566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
18619566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18629566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18639566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
18647937d9ceSMichael Lange   PetscFunctionReturn(0);
18657937d9ceSMichael Lange }
18667937d9ceSMichael Lange 
1867*d42890abSMatthew G. Knepley static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1868*d42890abSMatthew G. Knepley {
1869*d42890abSMatthew G. Knepley   const PetscInt *degree;
1870*d42890abSMatthew G. Knepley   const PetscInt *points;
1871*d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1872*d42890abSMatthew G. Knepley 
1873*d42890abSMatthew G. Knepley   PetscFunctionBegin;
1874*d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1875*d42890abSMatthew G. Knepley   /* Add in leaves */
1876*d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1877*d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1878*d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1879*d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1880*d42890abSMatthew G. Knepley   }
1881*d42890abSMatthew G. Knepley   /* Add in shared roots */
1882*d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1883*d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1884*d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1885*d42890abSMatthew G. Knepley     if (degree[r]) {
1886*d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1887*d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1888*d42890abSMatthew G. Knepley     }
1889*d42890abSMatthew G. Knepley   }
1890*d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1891*d42890abSMatthew G. Knepley }
1892*d42890abSMatthew G. Knepley 
1893*d42890abSMatthew G. Knepley static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1894*d42890abSMatthew G. Knepley {
1895*d42890abSMatthew G. Knepley   const PetscInt *degree;
1896*d42890abSMatthew G. Knepley   const PetscInt *points;
1897*d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1898*d42890abSMatthew G. Knepley 
1899*d42890abSMatthew G. Knepley   PetscFunctionBegin;
1900*d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1901*d42890abSMatthew G. Knepley   /* Read out leaves */
1902*d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1903*d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1904*d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1905*d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1906*d42890abSMatthew G. Knepley 
1907*d42890abSMatthew G. Knepley     if (cval != defVal) {
1908*d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1909*d42890abSMatthew G. Knepley       if (val == defVal) {
1910*d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
1911*d42890abSMatthew G. Knepley         if (markPoint) {PetscCall((*markPoint)(label, p, cval, ctx));}
1912*d42890abSMatthew G. Knepley       }
1913*d42890abSMatthew G. Knepley     }
1914*d42890abSMatthew G. Knepley   }
1915*d42890abSMatthew G. Knepley   /* Read out shared roots */
1916*d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1917*d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1918*d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1919*d42890abSMatthew G. Knepley     if (degree[r]) {
1920*d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
1921*d42890abSMatthew G. Knepley 
1922*d42890abSMatthew G. Knepley       if (cval != defVal) {
1923*d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
1924*d42890abSMatthew G. Knepley         if (val == defVal) {
1925*d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
1926*d42890abSMatthew G. Knepley           if (markPoint) {PetscCall((*markPoint)(label, r, cval, ctx));}
1927*d42890abSMatthew G. Knepley         }
1928*d42890abSMatthew G. Knepley       }
1929*d42890abSMatthew G. Knepley     }
1930*d42890abSMatthew G. Knepley   }
1931*d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1932*d42890abSMatthew G. Knepley }
1933*d42890abSMatthew G. Knepley 
1934*d42890abSMatthew G. Knepley /*@
1935*d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
1936*d42890abSMatthew G. Knepley 
1937*d42890abSMatthew G. Knepley   Collective on sf
1938*d42890abSMatthew G. Knepley 
1939*d42890abSMatthew G. Knepley   Input Parameters:
1940*d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1941*d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1942*d42890abSMatthew G. Knepley 
1943*d42890abSMatthew G. Knepley   Level: intermediate
1944*d42890abSMatthew G. Knepley 
1945*d42890abSMatthew G. Knepley .seealso: DMLabelPropagateEnd(), DMLabelPropagatePush()
1946*d42890abSMatthew G. Knepley @*/
1947*d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
1948*d42890abSMatthew G. Knepley {
1949*d42890abSMatthew G. Knepley   PetscInt       Nr, r, defVal;
1950*d42890abSMatthew G. Knepley   PetscMPIInt    size;
1951*d42890abSMatthew G. Knepley 
1952*d42890abSMatthew G. Knepley   PetscFunctionBegin;
1953*d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) sf), &size));
1954*d42890abSMatthew G. Knepley   if (size > 1) {
1955*d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
1956*d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
1957*d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
1958*d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
1959*d42890abSMatthew G. Knepley   }
1960*d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1961*d42890abSMatthew G. Knepley }
1962*d42890abSMatthew G. Knepley 
1963*d42890abSMatthew G. Knepley /*@
1964*d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
1965*d42890abSMatthew G. Knepley 
1966*d42890abSMatthew G. Knepley   Collective on sf
1967*d42890abSMatthew G. Knepley 
1968*d42890abSMatthew G. Knepley   Input Parameters:
1969*d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1970*d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1971*d42890abSMatthew G. Knepley 
1972*d42890abSMatthew G. Knepley   Level: intermediate
1973*d42890abSMatthew G. Knepley 
1974*d42890abSMatthew G. Knepley .seealso: DMLabelPropagateBegin(), DMLabelPropagatePush()
1975*d42890abSMatthew G. Knepley @*/
1976*d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
1977*d42890abSMatthew G. Knepley {
1978*d42890abSMatthew G. Knepley   PetscFunctionBegin;
1979*d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
1980*d42890abSMatthew G. Knepley   label->propArray = NULL;
1981*d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1982*d42890abSMatthew G. Knepley }
1983*d42890abSMatthew G. Knepley 
1984*d42890abSMatthew G. Knepley /*@C
1985*d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
1986*d42890abSMatthew G. Knepley 
1987*d42890abSMatthew G. Knepley   Collective on sf
1988*d42890abSMatthew G. Knepley 
1989*d42890abSMatthew G. Knepley   Input Parameters:
1990*d42890abSMatthew G. Knepley + label     - The DMLabel to propagate across processes
1991*d42890abSMatthew G. Knepley . sf        - The SF describing parallel layout of the label points
1992*d42890abSMatthew G. Knepley . markPoint - An optional user callback that is called when a point is marked, or NULL
1993*d42890abSMatthew G. Knepley - ctx       - An optional user context for the callback, or NULL
1994*d42890abSMatthew G. Knepley 
1995*d42890abSMatthew G. Knepley   Calling sequence of markPoint:
1996*d42890abSMatthew G. Knepley $ markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
1997*d42890abSMatthew G. Knepley 
1998*d42890abSMatthew G. Knepley + label - The DMLabel
1999*d42890abSMatthew G. Knepley . p     - The point being marked
2000*d42890abSMatthew G. Knepley . val   - The label value for p
2001*d42890abSMatthew G. Knepley - ctx   - An optional user context
2002*d42890abSMatthew G. Knepley 
2003*d42890abSMatthew G. Knepley   Level: intermediate
2004*d42890abSMatthew G. Knepley 
2005*d42890abSMatthew G. Knepley .seealso: DMLabelPropagateBegin(), DMLabelPropagateEnd()
2006*d42890abSMatthew G. Knepley @*/
2007*d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2008*d42890abSMatthew G. Knepley {
2009*d42890abSMatthew G. Knepley   PetscInt      *valArray = label->propArray;
2010*d42890abSMatthew G. Knepley   PetscMPIInt    size;
2011*d42890abSMatthew G. Knepley 
2012*d42890abSMatthew G. Knepley   PetscFunctionBegin;
2013*d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) pointSF), &size));
2014*d42890abSMatthew G. Knepley   if (size > 1) {
2015*d42890abSMatthew G. Knepley     /* Communicate marked edges
2016*d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2017*d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2018*d42890abSMatthew G. Knepley 
2019*d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2020*d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2021*d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2022*d42890abSMatthew G. Knepley 
2023*d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2024*d42890abSMatthew 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
2025*d42890abSMatthew G. Knepley        edge to the queue.
2026*d42890abSMatthew G. Knepley     */
2027*d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2028*d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2029*d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2030*d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray,MPI_REPLACE));
2031*d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray,MPI_REPLACE));
2032*d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2033*d42890abSMatthew G. Knepley   }
2034*d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
2035*d42890abSMatthew G. Knepley }
2036*d42890abSMatthew G. Knepley 
203784f0b6dfSMatthew G. Knepley /*@
203884f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
203984f0b6dfSMatthew G. Knepley 
20405b5e7992SMatthew G. Knepley   Not collective
20415b5e7992SMatthew G. Knepley 
204284f0b6dfSMatthew G. Knepley   Input Parameter:
204384f0b6dfSMatthew G. Knepley . label - the DMLabel
204484f0b6dfSMatthew G. Knepley 
204584f0b6dfSMatthew G. Knepley   Output Parameters:
204684f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
204784f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
204884f0b6dfSMatthew G. Knepley 
204984f0b6dfSMatthew G. Knepley   Level: developer
205084f0b6dfSMatthew G. Knepley 
205184f0b6dfSMatthew G. Knepley .seealso: DMLabelDistribute()
205284f0b6dfSMatthew G. Knepley @*/
2053c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2054c58f1c22SToby Isaac {
2055c58f1c22SToby Isaac   IS              vIS;
2056c58f1c22SToby Isaac   const PetscInt *values;
2057c58f1c22SToby Isaac   PetscInt       *points;
2058c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2059c58f1c22SToby Isaac 
2060c58f1c22SToby Isaac   PetscFunctionBegin;
2061d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
20629566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
20639566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
20649566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
2065c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
2066c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2067c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2068c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
2069c58f1c22SToby Isaac   }
20709566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
20719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2072c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2073c58f1c22SToby Isaac     PetscInt n;
2074c58f1c22SToby Isaac 
20759566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
20769566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2077c58f1c22SToby Isaac   }
20789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
20799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
20809566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2081c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2082c58f1c22SToby Isaac     IS              is;
2083c58f1c22SToby Isaac     const PetscInt *spoints;
2084c58f1c22SToby Isaac     PetscInt        dof, off, p;
2085c58f1c22SToby Isaac 
20869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
20879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
20889566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
20899566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2090c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
20919566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
20929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2093c58f1c22SToby Isaac   }
20949566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
20959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
20969566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
2097c58f1c22SToby Isaac   PetscFunctionReturn(0);
2098c58f1c22SToby Isaac }
2099c58f1c22SToby Isaac 
210084f0b6dfSMatthew G. Knepley /*@
2101c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2102c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
2103c58f1c22SToby Isaac 
21045b5e7992SMatthew G. Knepley   Collective on sf
21055b5e7992SMatthew G. Knepley 
2106c58f1c22SToby Isaac   Input Parameters:
2107c58f1c22SToby Isaac   + s - The PetscSection for the local field layout
2108c58f1c22SToby Isaac   . sf - The SF describing parallel layout of the section points
2109c58f1c22SToby Isaac   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
2110c58f1c22SToby Isaac   . label - The label specifying the points
2111c58f1c22SToby Isaac   - labelValue - The label stratum specifying the points
2112c58f1c22SToby Isaac 
2113c58f1c22SToby Isaac   Output Parameter:
2114c58f1c22SToby Isaac   . gsection - The PetscSection for the global field layout
2115c58f1c22SToby Isaac 
2116c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
2117c58f1c22SToby Isaac 
2118c58f1c22SToby Isaac   Level: developer
2119c58f1c22SToby Isaac 
2120c58f1c22SToby Isaac .seealso: PetscSectionCreate()
2121c58f1c22SToby Isaac @*/
2122c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2123c58f1c22SToby Isaac {
2124c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
2125c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2126c58f1c22SToby Isaac 
2127c58f1c22SToby Isaac   PetscFunctionBegin;
2128d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2129d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2130d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
21319566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection));
21329566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
21339566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
21349566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2135c58f1c22SToby Isaac   if (nroots >= 0) {
213608401ef6SPierre Jolivet     PetscCheck(nroots >= pEnd-pStart,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
21379566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2138c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
21399566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2140c58f1c22SToby Isaac     } else {
2141c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2142c58f1c22SToby Isaac     }
2143c58f1c22SToby Isaac   }
2144c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2145c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2146c58f1c22SToby Isaac     PetscInt value;
2147c58f1c22SToby Isaac 
21489566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2149c58f1c22SToby Isaac     if (value != labelValue) continue;
21509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
21519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
21529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
21539566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2154c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
2155c58f1c22SToby Isaac   }
21569566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2157c58f1c22SToby Isaac   if (nroots >= 0) {
21589566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
21599566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
2160c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
2161c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
2162c58f1c22SToby Isaac     }
2163c58f1c22SToby Isaac   }
2164c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
2165c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
2166c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2167c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2168c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
2169c58f1c22SToby Isaac   }
21709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s)));
2171c58f1c22SToby Isaac   globalOff -= off;
2172c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
2173c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2174c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
2175c58f1c22SToby Isaac   }
2176c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2177c58f1c22SToby Isaac   if (nroots >= 0) {
21789566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
21799566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
2180c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
2181c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
2182c58f1c22SToby Isaac     }
2183c58f1c22SToby Isaac   }
21849566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd-pStart) PetscCall(PetscFree(tmpOff));
21859566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
2186c58f1c22SToby Isaac   PetscFunctionReturn(0);
2187c58f1c22SToby Isaac }
2188c58f1c22SToby Isaac 
21895fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
21905fdea053SToby Isaac {
21915fdea053SToby Isaac   DMLabel           label;
21925fdea053SToby Isaac   PetscCopyMode     *modes;
21935fdea053SToby Isaac   PetscInt          *sizes;
21945fdea053SToby Isaac   const PetscInt    ***perms;
21955fdea053SToby Isaac   const PetscScalar ***rots;
21965fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
21975fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
21985fdea053SToby Isaac } PetscSectionSym_Label;
21995fdea053SToby Isaac 
22005fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
22015fdea053SToby Isaac {
22025fdea053SToby Isaac   PetscInt              i, j;
22035fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
22045fdea053SToby Isaac 
22055fdea053SToby Isaac   PetscFunctionBegin;
22065fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
22075fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
22085fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22099566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
22109566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
22115fdea053SToby Isaac       }
22125fdea053SToby Isaac       if (sl->perms[i]) {
22135fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
22145fdea053SToby Isaac 
22159566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
22165fdea053SToby Isaac       }
22175fdea053SToby Isaac       if (sl->rots[i]) {
22185fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
22195fdea053SToby Isaac 
22209566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
22215fdea053SToby Isaac       }
22225fdea053SToby Isaac     }
22235fdea053SToby Isaac   }
22249566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients));
22259566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
22265fdea053SToby Isaac   sl->numStrata = 0;
22275fdea053SToby Isaac   PetscFunctionReturn(0);
22285fdea053SToby Isaac }
22295fdea053SToby Isaac 
22305fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
22315fdea053SToby Isaac {
22325fdea053SToby Isaac   PetscFunctionBegin;
22339566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
22349566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
22355fdea053SToby Isaac   PetscFunctionReturn(0);
22365fdea053SToby Isaac }
22375fdea053SToby Isaac 
22385fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
22395fdea053SToby Isaac {
22405fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
22415fdea053SToby Isaac   PetscBool             isAscii;
22425fdea053SToby Isaac   DMLabel               label = sl->label;
2243d67d17b1SMatthew G. Knepley   const char           *name;
22445fdea053SToby Isaac 
22455fdea053SToby Isaac   PetscFunctionBegin;
22469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii));
22475fdea053SToby Isaac   if (isAscii) {
22485fdea053SToby Isaac     PetscInt          i, j, k;
22495fdea053SToby Isaac     PetscViewerFormat format;
22505fdea053SToby Isaac 
22519566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer,&format));
22525fdea053SToby Isaac     if (label) {
22539566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer,&format));
22545fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22559566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
22569566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
22579566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
22585fdea053SToby Isaac       } else {
22599566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
22609566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name));
22615fdea053SToby Isaac       }
22625fdea053SToby Isaac     } else {
22639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
22645fdea053SToby Isaac     }
22659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
22665fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
22675fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
22685fdea053SToby Isaac 
22695fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
22709566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point): no symmetries\n", value, sl->sizes[i]));
22715fdea053SToby Isaac       } else {
22729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point):\n", value, sl->sizes[i]));
22739566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
22749566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%D, %D)\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
22755fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22769566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
22775fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22785fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
22799566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %D: identity\n",j));
22805fdea053SToby Isaac             } else {
22815fdea053SToby Isaac               PetscInt tab;
22825fdea053SToby Isaac 
22839566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %D:\n",j));
22849566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
22859566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer,&tab));
22865fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
22879566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"Permutation:"));
22889566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,0));
22899566063dSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %D",sl->perms[i][j][k]));
22909566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
22919566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,tab));
22925fdea053SToby Isaac               }
22935fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
22949566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"Rotations:  "));
22959566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,0));
22965fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
22979566063dSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %+f+i*%+f",PetscRealPart(sl->rots[i][j][k]),PetscImaginaryPart(sl->rots[i][j][k])));
22985fdea053SToby Isaac #else
22999566063dSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %+f",sl->rots[i][j][k]));
23005fdea053SToby Isaac #endif
23019566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
23029566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,tab));
23035fdea053SToby Isaac               }
23049566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
23055fdea053SToby Isaac             }
23065fdea053SToby Isaac           }
23079566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
23085fdea053SToby Isaac         }
23099566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
23105fdea053SToby Isaac       }
23115fdea053SToby Isaac     }
23129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
23135fdea053SToby Isaac   }
23145fdea053SToby Isaac   PetscFunctionReturn(0);
23155fdea053SToby Isaac }
23165fdea053SToby Isaac 
23175fdea053SToby Isaac /*@
23185fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
23195fdea053SToby Isaac 
23205fdea053SToby Isaac   Logically collective on sym
23215fdea053SToby Isaac 
23225fdea053SToby Isaac   Input parameters:
23235fdea053SToby Isaac + sym - the section symmetries
23245fdea053SToby Isaac - label - the DMLabel describing the types of points
23255fdea053SToby Isaac 
23265fdea053SToby Isaac   Level: developer:
23275fdea053SToby Isaac 
23285fdea053SToby Isaac .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreateLabel(), PetscSectionGetPointSyms()
23295fdea053SToby Isaac @*/
23305fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
23315fdea053SToby Isaac {
23325fdea053SToby Isaac   PetscSectionSym_Label *sl;
23335fdea053SToby Isaac 
23345fdea053SToby Isaac   PetscFunctionBegin;
23355fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
23365fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
23379566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
23385fdea053SToby Isaac   if (label) {
23395fdea053SToby Isaac     sl->label = label;
23409566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) label));
23419566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label,&sl->numStrata));
23429566063dSJacob 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));
23439566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode)));
23449566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt)));
23459566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **)));
23469566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **)));
23479566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2])));
23485fdea053SToby Isaac   }
23495fdea053SToby Isaac   PetscFunctionReturn(0);
23505fdea053SToby Isaac }
23515fdea053SToby Isaac 
23525fdea053SToby Isaac /*@C
2353b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2354b004864fSMatthew G. Knepley 
2355b004864fSMatthew G. Knepley   Logically collective on sym
2356b004864fSMatthew G. Knepley 
2357b004864fSMatthew G. Knepley   Input Parameters:
2358b004864fSMatthew G. Knepley + sym       - the section symmetries
2359b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2360b004864fSMatthew G. Knepley 
2361b004864fSMatthew G. Knepley   Output Parameters:
2362b004864fSMatthew G. Knepley + size      - the number of dofs for points in the stratum of the label
2363b004864fSMatthew G. Knepley . minOrient - the smallest orientation for a point in this stratum
2364b004864fSMatthew G. Knepley . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2365b004864fSMatthew G. Knepley . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2366b004864fSMatthew 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
2367b004864fSMatthew G. Knepley 
2368b004864fSMatthew G. Knepley   Level: developer
2369b004864fSMatthew G. Knepley 
2370b004864fSMatthew G. Knepley .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
2371b004864fSMatthew G. Knepley @*/
2372b004864fSMatthew G. Knepley PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2373b004864fSMatthew G. Knepley {
2374b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2375b004864fSMatthew G. Knepley   const char            *name;
2376b004864fSMatthew G. Knepley   PetscInt               i;
2377b004864fSMatthew G. Knepley 
2378b004864fSMatthew G. Knepley   PetscFunctionBegin;
2379b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
2380b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *) sym->data;
2381b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2382b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2383b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2384b004864fSMatthew G. Knepley 
2385b004864fSMatthew G. Knepley     if (stratum == value) break;
2386b004864fSMatthew G. Knepley   }
23879566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
2388b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
2389b004864fSMatthew G. Knepley   if (size)      {PetscValidIntPointer(size, 3);      *size      = sl->sizes[i];}
2390b004864fSMatthew G. Knepley   if (minOrient) {PetscValidIntPointer(minOrient, 4); *minOrient = sl->minMaxOrients[i][0];}
2391b004864fSMatthew G. Knepley   if (maxOrient) {PetscValidIntPointer(maxOrient, 5); *maxOrient = sl->minMaxOrients[i][1];}
2392b004864fSMatthew G. Knepley   if (perms)     {PetscValidPointer(perms, 6);        *perms     = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;}
2393b004864fSMatthew G. Knepley   if (rots)      {PetscValidPointer(rots, 7);         *rots      = sl->rots[i]  ? &sl->rots[i][sl->minMaxOrients[i][0]]  : NULL;}
2394b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2395b004864fSMatthew G. Knepley }
2396b004864fSMatthew G. Knepley 
2397b004864fSMatthew G. Knepley /*@C
23985fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
23995fdea053SToby Isaac 
24005b5e7992SMatthew G. Knepley   Logically collective on sym
24015fdea053SToby Isaac 
24025fdea053SToby Isaac   InputParameters:
24035b5e7992SMatthew G. Knepley + sym       - the section symmetries
24045fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
24055fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
24065fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
24075fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
24085fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
24095fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2410a2b725a8SWilliam 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
24115fdea053SToby Isaac 
24125fdea053SToby Isaac   Level: developer
24135fdea053SToby Isaac 
2414b004864fSMatthew G. Knepley .seealso: PetscSectionSymLabelGetStratum(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
24155fdea053SToby Isaac @*/
24165fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
24175fdea053SToby Isaac {
24185fdea053SToby Isaac   PetscSectionSym_Label *sl;
2419d67d17b1SMatthew G. Knepley   const char            *name;
2420d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
24215fdea053SToby Isaac 
24225fdea053SToby Isaac   PetscFunctionBegin;
24235fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
24245fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
2425b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
24265fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
24275fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
24285fdea053SToby Isaac 
24295fdea053SToby Isaac     if (stratum == value) break;
24305fdea053SToby Isaac   }
24319566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
2432b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %D not found in label %s", stratum, name);
24335fdea053SToby Isaac   sl->sizes[i] = size;
24345fdea053SToby Isaac   sl->modes[i] = mode;
24355fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
24365fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
24375fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
24385fdea053SToby Isaac     if (perms) {
24395fdea053SToby Isaac       PetscInt    **ownPerms;
24405fdea053SToby Isaac 
24419566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient,&ownPerms));
24425fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
24435fdea053SToby Isaac         if (perms[j]) {
24449566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size,&ownPerms[j]));
24455fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
24465fdea053SToby Isaac         }
24475fdea053SToby Isaac       }
24485fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
24495fdea053SToby Isaac     }
24505fdea053SToby Isaac     if (rots) {
24515fdea053SToby Isaac       PetscScalar **ownRots;
24525fdea053SToby Isaac 
24539566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient,&ownRots));
24545fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
24555fdea053SToby Isaac         if (rots[j]) {
24569566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size,&ownRots[j]));
24575fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
24585fdea053SToby Isaac         }
24595fdea053SToby Isaac       }
24605fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
24615fdea053SToby Isaac     }
24625fdea053SToby Isaac   } else {
24635fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
24645fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
24655fdea053SToby Isaac   }
24665fdea053SToby Isaac   PetscFunctionReturn(0);
24675fdea053SToby Isaac }
24685fdea053SToby Isaac 
24695fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
24705fdea053SToby Isaac {
24715fdea053SToby Isaac   PetscInt              i, j, numStrata;
24725fdea053SToby Isaac   PetscSectionSym_Label *sl;
24735fdea053SToby Isaac   DMLabel               label;
24745fdea053SToby Isaac 
24755fdea053SToby Isaac   PetscFunctionBegin;
24765fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
24775fdea053SToby Isaac   numStrata = sl->numStrata;
24785fdea053SToby Isaac   label     = sl->label;
24795fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
24805fdea053SToby Isaac     PetscInt point = points[2*i];
24815fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
24825fdea053SToby Isaac 
24835fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
24845fdea053SToby Isaac       if (label->validIS[j]) {
24855fdea053SToby Isaac         PetscInt k;
24865fdea053SToby Isaac 
24879566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j],point,&k));
24885fdea053SToby Isaac         if (k >= 0) break;
24895fdea053SToby Isaac       } else {
24905fdea053SToby Isaac         PetscBool has;
24915fdea053SToby Isaac 
24929566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
24935fdea053SToby Isaac         if (has) break;
24945fdea053SToby Isaac       }
24955fdea053SToby Isaac     }
249608401ef6SPierre Jolivet     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 %D orientation %D not in range [%D, %D) for stratum %D",point,ornt,sl->minMaxOrients[j][0],sl->minMaxOrients[j][1],j < numStrata ? label->stratumValues[j] : label->defaultValue);
24975fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
24985fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
24995fdea053SToby Isaac   }
25005fdea053SToby Isaac   PetscFunctionReturn(0);
25015fdea053SToby Isaac }
25025fdea053SToby Isaac 
2503b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2504b004864fSMatthew G. Knepley {
2505b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) nsym->data;
2506b004864fSMatthew G. Knepley   IS                     valIS;
2507b004864fSMatthew G. Knepley   const PetscInt        *values;
2508b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2509b004864fSMatthew G. Knepley 
2510b004864fSMatthew G. Knepley   PetscFunctionBegin;
25119566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
25129566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
25139566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2514b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2515b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2516b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2517b004864fSMatthew G. Knepley     const PetscInt    **perms;
2518b004864fSMatthew G. Knepley     const PetscScalar **rots;
2519b004864fSMatthew G. Knepley 
25209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym,  val, &size, &minOrient, &maxOrient, &perms, &rots));
25219566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val,  size,  minOrient,  maxOrient, PETSC_COPY_VALUES, perms, rots));
2522b004864fSMatthew G. Knepley   }
25239566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
2524b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2525b004864fSMatthew G. Knepley }
2526b004864fSMatthew G. Knepley 
2527b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2528b004864fSMatthew G. Knepley {
2529b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
2530b004864fSMatthew G. Knepley   DMLabel                dlabel;
2531b004864fSMatthew G. Knepley 
2532b004864fSMatthew G. Knepley   PetscFunctionBegin;
25339566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
25349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject) sym), dlabel, dsym));
25359566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
25369566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
2537b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2538b004864fSMatthew G. Knepley }
2539b004864fSMatthew G. Knepley 
25405fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
25415fdea053SToby Isaac {
25425fdea053SToby Isaac   PetscSectionSym_Label *sl;
25435fdea053SToby Isaac 
25445fdea053SToby Isaac   PetscFunctionBegin;
25459566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(sym,&sl));
25465fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2547b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2548b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
25495fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
25505fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
25515fdea053SToby Isaac   sym->data            = (void *) sl;
25525fdea053SToby Isaac   PetscFunctionReturn(0);
25535fdea053SToby Isaac }
25545fdea053SToby Isaac 
25555fdea053SToby Isaac /*@
25565fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
25575fdea053SToby Isaac 
25585fdea053SToby Isaac   Collective
25595fdea053SToby Isaac 
25605fdea053SToby Isaac   Input Parameters:
25615fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
25625fdea053SToby Isaac - label - the label defining the strata
25635fdea053SToby Isaac 
25645fdea053SToby Isaac   Output Parameters:
25655fdea053SToby Isaac . sym - the section symmetries
25665fdea053SToby Isaac 
25675fdea053SToby Isaac   Level: developer
25685fdea053SToby Isaac 
25695fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms()
25705fdea053SToby Isaac @*/
25715fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
25725fdea053SToby Isaac {
25735fdea053SToby Isaac   PetscFunctionBegin;
25749566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
25759566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm,sym));
25769566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL));
25779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym,label));
25785fdea053SToby Isaac   PetscFunctionReturn(0);
25795fdea053SToby Isaac }
2580