xref: /petsc/src/dm/label/dmlabel.c (revision cffad2c90811f2db9e7effa2a9b002d28afd4371)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h>   /*I      "petscdmlabel.h"   I*/
3ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h>   /*I      "petscsection.h"   I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5ea844a1aSMatthew Knepley #include <petscsection.h>
6c58f1c22SToby Isaac 
7c58f1c22SToby Isaac /*@C
8c58f1c22SToby Isaac   DMLabelCreate - Create a DMLabel object, which is a multimap
9c58f1c22SToby Isaac 
105b5e7992SMatthew G. Knepley   Collective
115b5e7992SMatthew G. Knepley 
12d67d17b1SMatthew G. Knepley   Input parameters:
13d67d17b1SMatthew G. Knepley + comm - The communicator, usually PETSC_COMM_SELF
14d67d17b1SMatthew G. Knepley - name - The label name
15c58f1c22SToby Isaac 
16c58f1c22SToby Isaac   Output parameter:
17c58f1c22SToby Isaac . label - The DMLabel
18c58f1c22SToby Isaac 
19c58f1c22SToby Isaac   Level: beginner
20c58f1c22SToby Isaac 
2105ab7a9fSVaclav Hapla   Notes:
2205ab7a9fSVaclav Hapla   The label name is actually usual PetscObject name.
2305ab7a9fSVaclav Hapla   One can get/set it with PetscObjectGetName()/PetscObjectSetName().
2405ab7a9fSVaclav Hapla 
25db781477SPatrick Sanan .seealso: `DMLabelDestroy()`
26c58f1c22SToby Isaac @*/
27d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
28c58f1c22SToby Isaac {
29c58f1c22SToby Isaac   PetscFunctionBegin;
30064a246eSJacob Faibussowitsch   PetscValidPointer(label,3);
319566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
32c58f1c22SToby Isaac 
339566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(*label,DMLABEL_CLASSID,"DMLabel","DMLabel","DM",comm,DMLabelDestroy,DMLabelView));
34d67d17b1SMatthew G. Knepley 
35c58f1c22SToby Isaac   (*label)->numStrata      = 0;
365aa44df4SToby Isaac   (*label)->defaultValue   = -1;
37c58f1c22SToby Isaac   (*label)->stratumValues  = NULL;
38ad8374ffSToby Isaac   (*label)->validIS        = NULL;
39c58f1c22SToby Isaac   (*label)->stratumSizes   = NULL;
40c58f1c22SToby Isaac   (*label)->points         = NULL;
41c58f1c22SToby Isaac   (*label)->ht             = NULL;
42c58f1c22SToby Isaac   (*label)->pStart         = -1;
43c58f1c22SToby Isaac   (*label)->pEnd           = -1;
44c58f1c22SToby Isaac   (*label)->bt             = NULL;
459566063dSJacob Faibussowitsch   PetscCall(PetscHMapICreate(&(*label)->hmap));
469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *label, name));
47c58f1c22SToby Isaac   PetscFunctionReturn(0);
48c58f1c22SToby Isaac }
49c58f1c22SToby Isaac 
50c58f1c22SToby Isaac /*
51c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
52c58f1c22SToby Isaac 
535b5e7992SMatthew G. Knepley   Not collective
545b5e7992SMatthew G. Knepley 
55c58f1c22SToby Isaac   Input parameter:
56c58f1c22SToby Isaac + label - The DMLabel
57c58f1c22SToby Isaac - v - The stratum value
58c58f1c22SToby Isaac 
59c58f1c22SToby Isaac   Output parameter:
60c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
61c58f1c22SToby Isaac 
62c58f1c22SToby Isaac   Level: developer
63c58f1c22SToby Isaac 
64db781477SPatrick Sanan .seealso: `DMLabelCreate()`
65c58f1c22SToby Isaac */
66c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
67c58f1c22SToby Isaac {
68277ea44aSLisandro Dalcin   IS             is;
69b9907514SLisandro Dalcin   PetscInt       off = 0, *pointArray, p;
70c58f1c22SToby Isaac 
71b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
72c58f1c22SToby Isaac   PetscFunctionBegin;
731dca8a05SBarry Smith   PetscCheck(v >= 0 && v < label->numStrata,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeValid_Private", v);
749566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->stratumSizes[v], &pointArray));
769566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(label->ht[v], &off, pointArray));
779566063dSJacob Faibussowitsch   PetscCall(PetscHSetIClear(label->ht[v]));
789566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(label->stratumSizes[v], pointArray));
79c58f1c22SToby Isaac   if (label->bt) {
80c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
81ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
8263a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
839566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
84c58f1c22SToby Isaac     }
85c58f1c22SToby Isaac   }
86ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v]-1] == pointArray[0] + label->stratumSizes[v]-1) {
879566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
889566063dSJacob Faibussowitsch     PetscCall(PetscFree(pointArray));
89ba2698f1SMatthew G. Knepley   } else {
909566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
91ba2698f1SMatthew G. Knepley   }
929566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) is, "indices"));
93277ea44aSLisandro Dalcin   label->points[v]  = is;
94ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
959566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject) label));
96c58f1c22SToby Isaac   PetscFunctionReturn(0);
97c58f1c22SToby Isaac }
98c58f1c22SToby Isaac 
99c58f1c22SToby Isaac /*
100c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
101c58f1c22SToby Isaac 
1025b5e7992SMatthew G. Knepley   Not collective
1035b5e7992SMatthew G. Knepley 
104c58f1c22SToby Isaac   Input parameter:
105c58f1c22SToby Isaac . label - The DMLabel
106c58f1c22SToby Isaac 
107c58f1c22SToby Isaac   Output parameter:
108c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
109c58f1c22SToby Isaac 
110c58f1c22SToby Isaac   Level: developer
111c58f1c22SToby Isaac 
112db781477SPatrick Sanan .seealso: `DMLabelCreate()`
113c58f1c22SToby Isaac */
114c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
115c58f1c22SToby Isaac {
116c58f1c22SToby Isaac   PetscInt       v;
117c58f1c22SToby Isaac 
118c58f1c22SToby Isaac   PetscFunctionBegin;
119c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; v++) {
1209566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeValid_Private(label, v));
121c58f1c22SToby Isaac   }
122c58f1c22SToby Isaac   PetscFunctionReturn(0);
123c58f1c22SToby Isaac }
124c58f1c22SToby Isaac 
125c58f1c22SToby Isaac /*
126c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
127c58f1c22SToby Isaac 
1285b5e7992SMatthew G. Knepley   Not collective
1295b5e7992SMatthew G. Knepley 
130c58f1c22SToby Isaac   Input parameter:
131c58f1c22SToby Isaac + label - The DMLabel
132c58f1c22SToby Isaac - v - The stratum value
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Output parameter:
135c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
136c58f1c22SToby Isaac 
137c58f1c22SToby Isaac   Level: developer
138c58f1c22SToby Isaac 
139db781477SPatrick Sanan .seealso: `DMLabelCreate()`
140c58f1c22SToby Isaac */
141c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
142c58f1c22SToby Isaac {
143c58f1c22SToby Isaac   PetscInt       p;
144ad8374ffSToby Isaac   const PetscInt *points;
145c58f1c22SToby Isaac 
146b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
147c58f1c22SToby Isaac   PetscFunctionBegin;
1481dca8a05SBarry Smith   PetscCheck(v >= 0 && v < label->numStrata,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %" PetscInt_FMT " in DMLabelMakeInvalid_Private", v);
149ad8374ffSToby Isaac   if (label->points[v]) {
1509566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
151e8f14785SLisandro Dalcin     for (p = 0; p < label->stratumSizes[v]; ++p) {
1529566063dSJacob Faibussowitsch       PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
153e8f14785SLisandro Dalcin     }
1549566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v],&points));
1559566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&(label->points[v])));
156ad8374ffSToby Isaac   }
157ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
158c58f1c22SToby Isaac   PetscFunctionReturn(0);
159c58f1c22SToby Isaac }
160c58f1c22SToby Isaac 
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 
280db781477SPatrick Sanan .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 
304db781477SPatrick Sanan .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 
366db781477SPatrick Sanan .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));
39563a3b9bcSJacob Faibussowitsch     if (label->bt) PetscCall(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%" PetscInt_FMT ", %" PetscInt_FMT ")\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) {
40363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " (%" PetscInt_FMT ")\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 
424db781477SPatrick Sanan .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));
4361baa6e33SBarry Smith   if (iascii) PetscCall(DMLabelView_Ascii(label, viewer));
437c58f1c22SToby Isaac   PetscFunctionReturn(0);
438c58f1c22SToby Isaac }
439c58f1c22SToby Isaac 
44084f0b6dfSMatthew G. Knepley /*@
441d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
442d67d17b1SMatthew G. Knepley 
4435b5e7992SMatthew G. Knepley   Not collective
4445b5e7992SMatthew G. Knepley 
445d67d17b1SMatthew G. Knepley   Input Parameter:
446d67d17b1SMatthew G. Knepley . label - The DMLabel
447d67d17b1SMatthew G. Knepley 
448d67d17b1SMatthew G. Knepley   Level: beginner
449d67d17b1SMatthew G. Knepley 
450db781477SPatrick Sanan .seealso: `DMLabelDestroy()`, `DMLabelCreate()`
451d67d17b1SMatthew G. Knepley @*/
452d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelReset(DMLabel label)
453d67d17b1SMatthew G. Knepley {
454d67d17b1SMatthew G. Knepley   PetscInt       v;
455d67d17b1SMatthew G. Knepley 
456d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
457d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
458d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
4599566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&label->ht[v]));
4609566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
461d67d17b1SMatthew G. Knepley   }
462b9907514SLisandro Dalcin   label->numStrata = 0;
4639566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumValues));
4649566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->stratumSizes));
4659566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->ht));
4669566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->points));
4679566063dSJacob Faibussowitsch   PetscCall(PetscFree(label->validIS));
468f9244615SMatthew G. Knepley   label->stratumValues = NULL;
469f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
470f9244615SMatthew G. Knepley   label->ht            = NULL;
471f9244615SMatthew G. Knepley   label->points        = NULL;
472f9244615SMatthew G. Knepley   label->validIS       = NULL;
4739566063dSJacob Faibussowitsch   PetscCall(PetscHMapIReset(label->hmap));
474b9907514SLisandro Dalcin   label->pStart = -1;
475b9907514SLisandro Dalcin   label->pEnd   = -1;
4769566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
477d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
478d67d17b1SMatthew G. Knepley }
479d67d17b1SMatthew G. Knepley 
480d67d17b1SMatthew G. Knepley /*@
48184f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
48284f0b6dfSMatthew G. Knepley 
4835b5e7992SMatthew G. Knepley   Collective on label
4845b5e7992SMatthew G. Knepley 
48584f0b6dfSMatthew G. Knepley   Input Parameter:
48684f0b6dfSMatthew G. Knepley . label - The DMLabel
48784f0b6dfSMatthew G. Knepley 
48884f0b6dfSMatthew G. Knepley   Level: beginner
48984f0b6dfSMatthew G. Knepley 
490db781477SPatrick Sanan .seealso: `DMLabelReset()`, `DMLabelCreate()`
49184f0b6dfSMatthew G. Knepley @*/
492c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
493c58f1c22SToby Isaac {
494c58f1c22SToby Isaac   PetscFunctionBegin;
495d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
496d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1);
497b9907514SLisandro Dalcin   if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);}
4989566063dSJacob Faibussowitsch   PetscCall(DMLabelReset(*label));
4999566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*label)->hmap));
5009566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(label));
501c58f1c22SToby Isaac   PetscFunctionReturn(0);
502c58f1c22SToby Isaac }
503c58f1c22SToby Isaac 
50484f0b6dfSMatthew G. Knepley /*@
50584f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
50684f0b6dfSMatthew G. Knepley 
5075b5e7992SMatthew G. Knepley   Collective on label
5085b5e7992SMatthew G. Knepley 
50984f0b6dfSMatthew G. Knepley   Input Parameter:
51084f0b6dfSMatthew G. Knepley . label - The DMLabel
51184f0b6dfSMatthew G. Knepley 
51284f0b6dfSMatthew G. Knepley   Output Parameter:
51384f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
51484f0b6dfSMatthew G. Knepley 
51584f0b6dfSMatthew G. Knepley   Level: intermediate
51684f0b6dfSMatthew G. Knepley 
517db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelDestroy()`
51884f0b6dfSMatthew G. Knepley @*/
519c58f1c22SToby Isaac PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
520c58f1c22SToby Isaac {
521d67d17b1SMatthew G. Knepley   const char    *name;
522ad8374ffSToby Isaac   PetscInt       v;
523c58f1c22SToby Isaac 
524c58f1c22SToby Isaac   PetscFunctionBegin;
525d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5269566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
5279566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) label, &name));
5289566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew));
529c58f1c22SToby Isaac 
530c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5315aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->ht));
5359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->points));
5369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
537c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
5389566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelnew)->ht[v]));
539c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
540c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
5419566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) (label->points[v])));
542ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
543b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
544c58f1c22SToby Isaac   }
5459566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDestroy(&(*labelnew)->hmap));
5469566063dSJacob Faibussowitsch   PetscCall(PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap));
547c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
548c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
549c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
550c58f1c22SToby Isaac   PetscFunctionReturn(0);
551c58f1c22SToby Isaac }
552c58f1c22SToby Isaac 
553609dae6eSVaclav Hapla /*@C
554609dae6eSVaclav Hapla   DMLabelCompare - Compare two DMLabel objects
555609dae6eSVaclav Hapla 
5565efe38ccSVaclav Hapla   Collective on comm
557609dae6eSVaclav Hapla 
558609dae6eSVaclav Hapla   Input Parameters:
559f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
560f1a722f8SMatthew G. Knepley . l0 - First DMLabel
561609dae6eSVaclav Hapla - l1 - Second DMLabel
562609dae6eSVaclav Hapla 
563609dae6eSVaclav Hapla   Output Parameters
5645efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
5655efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
566609dae6eSVaclav Hapla 
567609dae6eSVaclav Hapla   Level: intermediate
568609dae6eSVaclav Hapla 
569609dae6eSVaclav Hapla   Notes:
5705efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
5715efe38ccSVaclav Hapla   If it is passed as NULL and difference is found, an error is thrown on all processes.
5725efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
573609dae6eSVaclav Hapla 
5745efe38ccSVaclav Hapla   The output message is set independently on each rank.
5755efe38ccSVaclav Hapla   It is set to NULL if no difference was found on the current rank. It must be freed by user.
5765efe38ccSVaclav Hapla   If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
5775efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
578609dae6eSVaclav Hapla 
579609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
580609dae6eSVaclav Hapla 
5815efe38ccSVaclav Hapla   The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
5825efe38ccSVaclav Hapla 
583609dae6eSVaclav Hapla   Fortran Notes:
584609dae6eSVaclav Hapla   This function is currently not available from Fortran.
585609dae6eSVaclav Hapla 
586db781477SPatrick Sanan .seealso: `DMCompareLabels()`, `DMLabelGetNumValues()`, `DMLabelGetDefaultValue()`, `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelGetStratumIS()`
587609dae6eSVaclav Hapla @*/
5885efe38ccSVaclav Hapla PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
589609dae6eSVaclav Hapla {
590609dae6eSVaclav Hapla   const char     *name0, *name1;
591609dae6eSVaclav Hapla   char            msg[PETSC_MAX_PATH_LEN] = "";
5925efe38ccSVaclav Hapla   PetscBool       eq;
5935efe38ccSVaclav Hapla   PetscMPIInt     rank;
594609dae6eSVaclav Hapla 
595609dae6eSVaclav Hapla   PetscFunctionBegin;
5965efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
5975efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
5985efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
5995efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
6009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l0, &name0));
6029566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)l1, &name1));
603609dae6eSVaclav Hapla   {
604609dae6eSVaclav Hapla     PetscInt v0, v1;
605609dae6eSVaclav Hapla 
6069566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l0, &v0));
6079566063dSJacob Faibussowitsch     PetscCall(DMLabelGetDefaultValue(l1, &v1));
6085efe38ccSVaclav Hapla     eq = (PetscBool) (v0 == v1);
6095efe38ccSVaclav Hapla     if (!eq) {
61063a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Default value of DMLabel l0 \"%s\" = %" PetscInt_FMT " != %" PetscInt_FMT " = Default value of DMLabel l1 \"%s\"", name0, v0, v1, name1));
611609dae6eSVaclav Hapla     }
6129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6135efe38ccSVaclav Hapla     if (!eq) goto finish;
614609dae6eSVaclav Hapla   }
615609dae6eSVaclav Hapla   {
616609dae6eSVaclav Hapla     IS              is0, is1;
617609dae6eSVaclav Hapla 
6189566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6199566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6209566063dSJacob Faibussowitsch     PetscCall(ISEqual(is0, is1, &eq));
6219566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is0));
6229566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
6235efe38ccSVaclav Hapla     if (!eq) {
6249566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
625609dae6eSVaclav Hapla     }
6269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6275efe38ccSVaclav Hapla     if (!eq) goto finish;
628609dae6eSVaclav Hapla   }
629609dae6eSVaclav Hapla   {
630609dae6eSVaclav Hapla     PetscInt i, nValues;
631609dae6eSVaclav Hapla 
6329566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(l0, &nValues));
633609dae6eSVaclav Hapla     for (i=0; i<nValues; i++) {
634609dae6eSVaclav Hapla       const PetscInt  v = l0->stratumValues[i];
635609dae6eSVaclav Hapla       PetscInt        n;
636609dae6eSVaclav Hapla       IS              is0, is1;
637609dae6eSVaclav Hapla 
6389566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumSize_Private(l0, i, &n));
639609dae6eSVaclav Hapla       if (!n) continue;
6409566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l0, v, &is0));
6419566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(l1, v, &is1));
6429566063dSJacob Faibussowitsch       PetscCall(ISEqualUnsorted(is0, is1, &eq));
6439566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is0));
6449566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is1));
6455efe38ccSVaclav Hapla       if (!eq) {
64663a3b9bcSJacob Faibussowitsch         PetscCall(PetscSNPrintf(msg, sizeof(msg), "Stratum #%" PetscInt_FMT " with value %" PetscInt_FMT " contains different points in DMLabel l0 \"%s\" and DMLabel l1 \"%s\"", i, v, name0, name1));
6475efe38ccSVaclav Hapla         break;
648609dae6eSVaclav Hapla       }
649609dae6eSVaclav Hapla     }
6509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
651609dae6eSVaclav Hapla   }
652609dae6eSVaclav Hapla finish:
6535efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
654609dae6eSVaclav Hapla   if (message) {
655609dae6eSVaclav Hapla     *message = NULL;
656609dae6eSVaclav Hapla     if (msg[0]) {
6579566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(msg, message));
658609dae6eSVaclav Hapla     }
6595efe38ccSVaclav Hapla   } else {
6605efe38ccSVaclav Hapla     if (msg[0]) {
6619566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
662609dae6eSVaclav Hapla     }
6639566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
6645efe38ccSVaclav Hapla   }
6655efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
6665efe38ccSVaclav Hapla   if (equal) *equal = eq;
66763a3b9bcSJacob Faibussowitsch   else PetscCheck(eq,comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal",name0,name1);
668609dae6eSVaclav Hapla   PetscFunctionReturn(0);
669609dae6eSVaclav Hapla }
670609dae6eSVaclav Hapla 
671c6a43d28SMatthew G. Knepley /*@
672c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
673c6a43d28SMatthew G. Knepley 
6745b5e7992SMatthew G. Knepley   Not collective
6755b5e7992SMatthew G. Knepley 
676c6a43d28SMatthew G. Knepley   Input Parameter:
677c6a43d28SMatthew G. Knepley . label  - The DMLabel
678c6a43d28SMatthew G. Knepley 
679c6a43d28SMatthew G. Knepley   Level: intermediate
680c6a43d28SMatthew G. Knepley 
681db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
682c6a43d28SMatthew G. Knepley @*/
683c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
684c6a43d28SMatthew G. Knepley {
685c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
686c6a43d28SMatthew G. Knepley 
687c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
688c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6899566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
690c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
691c6a43d28SMatthew G. Knepley     const PetscInt *points;
692c6a43d28SMatthew G. Knepley     PetscInt       i;
693c6a43d28SMatthew G. Knepley 
6949566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
695c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
696c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
697c6a43d28SMatthew G. Knepley 
698c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
699c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
700c6a43d28SMatthew G. Knepley     }
7019566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
702c6a43d28SMatthew G. Knepley   }
703c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
704c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7059566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
706c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
707c6a43d28SMatthew G. Knepley }
708c6a43d28SMatthew G. Knepley 
709c6a43d28SMatthew G. Knepley /*@
710c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
711c6a43d28SMatthew G. Knepley 
7125b5e7992SMatthew G. Knepley   Not collective
7135b5e7992SMatthew G. Knepley 
714c6a43d28SMatthew G. Knepley   Input Parameters:
715c6a43d28SMatthew G. Knepley + label  - The DMLabel
716c6a43d28SMatthew G. Knepley . pStart - The smallest point
717c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
718c6a43d28SMatthew G. Knepley 
719c6a43d28SMatthew G. Knepley   Level: intermediate
720c6a43d28SMatthew G. Knepley 
721db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelComputeIndex()`, `DMLabelDestroyIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
722c6a43d28SMatthew G. Knepley @*/
723c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
724c58f1c22SToby Isaac {
725c58f1c22SToby Isaac   PetscInt       v;
726c58f1c22SToby Isaac 
727c58f1c22SToby Isaac   PetscFunctionBegin;
728d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7299566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
7309566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
731c58f1c22SToby Isaac   label->pStart = pStart;
732c58f1c22SToby Isaac   label->pEnd   = pEnd;
733c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7349566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(pEnd - pStart, &label->bt));
735c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
736ad8374ffSToby Isaac     const PetscInt *points;
737c58f1c22SToby Isaac     PetscInt       i;
738c58f1c22SToby Isaac 
7399566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(label->points[v], &points));
740c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
741ad8374ffSToby Isaac       const PetscInt point = points[i];
742c58f1c22SToby Isaac 
74363a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < pStart) && !(point >= pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd);
7449566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - pStart));
745c58f1c22SToby Isaac     }
7469566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(label->points[v], &points));
747c58f1c22SToby Isaac   }
748c58f1c22SToby Isaac   PetscFunctionReturn(0);
749c58f1c22SToby Isaac }
750c58f1c22SToby Isaac 
751c6a43d28SMatthew G. Knepley /*@
752c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
753c6a43d28SMatthew G. Knepley 
7545b5e7992SMatthew G. Knepley   Not collective
7555b5e7992SMatthew G. Knepley 
756c6a43d28SMatthew G. Knepley   Input Parameter:
757c6a43d28SMatthew G. Knepley . label - the DMLabel
758c6a43d28SMatthew G. Knepley 
759c6a43d28SMatthew G. Knepley   Level: intermediate
760c6a43d28SMatthew G. Knepley 
761db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
762c6a43d28SMatthew G. Knepley @*/
763c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
764c58f1c22SToby Isaac {
765c58f1c22SToby Isaac   PetscFunctionBegin;
766d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
767c58f1c22SToby Isaac   label->pStart = -1;
768c58f1c22SToby Isaac   label->pEnd   = -1;
7699566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&label->bt));
770c58f1c22SToby Isaac   PetscFunctionReturn(0);
771c58f1c22SToby Isaac }
772c58f1c22SToby Isaac 
773c58f1c22SToby Isaac /*@
774c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
775c6a43d28SMatthew G. Knepley 
7765b5e7992SMatthew G. Knepley   Not collective
7775b5e7992SMatthew G. Knepley 
778c6a43d28SMatthew G. Knepley   Input Parameter:
779c6a43d28SMatthew G. Knepley . label - the DMLabel
780c6a43d28SMatthew G. Knepley 
781c6a43d28SMatthew G. Knepley   Output Parameters:
782c6a43d28SMatthew G. Knepley + pStart - The smallest point
783c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
784c6a43d28SMatthew G. Knepley 
785c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
786c6a43d28SMatthew G. Knepley 
787c6a43d28SMatthew G. Knepley   Level: intermediate
788c6a43d28SMatthew G. Knepley 
789db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
790c6a43d28SMatthew G. Knepley @*/
791c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
792c6a43d28SMatthew G. Knepley {
793c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
794c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7959566063dSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) PetscCall(DMLabelComputeIndex(label));
796c6a43d28SMatthew G. Knepley   if (pStart) {
797534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
798c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
799c6a43d28SMatthew G. Knepley   }
800c6a43d28SMatthew G. Knepley   if (pEnd) {
801534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
802c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
803c6a43d28SMatthew G. Knepley   }
804c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
805c6a43d28SMatthew G. Knepley }
806c6a43d28SMatthew G. Knepley 
807c6a43d28SMatthew G. Knepley /*@
808c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
809c58f1c22SToby Isaac 
8105b5e7992SMatthew G. Knepley   Not collective
8115b5e7992SMatthew G. Knepley 
812c58f1c22SToby Isaac   Input Parameters:
813c58f1c22SToby Isaac + label - the DMLabel
814c58f1c22SToby Isaac - value - the value
815c58f1c22SToby Isaac 
816c58f1c22SToby Isaac   Output Parameter:
817c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
818c58f1c22SToby Isaac 
819c58f1c22SToby Isaac   Level: developer
820c58f1c22SToby Isaac 
821db781477SPatrick Sanan .seealso: `DMLabelHasPoint()`, `DMLabelGetValue()`, `DMLabelSetValue()`
822c58f1c22SToby Isaac @*/
823c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
824c58f1c22SToby Isaac {
825c58f1c22SToby Isaac   PetscInt v;
826c58f1c22SToby Isaac 
827c58f1c22SToby Isaac   PetscFunctionBegin;
828d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
829534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8309566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
8310c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
832c58f1c22SToby Isaac   PetscFunctionReturn(0);
833c58f1c22SToby Isaac }
834c58f1c22SToby Isaac 
835c58f1c22SToby Isaac /*@
836c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
837c58f1c22SToby Isaac 
8385b5e7992SMatthew G. Knepley   Not collective
8395b5e7992SMatthew G. Knepley 
840c58f1c22SToby Isaac   Input Parameters:
841c58f1c22SToby Isaac + label - the DMLabel
842c58f1c22SToby Isaac - point - the point
843c58f1c22SToby Isaac 
844c58f1c22SToby Isaac   Output Parameter:
845c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
846c58f1c22SToby Isaac 
847c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
848c58f1c22SToby Isaac 
849c58f1c22SToby Isaac   Level: developer
850c58f1c22SToby Isaac 
851db781477SPatrick Sanan .seealso: `DMLabelCreateIndex()`, `DMLabelGetValue()`, `DMLabelSetValue()`
852c58f1c22SToby Isaac @*/
853c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
854c58f1c22SToby Isaac {
855c58f1c22SToby Isaac   PetscFunctionBeginHot;
856d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
857534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8589566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
85976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
86028b400f6SJacob Faibussowitsch     PetscCheck(label->bt,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
86163a3b9bcSJacob Faibussowitsch     PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
86276bd3646SJed Brown   }
863c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
864c58f1c22SToby Isaac   PetscFunctionReturn(0);
865c58f1c22SToby Isaac }
866c58f1c22SToby Isaac 
867c58f1c22SToby Isaac /*@
868c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
869c58f1c22SToby Isaac 
8705b5e7992SMatthew G. Knepley   Not collective
8715b5e7992SMatthew G. Knepley 
872c58f1c22SToby Isaac   Input Parameters:
873c58f1c22SToby Isaac + label - the DMLabel
874c58f1c22SToby Isaac . value - the stratum value
875c58f1c22SToby Isaac - point - the point
876c58f1c22SToby Isaac 
877c58f1c22SToby Isaac   Output Parameter:
878c58f1c22SToby Isaac . contains - true if the stratum contains the point
879c58f1c22SToby Isaac 
880c58f1c22SToby Isaac   Level: intermediate
881c58f1c22SToby Isaac 
882db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`
883c58f1c22SToby Isaac @*/
884c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
885c58f1c22SToby Isaac {
8860c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
887d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
888534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
889*cffad2c9SToby Isaac   if (value == label->defaultValue) {
890*cffad2c9SToby Isaac     PetscInt pointVal;
8910c3c4a36SLisandro Dalcin 
892*cffad2c9SToby Isaac     PetscCall(DMLabelGetValue(label, point, &pointVal));
893*cffad2c9SToby Isaac     *contains = (PetscBool) (pointVal == value);
894*cffad2c9SToby Isaac   } else {
895*cffad2c9SToby Isaac     PetscInt v;
896*cffad2c9SToby Isaac 
897*cffad2c9SToby Isaac     PetscCall(DMLabelLookupStratum(label, value, &v));
898*cffad2c9SToby Isaac     if (v >= 0) {
899ad8374ffSToby Isaac       if (label->validIS[v]) {
900c58f1c22SToby Isaac         PetscInt i;
901c58f1c22SToby Isaac 
9029566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[v], point, &i));
903*cffad2c9SToby Isaac         *contains = (PetscBool) (i >= 0);
904c58f1c22SToby Isaac       } else {
905*cffad2c9SToby Isaac         PetscCall(PetscHSetIHas(label->ht[v], point, contains));
906*cffad2c9SToby Isaac       }
907*cffad2c9SToby Isaac     } else { // value is not present
908*cffad2c9SToby Isaac       *contains = PETSC_FALSE;
909*cffad2c9SToby Isaac     }
910c58f1c22SToby Isaac   }
911c58f1c22SToby Isaac   PetscFunctionReturn(0);
912c58f1c22SToby Isaac }
913c58f1c22SToby Isaac 
91484f0b6dfSMatthew G. Knepley /*@
9155aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9165aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9175aa44df4SToby Isaac 
9185b5e7992SMatthew G. Knepley   Not collective
9195b5e7992SMatthew G. Knepley 
9205aa44df4SToby Isaac   Input parameter:
9215aa44df4SToby Isaac . label - a DMLabel object
9225aa44df4SToby Isaac 
9235aa44df4SToby Isaac   Output parameter:
9245aa44df4SToby Isaac . defaultValue - the default value
9255aa44df4SToby Isaac 
9265aa44df4SToby Isaac   Level: beginner
9275aa44df4SToby Isaac 
928db781477SPatrick Sanan .seealso: `DMLabelSetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
92984f0b6dfSMatthew G. Knepley @*/
9305aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
9315aa44df4SToby Isaac {
9325aa44df4SToby Isaac   PetscFunctionBegin;
933d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9345aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9355aa44df4SToby Isaac   PetscFunctionReturn(0);
9365aa44df4SToby Isaac }
9375aa44df4SToby Isaac 
93884f0b6dfSMatthew G. Knepley /*@
9395aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9405aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9415aa44df4SToby Isaac 
9425b5e7992SMatthew G. Knepley   Not collective
9435b5e7992SMatthew G. Knepley 
9445aa44df4SToby Isaac   Input parameter:
9455aa44df4SToby Isaac . label - a DMLabel object
9465aa44df4SToby Isaac 
9475aa44df4SToby Isaac   Output parameter:
9485aa44df4SToby Isaac . defaultValue - the default value
9495aa44df4SToby Isaac 
9505aa44df4SToby Isaac   Level: beginner
9515aa44df4SToby Isaac 
952db781477SPatrick Sanan .seealso: `DMLabelGetDefaultValue()`, `DMLabelGetValue()`, `DMLabelSetValue()`
95384f0b6dfSMatthew G. Knepley @*/
9545aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
9555aa44df4SToby Isaac {
9565aa44df4SToby Isaac   PetscFunctionBegin;
957d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9585aa44df4SToby Isaac   label->defaultValue = defaultValue;
9595aa44df4SToby Isaac   PetscFunctionReturn(0);
9605aa44df4SToby Isaac }
9615aa44df4SToby Isaac 
962c58f1c22SToby Isaac /*@
9635aa44df4SToby 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())
964c58f1c22SToby Isaac 
9655b5e7992SMatthew G. Knepley   Not collective
9665b5e7992SMatthew G. Knepley 
967c58f1c22SToby Isaac   Input Parameters:
968c58f1c22SToby Isaac + label - the DMLabel
969c58f1c22SToby Isaac - point - the point
970c58f1c22SToby Isaac 
971c58f1c22SToby Isaac   Output Parameter:
9728e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
973c58f1c22SToby Isaac 
974*cffad2c9SToby Isaac   Note: a label may assign multiple values to a point.  No guarantees are made about which value is returned in that case.  Use `DMLabelStratumHasPoint()` to check for inclusion in a specific value stratum.
975*cffad2c9SToby Isaac 
976c58f1c22SToby Isaac   Level: intermediate
977c58f1c22SToby Isaac 
978db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
979c58f1c22SToby Isaac @*/
980c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
981c58f1c22SToby Isaac {
982c58f1c22SToby Isaac   PetscInt       v;
983c58f1c22SToby Isaac 
9840c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
985d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
986dadcf809SJacob Faibussowitsch   PetscValidIntPointer(value, 3);
9875aa44df4SToby Isaac   *value = label->defaultValue;
988c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
989ad8374ffSToby Isaac     if (label->validIS[v]) {
990c58f1c22SToby Isaac       PetscInt i;
991c58f1c22SToby Isaac 
9929566063dSJacob Faibussowitsch       PetscCall(ISLocate(label->points[v], point, &i));
993c58f1c22SToby Isaac       if (i >= 0) {
994c58f1c22SToby Isaac         *value = label->stratumValues[v];
995c58f1c22SToby Isaac         break;
996c58f1c22SToby Isaac       }
997c58f1c22SToby Isaac     } else {
998c58f1c22SToby Isaac       PetscBool has;
999c58f1c22SToby Isaac 
10009566063dSJacob Faibussowitsch       PetscCall(PetscHSetIHas(label->ht[v], point, &has));
1001c58f1c22SToby Isaac       if (has) {
1002c58f1c22SToby Isaac         *value = label->stratumValues[v];
1003c58f1c22SToby Isaac         break;
1004c58f1c22SToby Isaac       }
1005c58f1c22SToby Isaac     }
1006c58f1c22SToby Isaac   }
1007c58f1c22SToby Isaac   PetscFunctionReturn(0);
1008c58f1c22SToby Isaac }
1009c58f1c22SToby Isaac 
1010c58f1c22SToby Isaac /*@
1011367003a6SStefano 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.
1012c58f1c22SToby Isaac 
10135b5e7992SMatthew G. Knepley   Not collective
10145b5e7992SMatthew G. Knepley 
1015c58f1c22SToby Isaac   Input Parameters:
1016c58f1c22SToby Isaac + label - the DMLabel
1017c58f1c22SToby Isaac . point - the point
1018c58f1c22SToby Isaac - value - The point value
1019c58f1c22SToby Isaac 
1020c58f1c22SToby Isaac   Level: intermediate
1021c58f1c22SToby Isaac 
1022db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelClearValue()`, `DMLabelGetDefaultValue()`, `DMLabelSetDefaultValue()`
1023c58f1c22SToby Isaac @*/
1024c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1025c58f1c22SToby Isaac {
1026c58f1c22SToby Isaac   PetscInt       v;
1027c58f1c22SToby Isaac 
1028c58f1c22SToby Isaac   PetscFunctionBegin;
1029d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10300c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10315aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
10329566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
1033c58f1c22SToby Isaac   /* Set key */
10349566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10359566063dSJacob Faibussowitsch   PetscCall(PetscHSetIAdd(label->ht[v], point));
1036c58f1c22SToby Isaac   PetscFunctionReturn(0);
1037c58f1c22SToby Isaac }
1038c58f1c22SToby Isaac 
1039c58f1c22SToby Isaac /*@
1040c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1041c58f1c22SToby Isaac 
10425b5e7992SMatthew G. Knepley   Not collective
10435b5e7992SMatthew G. Knepley 
1044c58f1c22SToby Isaac   Input Parameters:
1045c58f1c22SToby Isaac + label - the DMLabel
1046c58f1c22SToby Isaac . point - the point
1047c58f1c22SToby Isaac - value - The point value
1048c58f1c22SToby Isaac 
1049c58f1c22SToby Isaac   Level: intermediate
1050c58f1c22SToby Isaac 
1051db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`
1052c58f1c22SToby Isaac @*/
1053c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1054c58f1c22SToby Isaac {
1055ad8374ffSToby Isaac   PetscInt       v;
1056c58f1c22SToby Isaac 
1057c58f1c22SToby Isaac   PetscFunctionBegin;
1058d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1059c58f1c22SToby Isaac   /* Find label value */
10609566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
10610c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
10620c3c4a36SLisandro Dalcin 
1063eeed21e7SToby Isaac   if (label->bt) {
106463a3b9bcSJacob Faibussowitsch     PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
10659566063dSJacob Faibussowitsch     PetscCall(PetscBTClear(label->bt, point - label->pStart));
1066eeed21e7SToby Isaac   }
10670c3c4a36SLisandro Dalcin 
10680c3c4a36SLisandro Dalcin   /* Delete key */
10699566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
10709566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDel(label->ht[v], point));
1071c58f1c22SToby Isaac   PetscFunctionReturn(0);
1072c58f1c22SToby Isaac }
1073c58f1c22SToby Isaac 
1074c58f1c22SToby Isaac /*@
1075c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
1076c58f1c22SToby Isaac 
10775b5e7992SMatthew G. Knepley   Not collective
10785b5e7992SMatthew G. Knepley 
1079c58f1c22SToby Isaac   Input Parameters:
1080c58f1c22SToby Isaac + label - the DMLabel
1081c58f1c22SToby Isaac . is    - the point IS
1082c58f1c22SToby Isaac - value - The point value
1083c58f1c22SToby Isaac 
1084c58f1c22SToby Isaac   Level: intermediate
1085c58f1c22SToby Isaac 
1086db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1087c58f1c22SToby Isaac @*/
1088c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1089c58f1c22SToby Isaac {
10900c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1091c58f1c22SToby Isaac   const PetscInt *points;
1092c58f1c22SToby Isaac 
1093c58f1c22SToby Isaac   PetscFunctionBegin;
1094d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1095c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
10960c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10970c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
10989566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
10990c3c4a36SLisandro Dalcin   /* Set keys */
11009566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeInvalid_Private(label, v));
11019566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &n));
11029566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is, &points));
11039566063dSJacob Faibussowitsch   for (p = 0; p < n; ++p) PetscCall(PetscHSetIAdd(label->ht[v], points[p]));
11049566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is, &points));
1105c58f1c22SToby Isaac   PetscFunctionReturn(0);
1106c58f1c22SToby Isaac }
1107c58f1c22SToby Isaac 
110884f0b6dfSMatthew G. Knepley /*@
110984f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
111084f0b6dfSMatthew G. Knepley 
11115b5e7992SMatthew G. Knepley   Not collective
11125b5e7992SMatthew G. Knepley 
111384f0b6dfSMatthew G. Knepley   Input Parameter:
111484f0b6dfSMatthew G. Knepley . label - the DMLabel
111584f0b6dfSMatthew G. Knepley 
111601d2d390SJose E. Roman   Output Parameter:
111784f0b6dfSMatthew G. Knepley . numValues - the number of values
111884f0b6dfSMatthew G. Knepley 
111984f0b6dfSMatthew G. Knepley   Level: intermediate
112084f0b6dfSMatthew G. Knepley 
1121db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
112284f0b6dfSMatthew G. Knepley @*/
1123c58f1c22SToby Isaac PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1124c58f1c22SToby Isaac {
1125c58f1c22SToby Isaac   PetscFunctionBegin;
1126d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1127dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numValues, 2);
1128c58f1c22SToby Isaac   *numValues = label->numStrata;
1129c58f1c22SToby Isaac   PetscFunctionReturn(0);
1130c58f1c22SToby Isaac }
1131c58f1c22SToby Isaac 
113284f0b6dfSMatthew G. Knepley /*@
113384f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
113484f0b6dfSMatthew G. Knepley 
11355b5e7992SMatthew G. Knepley   Not collective
11365b5e7992SMatthew G. Knepley 
113784f0b6dfSMatthew G. Knepley   Input Parameter:
113884f0b6dfSMatthew G. Knepley . label - the DMLabel
113984f0b6dfSMatthew G. Knepley 
114001d2d390SJose E. Roman   Output Parameter:
114184f0b6dfSMatthew G. Knepley . is    - the value IS
114284f0b6dfSMatthew G. Knepley 
114384f0b6dfSMatthew G. Knepley   Level: intermediate
114484f0b6dfSMatthew G. Knepley 
11451d04cbbeSVaclav Hapla   Notes:
11461d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11471d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
11481d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
11491d04cbbeSVaclav Hapla 
1150db781477SPatrick Sanan .seealso: `DMLabelGetNonEmptyStratumValuesIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
115184f0b6dfSMatthew G. Knepley @*/
1152c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1153c58f1c22SToby Isaac {
1154c58f1c22SToby Isaac   PetscFunctionBegin;
1155d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1156c58f1c22SToby Isaac   PetscValidPointer(values, 2);
11579566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1158c58f1c22SToby Isaac   PetscFunctionReturn(0);
1159c58f1c22SToby Isaac }
1160c58f1c22SToby Isaac 
116184f0b6dfSMatthew G. Knepley /*@
11621d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
11631d04cbbeSVaclav Hapla 
11641d04cbbeSVaclav Hapla   Not collective
11651d04cbbeSVaclav Hapla 
11661d04cbbeSVaclav Hapla   Input Parameter:
11671d04cbbeSVaclav Hapla . label - the DMLabel
11681d04cbbeSVaclav Hapla 
11691d04cbbeSVaclav Hapla   Output Paramater:
11701d04cbbeSVaclav Hapla . is    - the value IS
11711d04cbbeSVaclav Hapla 
11721d04cbbeSVaclav Hapla   Level: intermediate
11731d04cbbeSVaclav Hapla 
11741d04cbbeSVaclav Hapla   Notes:
11751d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11761d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
11771d04cbbeSVaclav Hapla 
1178db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
11791d04cbbeSVaclav Hapla @*/
11801d04cbbeSVaclav Hapla PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
11811d04cbbeSVaclav Hapla {
11821d04cbbeSVaclav Hapla   PetscInt        i, j;
11831d04cbbeSVaclav Hapla   PetscInt       *valuesArr;
11841d04cbbeSVaclav Hapla 
11851d04cbbeSVaclav Hapla   PetscFunctionBegin;
11861d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11871d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
11889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(label->numStrata, &valuesArr));
11891d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
11901d04cbbeSVaclav Hapla     PetscInt        n;
11911d04cbbeSVaclav Hapla 
11929566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize_Private(label, i, &n));
11931d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
11941d04cbbeSVaclav Hapla   }
11951d04cbbeSVaclav Hapla   if (j == label->numStrata) {
11969566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
11971d04cbbeSVaclav Hapla   } else {
11989566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
11991d04cbbeSVaclav Hapla   }
12009566063dSJacob Faibussowitsch   PetscCall(PetscFree(valuesArr));
12011d04cbbeSVaclav Hapla   PetscFunctionReturn(0);
12021d04cbbeSVaclav Hapla }
12031d04cbbeSVaclav Hapla 
12041d04cbbeSVaclav Hapla /*@
1205d123abd9SMatthew 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
1206d123abd9SMatthew G. Knepley 
1207d123abd9SMatthew G. Knepley   Not collective
1208d123abd9SMatthew G. Knepley 
1209d123abd9SMatthew G. Knepley   Input Parameters:
1210d123abd9SMatthew G. Knepley + label - the DMLabel
121197bb3fdcSJose E. Roman - value - the value
1212d123abd9SMatthew G. Knepley 
121301d2d390SJose E. Roman   Output Parameter:
1214d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1215d123abd9SMatthew G. Knepley 
1216d123abd9SMatthew G. Knepley   Level: intermediate
1217d123abd9SMatthew G. Knepley 
1218db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
1219d123abd9SMatthew G. Knepley @*/
1220d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1221d123abd9SMatthew G. Knepley {
1222d123abd9SMatthew G. Knepley   PetscInt v;
1223d123abd9SMatthew G. Knepley 
1224d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1225d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1226dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 3);
1227d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
1228d123abd9SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) if (label->stratumValues[v] == value) break;
1229d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1230d123abd9SMatthew G. Knepley   else                       *index = v;
1231d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1232d123abd9SMatthew G. Knepley }
1233d123abd9SMatthew G. Knepley 
1234d123abd9SMatthew G. Knepley /*@
123584f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
123684f0b6dfSMatthew G. Knepley 
12375b5e7992SMatthew G. Knepley   Not collective
12385b5e7992SMatthew G. Knepley 
123984f0b6dfSMatthew G. Knepley   Input Parameters:
124084f0b6dfSMatthew G. Knepley + label - the DMLabel
124184f0b6dfSMatthew G. Knepley - value - the stratum value
124284f0b6dfSMatthew G. Knepley 
124301d2d390SJose E. Roman   Output Parameter:
124484f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
124584f0b6dfSMatthew G. Knepley 
124684f0b6dfSMatthew G. Knepley   Level: intermediate
124784f0b6dfSMatthew G. Knepley 
1248db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
124984f0b6dfSMatthew G. Knepley @*/
1250fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1251fada774cSMatthew G. Knepley {
1252fada774cSMatthew G. Knepley   PetscInt       v;
1253fada774cSMatthew G. Knepley 
1254fada774cSMatthew G. Knepley   PetscFunctionBegin;
1255d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1256dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(exists, 3);
12579566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12580c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1259fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1260fada774cSMatthew G. Knepley }
1261fada774cSMatthew G. Knepley 
126284f0b6dfSMatthew G. Knepley /*@
126384f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
126484f0b6dfSMatthew G. Knepley 
12655b5e7992SMatthew G. Knepley   Not collective
12665b5e7992SMatthew G. Knepley 
126784f0b6dfSMatthew G. Knepley   Input Parameters:
126884f0b6dfSMatthew G. Knepley + label - the DMLabel
126984f0b6dfSMatthew G. Knepley - value - the stratum value
127084f0b6dfSMatthew G. Knepley 
127101d2d390SJose E. Roman   Output Parameter:
127284f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
127384f0b6dfSMatthew G. Knepley 
127484f0b6dfSMatthew G. Knepley   Level: intermediate
127584f0b6dfSMatthew G. Knepley 
1276db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
127784f0b6dfSMatthew G. Knepley @*/
1278c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1279c58f1c22SToby Isaac {
1280c58f1c22SToby Isaac   PetscInt       v;
1281c58f1c22SToby Isaac 
1282c58f1c22SToby Isaac   PetscFunctionBegin;
1283d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1284dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
12859566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
12869566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize_Private(label, v, size));
1287c58f1c22SToby Isaac   PetscFunctionReturn(0);
1288c58f1c22SToby Isaac }
1289c58f1c22SToby Isaac 
129084f0b6dfSMatthew G. Knepley /*@
129184f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
129284f0b6dfSMatthew G. Knepley 
12935b5e7992SMatthew G. Knepley   Not collective
12945b5e7992SMatthew G. Knepley 
129584f0b6dfSMatthew G. Knepley   Input Parameters:
129684f0b6dfSMatthew G. Knepley + label - the DMLabel
129784f0b6dfSMatthew G. Knepley - value - the stratum value
129884f0b6dfSMatthew G. Knepley 
129901d2d390SJose E. Roman   Output Parameters:
130084f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
130184f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
130284f0b6dfSMatthew G. Knepley 
130384f0b6dfSMatthew G. Knepley   Level: intermediate
130484f0b6dfSMatthew G. Knepley 
1305db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
130684f0b6dfSMatthew G. Knepley @*/
1307c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1308c58f1c22SToby Isaac {
13090c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1310c58f1c22SToby Isaac 
1311c58f1c22SToby Isaac   PetscFunctionBegin;
1312d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1313dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = -1;}
1314dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = -1;}
13159566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13160c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13179566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13180c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
13199566063dSJacob Faibussowitsch   PetscCall(ISGetMinMax(label->points[v], &min, &max));
1320d6cb179aSToby Isaac   if (start) *start = min;
1321d6cb179aSToby Isaac   if (end)   *end   = max+1;
1322c58f1c22SToby Isaac   PetscFunctionReturn(0);
1323c58f1c22SToby Isaac }
1324c58f1c22SToby Isaac 
132584f0b6dfSMatthew G. Knepley /*@
132684f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
132784f0b6dfSMatthew G. Knepley 
13285b5e7992SMatthew G. Knepley   Not collective
13295b5e7992SMatthew G. Knepley 
133084f0b6dfSMatthew G. Knepley   Input Parameters:
133184f0b6dfSMatthew G. Knepley + label - the DMLabel
133284f0b6dfSMatthew G. Knepley - value - the stratum value
133384f0b6dfSMatthew G. Knepley 
133401d2d390SJose E. Roman   Output Parameter:
133584f0b6dfSMatthew G. Knepley . points - The stratum points
133684f0b6dfSMatthew G. Knepley 
133784f0b6dfSMatthew G. Knepley   Level: intermediate
133884f0b6dfSMatthew G. Knepley 
1339593ce467SVaclav Hapla   Notes:
1340593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1341593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1342593ce467SVaclav Hapla 
1343db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
134484f0b6dfSMatthew G. Knepley @*/
1345c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1346c58f1c22SToby Isaac {
1347c58f1c22SToby Isaac   PetscInt       v;
1348c58f1c22SToby Isaac 
1349c58f1c22SToby Isaac   PetscFunctionBegin;
1350d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1351c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1352c58f1c22SToby Isaac   *points = NULL;
13539566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
13540c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13559566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
13569566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject) label->points[v]));
1357ad8374ffSToby Isaac   *points = label->points[v];
1358c58f1c22SToby Isaac   PetscFunctionReturn(0);
1359c58f1c22SToby Isaac }
1360c58f1c22SToby Isaac 
136184f0b6dfSMatthew G. Knepley /*@
136284f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
136384f0b6dfSMatthew G. Knepley 
13645b5e7992SMatthew G. Knepley   Not collective
13655b5e7992SMatthew G. Knepley 
136684f0b6dfSMatthew G. Knepley   Input Parameters:
136784f0b6dfSMatthew G. Knepley + label - the DMLabel
136884f0b6dfSMatthew G. Knepley . value - the stratum value
136984f0b6dfSMatthew G. Knepley - points - The stratum points
137084f0b6dfSMatthew G. Knepley 
137184f0b6dfSMatthew G. Knepley   Level: intermediate
137284f0b6dfSMatthew G. Knepley 
1373db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
137484f0b6dfSMatthew G. Knepley @*/
13754de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
13764de306b1SToby Isaac {
13770c3c4a36SLisandro Dalcin   PetscInt       v;
13784de306b1SToby Isaac 
13794de306b1SToby Isaac   PetscFunctionBegin;
1380d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1381d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
13829566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupAddStratum(label, value, &v));
13834de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
13849566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
13859566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is, &(label->stratumSizes[v])));
13869566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)is));
13879566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&(label->points[v])));
13880c3c4a36SLisandro Dalcin   label->points[v]  = is;
13890c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
13909566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject) label));
13914de306b1SToby Isaac   if (label->bt) {
13924de306b1SToby Isaac     const PetscInt *points;
13934de306b1SToby Isaac     PetscInt p;
13944de306b1SToby Isaac 
13959566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,&points));
13964de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
13974de306b1SToby Isaac       const PetscInt point = points[p];
13984de306b1SToby Isaac 
139963a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
14009566063dSJacob Faibussowitsch       PetscCall(PetscBTSet(label->bt, point - label->pStart));
14014de306b1SToby Isaac     }
14024de306b1SToby Isaac   }
14034de306b1SToby Isaac   PetscFunctionReturn(0);
14044de306b1SToby Isaac }
14054de306b1SToby Isaac 
140684f0b6dfSMatthew G. Knepley /*@
140784f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14084de306b1SToby Isaac 
14095b5e7992SMatthew G. Knepley   Not collective
14105b5e7992SMatthew G. Knepley 
141184f0b6dfSMatthew G. Knepley   Input Parameters:
141284f0b6dfSMatthew G. Knepley + label - the DMLabel
141384f0b6dfSMatthew G. Knepley - value - the stratum value
141484f0b6dfSMatthew G. Knepley 
141584f0b6dfSMatthew G. Knepley   Level: intermediate
141684f0b6dfSMatthew G. Knepley 
1417db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
141884f0b6dfSMatthew G. Knepley @*/
1419c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1420c58f1c22SToby Isaac {
1421c58f1c22SToby Isaac   PetscInt       v;
1422c58f1c22SToby Isaac 
1423c58f1c22SToby Isaac   PetscFunctionBegin;
1424d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14259566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
14260c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
14274de306b1SToby Isaac   if (label->validIS[v]) {
14284de306b1SToby Isaac     if (label->bt) {
1429c58f1c22SToby Isaac       PetscInt       i;
1430ad8374ffSToby Isaac       const PetscInt *points;
1431c58f1c22SToby Isaac 
14329566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[v], &points));
1433c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1434ad8374ffSToby Isaac         const PetscInt point = points[i];
1435c58f1c22SToby Isaac 
143663a3b9bcSJacob Faibussowitsch         PetscCheck(!(point < label->pStart) && !(point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, label->pStart, label->pEnd);
14379566063dSJacob Faibussowitsch         PetscCall(PetscBTClear(label->bt, point - label->pStart));
1438c58f1c22SToby Isaac       }
14399566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[v], &points));
1440c58f1c22SToby Isaac     }
1441c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
14429566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&label->points[v]));
14439566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
14449566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) label->points[v], "indices"));
14459566063dSJacob Faibussowitsch     PetscCall(PetscObjectStateIncrease((PetscObject) label));
1446c58f1c22SToby Isaac   } else {
14479566063dSJacob Faibussowitsch     PetscCall(PetscHSetIClear(label->ht[v]));
1448c58f1c22SToby Isaac   }
1449c58f1c22SToby Isaac   PetscFunctionReturn(0);
1450c58f1c22SToby Isaac }
1451c58f1c22SToby Isaac 
145284f0b6dfSMatthew G. Knepley /*@
1453412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1454412e9a14SMatthew G. Knepley 
1455412e9a14SMatthew G. Knepley   Not collective
1456412e9a14SMatthew G. Knepley 
1457412e9a14SMatthew G. Knepley   Input Parameters:
1458412e9a14SMatthew G. Knepley + label  - The DMLabel
1459412e9a14SMatthew G. Knepley . value  - The label value for all points
1460412e9a14SMatthew G. Knepley . pStart - The first point
1461412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1462412e9a14SMatthew G. Knepley 
1463412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1464412e9a14SMatthew G. Knepley 
1465412e9a14SMatthew G. Knepley   Level: intermediate
1466412e9a14SMatthew G. Knepley 
1467db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelSetStratumIS()`, `DMLabelGetStratumIS()`
1468412e9a14SMatthew G. Knepley @*/
1469412e9a14SMatthew G. Knepley PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1470412e9a14SMatthew G. Knepley {
1471412e9a14SMatthew G. Knepley   IS             pIS;
1472412e9a14SMatthew G. Knepley 
1473412e9a14SMatthew G. Knepley   PetscFunctionBegin;
14749566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
14759566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, pIS));
14769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pIS));
1477412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1478412e9a14SMatthew G. Knepley }
1479412e9a14SMatthew G. Knepley 
1480412e9a14SMatthew G. Knepley /*@
1481d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1482d123abd9SMatthew G. Knepley 
1483d123abd9SMatthew G. Knepley   Not collective
1484d123abd9SMatthew G. Knepley 
1485d123abd9SMatthew G. Knepley   Input Parameters:
1486d123abd9SMatthew G. Knepley + label  - The DMLabel
1487d123abd9SMatthew G. Knepley . value  - The label value
1488d123abd9SMatthew G. Knepley - p      - A point with this value
1489d123abd9SMatthew G. Knepley 
1490d123abd9SMatthew G. Knepley   Output Parameter:
1491d123abd9SMatthew 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
1492d123abd9SMatthew G. Knepley 
1493d123abd9SMatthew G. Knepley   Level: intermediate
1494d123abd9SMatthew G. Knepley 
1495db781477SPatrick Sanan .seealso: `DMLabelGetValueIndex()`, `DMLabelGetStratumIS()`, `DMLabelCreate()`
1496d123abd9SMatthew G. Knepley @*/
1497d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1498d123abd9SMatthew G. Knepley {
1499d123abd9SMatthew G. Knepley   const PetscInt *indices;
1500d123abd9SMatthew G. Knepley   PetscInt        v;
1501d123abd9SMatthew G. Knepley 
1502d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1503d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1504dadcf809SJacob Faibussowitsch   PetscValidIntPointer(index, 4);
1505d123abd9SMatthew G. Knepley   *index = -1;
15069566063dSJacob Faibussowitsch   PetscCall(DMLabelLookupStratum(label, value, &v));
1507d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
15089566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeValid_Private(label, v));
15099566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(label->points[v], &indices));
15109566063dSJacob Faibussowitsch   PetscCall(PetscFindInt(p, label->stratumSizes[v], indices, index));
15119566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(label->points[v], &indices));
1512d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1513d123abd9SMatthew G. Knepley }
1514d123abd9SMatthew G. Knepley 
1515d123abd9SMatthew G. Knepley /*@
151684f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
151784f0b6dfSMatthew G. Knepley 
15185b5e7992SMatthew G. Knepley   Not collective
15195b5e7992SMatthew G. Knepley 
152084f0b6dfSMatthew G. Knepley   Input Parameters:
152184f0b6dfSMatthew G. Knepley + label - the DMLabel
152222cd2cdaSVaclav Hapla . start - the first point kept
152322cd2cdaSVaclav Hapla - end - one more than the last point kept
152484f0b6dfSMatthew G. Knepley 
152584f0b6dfSMatthew G. Knepley   Level: intermediate
152684f0b6dfSMatthew G. Knepley 
1527db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
152884f0b6dfSMatthew G. Knepley @*/
1529c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1530c58f1c22SToby Isaac {
1531c58f1c22SToby Isaac   PetscInt       v;
1532c58f1c22SToby Isaac 
1533c58f1c22SToby Isaac   PetscFunctionBegin;
1534d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15359566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroyIndex(label));
15369566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
1537c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
15389566063dSJacob Faibussowitsch     PetscCall(ISGeneralFilter(label->points[v], start, end));
1539c58f1c22SToby Isaac   }
15409566063dSJacob Faibussowitsch   PetscCall(DMLabelCreateIndex(label, start, end));
1541c58f1c22SToby Isaac   PetscFunctionReturn(0);
1542c58f1c22SToby Isaac }
1543c58f1c22SToby Isaac 
154484f0b6dfSMatthew G. Knepley /*@
154584f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
154684f0b6dfSMatthew G. Knepley 
15475b5e7992SMatthew G. Knepley   Not collective
15485b5e7992SMatthew G. Knepley 
154984f0b6dfSMatthew G. Knepley   Input Parameters:
155084f0b6dfSMatthew G. Knepley + label - the DMLabel
155184f0b6dfSMatthew G. Knepley - permutation - the point permutation
155284f0b6dfSMatthew G. Knepley 
155384f0b6dfSMatthew G. Knepley   Output Parameter:
155484f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
155584f0b6dfSMatthew G. Knepley 
155684f0b6dfSMatthew G. Knepley   Level: intermediate
155784f0b6dfSMatthew G. Knepley 
1558db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
155984f0b6dfSMatthew G. Knepley @*/
1560c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1561c58f1c22SToby Isaac {
1562c58f1c22SToby Isaac   const PetscInt *perm;
1563c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1564c58f1c22SToby Isaac 
1565c58f1c22SToby Isaac   PetscFunctionBegin;
1566d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1567d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
15689566063dSJacob Faibussowitsch   PetscCall(DMLabelMakeAllValid_Private(label));
15699566063dSJacob Faibussowitsch   PetscCall(DMLabelDuplicate(label, labelNew));
15709566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(*labelNew, &numValues));
15719566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(permutation, &numPoints));
15729566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(permutation, &perm));
1573c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1574c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1575ad8374ffSToby Isaac     const PetscInt *points;
1576ad8374ffSToby Isaac     PetscInt *pointsNew;
1577c58f1c22SToby Isaac 
15789566063dSJacob Faibussowitsch     PetscCall(ISGetIndices((*labelNew)->points[v],&points));
15799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size,&pointsNew));
1580c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1581ad8374ffSToby Isaac       const PetscInt point = points[q];
1582c58f1c22SToby Isaac 
158363a3b9bcSJacob Faibussowitsch       PetscCheck(!(point < 0) && !(point >= numPoints),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ") for the remapping", point, numPoints);
1584ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1585c58f1c22SToby Isaac     }
15869566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices((*labelNew)->points[v],&points));
15879566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(size, pointsNew));
15889566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&((*labelNew)->points[v])));
1589fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
15909566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v])));
15919566063dSJacob Faibussowitsch       PetscCall(PetscFree(pointsNew));
1592fa8e8ae5SToby Isaac     } else {
15939566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v])));
1594fa8e8ae5SToby Isaac     }
15959566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices"));
1596c58f1c22SToby Isaac   }
15979566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(permutation, &perm));
1598c58f1c22SToby Isaac   if (label->bt) {
15999566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&label->bt));
16009566063dSJacob Faibussowitsch     PetscCall(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1601c58f1c22SToby Isaac   }
1602c58f1c22SToby Isaac   PetscFunctionReturn(0);
1603c58f1c22SToby Isaac }
1604c58f1c22SToby Isaac 
160526c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
160626c55118SMichael Lange {
160726c55118SMichael Lange   MPI_Comm       comm;
1608eb30be1eSVaclav Hapla   PetscInt       s, l, nroots, nleaves, offset, size;
160926c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
161026c55118SMichael Lange   PetscSection   rootSection;
161126c55118SMichael Lange   PetscSF        labelSF;
161226c55118SMichael Lange 
161326c55118SMichael Lange   PetscFunctionBegin;
16149566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelMakeAllValid_Private(label));
16159566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
161626c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
161726c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
16189566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
16199566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &rootSection));
16209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(rootSection, 0, nroots));
162126c55118SMichael Lange   if (label) {
162226c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1623ad8374ffSToby Isaac       const PetscInt *points;
1624ad8374ffSToby Isaac 
16259566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
162626c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1627eb30be1eSVaclav Hapla         PetscCall(PetscSectionAddDof(rootSection, points[l], 1));
162826c55118SMichael Lange       }
16299566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
163026c55118SMichael Lange     }
163126c55118SMichael Lange   }
16329566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(rootSection));
163326c55118SMichael Lange   /* Create a point-wise array of stratum values */
16349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(rootSection, &size));
16359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &rootStrata));
16369566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(nroots, &rootIdx));
163726c55118SMichael Lange   if (label) {
163826c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1639ad8374ffSToby Isaac       const PetscInt *points;
1640ad8374ffSToby Isaac 
16419566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(label->points[s], &points));
164226c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1643ad8374ffSToby Isaac         const PetscInt p = points[l];
16449566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(rootSection, p, &offset));
164526c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
164626c55118SMichael Lange       }
16479566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(label->points[s], &points));
164826c55118SMichael Lange     }
164926c55118SMichael Lange   }
165026c55118SMichael Lange   /* Build SF that maps label points to remote processes */
16519566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, leafSection));
16529566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
16539566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
16549566063dSJacob Faibussowitsch   PetscCall(PetscFree(remoteOffsets));
165526c55118SMichael Lange   /* Send the strata for each point over the derived SF */
16569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*leafSection, &size));
16579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, leafStrata));
16589566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
16599566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
166026c55118SMichael Lange   /* Clean up */
16619566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
16629566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootIdx));
16639566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
16649566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&labelSF));
166526c55118SMichael Lange   PetscFunctionReturn(0);
166626c55118SMichael Lange }
166726c55118SMichael Lange 
166884f0b6dfSMatthew G. Knepley /*@
166984f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
167084f0b6dfSMatthew G. Knepley 
16715b5e7992SMatthew G. Knepley   Collective on sf
16725b5e7992SMatthew G. Knepley 
167384f0b6dfSMatthew G. Knepley   Input Parameters:
167484f0b6dfSMatthew G. Knepley + label - the DMLabel
167584f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
167684f0b6dfSMatthew G. Knepley 
167784f0b6dfSMatthew G. Knepley   Output Parameter:
167884f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
167984f0b6dfSMatthew G. Knepley 
168084f0b6dfSMatthew G. Knepley   Level: intermediate
168184f0b6dfSMatthew G. Knepley 
1682db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMLabelGetValue()`, `DMLabelSetValue()`, `DMLabelClearValue()`
168384f0b6dfSMatthew G. Knepley @*/
1684c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1685c58f1c22SToby Isaac {
1686c58f1c22SToby Isaac   MPI_Comm       comm;
168726c55118SMichael Lange   PetscSection   leafSection;
168826c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
168926c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1690ad8374ffSToby Isaac   PetscInt     **points;
1691d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1692c58f1c22SToby Isaac   char          *name;
1693c58f1c22SToby Isaac   PetscInt       nameSize;
1694e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1695c58f1c22SToby Isaac   size_t         len = 0;
169626c55118SMichael Lange   PetscMPIInt    rank;
1697c58f1c22SToby Isaac 
1698c58f1c22SToby Isaac   PetscFunctionBegin;
1699d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1700f018e600SMatthew G. Knepley   if (label) {
1701f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
17029566063dSJacob Faibussowitsch     PetscCall(DMLabelMakeAllValid_Private(label));
1703f018e600SMatthew G. Knepley   }
17049566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
17059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1706c58f1c22SToby Isaac   /* Bcast name */
1707dd400576SPatrick Sanan   if (rank == 0) {
17089566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &lname));
17099566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1710d67d17b1SMatthew G. Knepley   }
1711c58f1c22SToby Isaac   nameSize = len;
17129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize+1, &name));
17149566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize+1));
17159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
17169566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17179566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
171877d236dfSMichael Lange   /* Bcast defaultValue */
1719dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
17209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
172126c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
17229566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
17235cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
17249566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&stratumHash));
17259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(leafSection, &size));
17269566063dSJacob Faibussowitsch   for (p = 0; p < size; ++p) PetscCall(PetscHSetIAdd(stratumHash, leafStrata[p]));
17279566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
17289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1729ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
17309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
17315cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
17325cbdf6fcSMichael Lange   offset = 0;
17339566063dSJacob Faibussowitsch   PetscCall(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
17349566063dSJacob Faibussowitsch   PetscCall(PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues));
173590e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17369566063dSJacob Faibussowitsch     PetscCall(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
173790e9b2aeSLisandro Dalcin   }
17385cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1739231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1740231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
17415cbdf6fcSMichael Lange     }
17425cbdf6fcSMichael Lange   }
1743c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
17449566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes));
17459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1746c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1749c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1750c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1751c58f1c22SToby Isaac     }
1752c58f1c22SToby Isaac   }
17539566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht));
17549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points));
17559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*labelNew)->numStrata,&points));
1756c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17579566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&(*labelNew)->ht[s]));
17589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1759c58f1c22SToby Isaac   }
1760c58f1c22SToby Isaac   /* Insert points into new strata */
17619566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
17629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1763c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(leafSection, p, &dof));
17659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(leafSection, p, &offset));
1766c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1767c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1768ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1769c58f1c22SToby Isaac     }
1770c58f1c22SToby Isaac   }
1771ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
17729566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s])));
17739566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices"));
1774ad8374ffSToby Isaac   }
17759566063dSJacob Faibussowitsch   PetscCall(PetscFree(points));
17769566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&stratumHash));
17779566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafStrata));
17789566063dSJacob Faibussowitsch   PetscCall(PetscFree(strataIdx));
17799566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&leafSection));
1780c58f1c22SToby Isaac   PetscFunctionReturn(0);
1781c58f1c22SToby Isaac }
1782c58f1c22SToby Isaac 
17837937d9ceSMichael Lange /*@
17847937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
17857937d9ceSMichael Lange 
17865b5e7992SMatthew G. Knepley   Collective on sf
17875b5e7992SMatthew G. Knepley 
17887937d9ceSMichael Lange   Input Parameters:
17897937d9ceSMichael Lange + label - the DMLabel
179084f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
17917937d9ceSMichael Lange 
179284f0b6dfSMatthew G. Knepley   Output Parameters:
179384f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
17947937d9ceSMichael Lange 
17957937d9ceSMichael Lange   Level: developer
17967937d9ceSMichael Lange 
17977937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
17987937d9ceSMichael Lange 
1799db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
18007937d9ceSMichael Lange @*/
18017937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
18027937d9ceSMichael Lange {
18037937d9ceSMichael Lange   MPI_Comm       comm;
18047937d9ceSMichael Lange   PetscSection   rootSection;
18057937d9ceSMichael Lange   PetscSF        sfLabel;
18067937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
18077937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18087937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18097937d9ceSMichael Lange   PetscInt       *rootStrata;
1810d67d17b1SMatthew G. Knepley   const char    *lname;
18117937d9ceSMichael Lange   char          *name;
18127937d9ceSMichael Lange   PetscInt       nameSize;
18137937d9ceSMichael Lange   size_t         len = 0;
18149852e123SBarry Smith   PetscMPIInt    rank, size;
18157937d9ceSMichael Lange 
18167937d9ceSMichael Lange   PetscFunctionBegin;
1817d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1818d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
18199566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
18209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
18219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
18227937d9ceSMichael Lange   /* Bcast name */
1823dd400576SPatrick Sanan   if (rank == 0) {
18249566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) label, &lname));
18259566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(lname, &len));
1826d67d17b1SMatthew G. Knepley   }
18277937d9ceSMichael Lange   nameSize = len;
18289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
18299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nameSize+1, &name));
18309566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscArraycpy(name, lname, nameSize+1));
18319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
18329566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
18339566063dSJacob Faibussowitsch   PetscCall(PetscFree(name));
18347937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
18357937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
18367937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
18379566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
18389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &leafPoints));
1839dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
18407937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
18418212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
18428212dd46SStefano Zampini 
18438212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
18448212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
18457937d9ceSMichael Lange   }
18469566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(sf, &rootDegree));
18479566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(sf, &rootDegree));
18487937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
18499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nmultiroots, &rootPoints));
18509566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
18519566063dSJacob Faibussowitsch   PetscCall(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
18529566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm,& sfLabel));
18539566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
18547937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
18559566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
18567937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
18577937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
18587937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
18599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(rootSection, idx+d, &dof));
18609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(rootSection, idx+d, &offset));
18619566063dSJacob Faibussowitsch       for (s = 0; s < dof; s++) PetscCall(DMLabelSetValue(*labelNew, p, rootStrata[offset+s]));
18627937d9ceSMichael Lange     }
18637937d9ceSMichael Lange     idx += rootDegree[p];
18647937d9ceSMichael Lange   }
18659566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafPoints));
18669566063dSJacob Faibussowitsch   PetscCall(PetscFree(rootStrata));
18679566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&rootSection));
18689566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfLabel));
18697937d9ceSMichael Lange   PetscFunctionReturn(0);
18707937d9ceSMichael Lange }
18717937d9ceSMichael Lange 
1872d42890abSMatthew G. Knepley static PetscErrorCode DMLabelPropagateInit_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[])
1873d42890abSMatthew G. Knepley {
1874d42890abSMatthew G. Knepley   const PetscInt *degree;
1875d42890abSMatthew G. Knepley   const PetscInt *points;
1876d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1877d42890abSMatthew G. Knepley 
1878d42890abSMatthew G. Knepley   PetscFunctionBegin;
1879d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1880d42890abSMatthew G. Knepley   /* Add in leaves */
1881d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1882d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1883d42890abSMatthew G. Knepley     PetscCall(DMLabelGetValue(label, points[l], &val));
1884d42890abSMatthew G. Knepley     if (val != defVal) valArray[points[l]] = val;
1885d42890abSMatthew G. Knepley   }
1886d42890abSMatthew G. Knepley   /* Add in shared roots */
1887d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1888d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1889d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1890d42890abSMatthew G. Knepley     if (degree[r]) {
1891d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, r, &val));
1892d42890abSMatthew G. Knepley       if (val != defVal) valArray[r] = val;
1893d42890abSMatthew G. Knepley     }
1894d42890abSMatthew G. Knepley   }
1895d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1896d42890abSMatthew G. Knepley }
1897d42890abSMatthew G. Knepley 
1898d42890abSMatthew G. Knepley static PetscErrorCode DMLabelPropagateFini_Internal(DMLabel label, PetscSF pointSF, PetscInt valArray[], PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
1899d42890abSMatthew G. Knepley {
1900d42890abSMatthew G. Knepley   const PetscInt *degree;
1901d42890abSMatthew G. Knepley   const PetscInt *points;
1902d42890abSMatthew G. Knepley   PetscInt        Nr, r, Nl, l, val, defVal;
1903d42890abSMatthew G. Knepley 
1904d42890abSMatthew G. Knepley   PetscFunctionBegin;
1905d42890abSMatthew G. Knepley   PetscCall(DMLabelGetDefaultValue(label, &defVal));
1906d42890abSMatthew G. Knepley   /* Read out leaves */
1907d42890abSMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, &Nl, &points, NULL));
1908d42890abSMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
1909d42890abSMatthew G. Knepley     const PetscInt p    = points[l];
1910d42890abSMatthew G. Knepley     const PetscInt cval = valArray[p];
1911d42890abSMatthew G. Knepley 
1912d42890abSMatthew G. Knepley     if (cval != defVal) {
1913d42890abSMatthew G. Knepley       PetscCall(DMLabelGetValue(label, p, &val));
1914d42890abSMatthew G. Knepley       if (val == defVal) {
1915d42890abSMatthew G. Knepley         PetscCall(DMLabelSetValue(label, p, cval));
1916d42890abSMatthew G. Knepley         if (markPoint) {PetscCall((*markPoint)(label, p, cval, ctx));}
1917d42890abSMatthew G. Knepley       }
1918d42890abSMatthew G. Knepley     }
1919d42890abSMatthew G. Knepley   }
1920d42890abSMatthew G. Knepley   /* Read out shared roots */
1921d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeBegin(pointSF, &degree));
1922d42890abSMatthew G. Knepley   PetscCall(PetscSFComputeDegreeEnd(pointSF, &degree));
1923d42890abSMatthew G. Knepley   for (r = 0; r < Nr; ++r) {
1924d42890abSMatthew G. Knepley     if (degree[r]) {
1925d42890abSMatthew G. Knepley       const PetscInt cval = valArray[r];
1926d42890abSMatthew G. Knepley 
1927d42890abSMatthew G. Knepley       if (cval != defVal) {
1928d42890abSMatthew G. Knepley         PetscCall(DMLabelGetValue(label, r, &val));
1929d42890abSMatthew G. Knepley         if (val == defVal) {
1930d42890abSMatthew G. Knepley           PetscCall(DMLabelSetValue(label, r, cval));
1931d42890abSMatthew G. Knepley           if (markPoint) {PetscCall((*markPoint)(label, r, cval, ctx));}
1932d42890abSMatthew G. Knepley         }
1933d42890abSMatthew G. Knepley       }
1934d42890abSMatthew G. Knepley     }
1935d42890abSMatthew G. Knepley   }
1936d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1937d42890abSMatthew G. Knepley }
1938d42890abSMatthew G. Knepley 
1939d42890abSMatthew G. Knepley /*@
1940d42890abSMatthew G. Knepley   DMLabelPropagateBegin - Setup a cycle of label propagation
1941d42890abSMatthew G. Knepley 
1942d42890abSMatthew G. Knepley   Collective on sf
1943d42890abSMatthew G. Knepley 
1944d42890abSMatthew G. Knepley   Input Parameters:
1945d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1946d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1947d42890abSMatthew G. Knepley 
1948d42890abSMatthew G. Knepley   Level: intermediate
1949d42890abSMatthew G. Knepley 
1950db781477SPatrick Sanan .seealso: `DMLabelPropagateEnd()`, `DMLabelPropagatePush()`
1951d42890abSMatthew G. Knepley @*/
1952d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagateBegin(DMLabel label, PetscSF sf)
1953d42890abSMatthew G. Knepley {
1954d42890abSMatthew G. Knepley   PetscInt       Nr, r, defVal;
1955d42890abSMatthew G. Knepley   PetscMPIInt    size;
1956d42890abSMatthew G. Knepley 
1957d42890abSMatthew G. Knepley   PetscFunctionBegin;
1958d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) sf), &size));
1959d42890abSMatthew G. Knepley   if (size > 1) {
1960d42890abSMatthew G. Knepley     PetscCall(DMLabelGetDefaultValue(label, &defVal));
1961d42890abSMatthew G. Knepley     PetscCall(PetscSFGetGraph(sf, &Nr, NULL, NULL, NULL));
1962d42890abSMatthew G. Knepley     if (Nr >= 0) PetscCall(PetscMalloc1(Nr, &label->propArray));
1963d42890abSMatthew G. Knepley     for (r = 0; r < Nr; ++r) label->propArray[r] = defVal;
1964d42890abSMatthew G. Knepley   }
1965d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1966d42890abSMatthew G. Knepley }
1967d42890abSMatthew G. Knepley 
1968d42890abSMatthew G. Knepley /*@
1969d42890abSMatthew G. Knepley   DMLabelPropagateEnd - Tear down a cycle of label propagation
1970d42890abSMatthew G. Knepley 
1971d42890abSMatthew G. Knepley   Collective on sf
1972d42890abSMatthew G. Knepley 
1973d42890abSMatthew G. Knepley   Input Parameters:
1974d42890abSMatthew G. Knepley + label - The DMLabel to propagate across processes
1975d42890abSMatthew G. Knepley - sf    - The SF describing parallel layout of the label points
1976d42890abSMatthew G. Knepley 
1977d42890abSMatthew G. Knepley   Level: intermediate
1978d42890abSMatthew G. Knepley 
1979db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagatePush()`
1980d42890abSMatthew G. Knepley @*/
1981d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagateEnd(DMLabel label, PetscSF pointSF)
1982d42890abSMatthew G. Knepley {
1983d42890abSMatthew G. Knepley   PetscFunctionBegin;
1984d42890abSMatthew G. Knepley   PetscCall(PetscFree(label->propArray));
1985d42890abSMatthew G. Knepley   label->propArray = NULL;
1986d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
1987d42890abSMatthew G. Knepley }
1988d42890abSMatthew G. Knepley 
1989d42890abSMatthew G. Knepley /*@C
1990d42890abSMatthew G. Knepley   DMLabelPropagatePush - Tear down a cycle of label propagation
1991d42890abSMatthew G. Knepley 
1992d42890abSMatthew G. Knepley   Collective on sf
1993d42890abSMatthew G. Knepley 
1994d42890abSMatthew G. Knepley   Input Parameters:
1995d42890abSMatthew G. Knepley + label     - The DMLabel to propagate across processes
1996d42890abSMatthew G. Knepley . sf        - The SF describing parallel layout of the label points
1997d42890abSMatthew G. Knepley . markPoint - An optional user callback that is called when a point is marked, or NULL
1998d42890abSMatthew G. Knepley - ctx       - An optional user context for the callback, or NULL
1999d42890abSMatthew G. Knepley 
2000d42890abSMatthew G. Knepley   Calling sequence of markPoint:
2001d42890abSMatthew G. Knepley $ markPoint(DMLabel label, PetscInt p, PetscInt val, void *ctx);
2002d42890abSMatthew G. Knepley 
2003d42890abSMatthew G. Knepley + label - The DMLabel
2004d42890abSMatthew G. Knepley . p     - The point being marked
2005d42890abSMatthew G. Knepley . val   - The label value for p
2006d42890abSMatthew G. Knepley - ctx   - An optional user context
2007d42890abSMatthew G. Knepley 
2008d42890abSMatthew G. Knepley   Level: intermediate
2009d42890abSMatthew G. Knepley 
2010db781477SPatrick Sanan .seealso: `DMLabelPropagateBegin()`, `DMLabelPropagateEnd()`
2011d42890abSMatthew G. Knepley @*/
2012d42890abSMatthew G. Knepley PetscErrorCode DMLabelPropagatePush(DMLabel label, PetscSF pointSF, PetscErrorCode (*markPoint)(DMLabel, PetscInt, PetscInt, void *), void *ctx)
2013d42890abSMatthew G. Knepley {
2014c50b2d26SMatthew G. Knepley   PetscInt      *valArray = label->propArray, Nr;
2015d42890abSMatthew G. Knepley   PetscMPIInt    size;
2016d42890abSMatthew G. Knepley 
2017d42890abSMatthew G. Knepley   PetscFunctionBegin;
2018d42890abSMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject) pointSF), &size));
2019c50b2d26SMatthew G. Knepley   PetscCall(PetscSFGetGraph(pointSF, &Nr, NULL, NULL, NULL));
2020c50b2d26SMatthew G. Knepley   if (size > 1 && Nr >= 0) {
2021d42890abSMatthew G. Knepley     /* Communicate marked edges
2022d42890abSMatthew G. Knepley        The current implementation allocates an array the size of the number of root. We put the label values into the
2023d42890abSMatthew G. Knepley        array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2024d42890abSMatthew G. Knepley 
2025d42890abSMatthew G. Knepley        TODO: We could use in-place communication with a different SF
2026d42890abSMatthew G. Knepley        We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2027d42890abSMatthew G. Knepley        already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2028d42890abSMatthew G. Knepley 
2029d42890abSMatthew G. Knepley        In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2030d42890abSMatthew 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
2031d42890abSMatthew G. Knepley        edge to the queue.
2032d42890abSMatthew G. Knepley     */
2033d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateInit_Internal(label, pointSF, valArray));
2034d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2035d42890abSMatthew G. Knepley     PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, valArray, valArray, MPI_MAX));
2036d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, valArray, valArray,MPI_REPLACE));
2037d42890abSMatthew G. Knepley     PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, valArray, valArray,MPI_REPLACE));
2038d42890abSMatthew G. Knepley     PetscCall(DMLabelPropagateFini_Internal(label, pointSF, valArray, markPoint, ctx));
2039d42890abSMatthew G. Knepley   }
2040d42890abSMatthew G. Knepley   PetscFunctionReturn(0);
2041d42890abSMatthew G. Knepley }
2042d42890abSMatthew G. Knepley 
204384f0b6dfSMatthew G. Knepley /*@
204484f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
204584f0b6dfSMatthew G. Knepley 
20465b5e7992SMatthew G. Knepley   Not collective
20475b5e7992SMatthew G. Knepley 
204884f0b6dfSMatthew G. Knepley   Input Parameter:
204984f0b6dfSMatthew G. Knepley . label - the DMLabel
205084f0b6dfSMatthew G. Knepley 
205184f0b6dfSMatthew G. Knepley   Output Parameters:
205284f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
205384f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
205484f0b6dfSMatthew G. Knepley 
205584f0b6dfSMatthew G. Knepley   Level: developer
205684f0b6dfSMatthew G. Knepley 
2057db781477SPatrick Sanan .seealso: `DMLabelDistribute()`
205884f0b6dfSMatthew G. Knepley @*/
2059c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
2060c58f1c22SToby Isaac {
2061c58f1c22SToby Isaac   IS              vIS;
2062c58f1c22SToby Isaac   const PetscInt *values;
2063c58f1c22SToby Isaac   PetscInt       *points;
2064c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
2065c58f1c22SToby Isaac 
2066c58f1c22SToby Isaac   PetscFunctionBegin;
2067d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
20689566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &nV));
20699566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(label, &vIS));
20709566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(vIS, &values));
2071c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
2072c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
2073c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
2074c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
2075c58f1c22SToby Isaac   }
20769566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, section));
20779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*section, vS, vE));
2078c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2079c58f1c22SToby Isaac     PetscInt n;
2080c58f1c22SToby Isaac 
20819566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumSize(label, values[v], &n));
20829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*section, values[v], n));
2083c58f1c22SToby Isaac   }
20849566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*section));
20859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(*section, &N));
20869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(N, &points));
2087c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
2088c58f1c22SToby Isaac     IS              is;
2089c58f1c22SToby Isaac     const PetscInt *spoints;
2090c58f1c22SToby Isaac     PetscInt        dof, off, p;
2091c58f1c22SToby Isaac 
20929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*section, values[v], &dof));
20939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*section, values[v], &off));
20949566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumIS(label, values[v], &is));
20959566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, &spoints));
2096c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
20979566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, &spoints));
20989566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2099c58f1c22SToby Isaac   }
21009566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(vIS, &values));
21019566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&vIS));
21029566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
2103c58f1c22SToby Isaac   PetscFunctionReturn(0);
2104c58f1c22SToby Isaac }
2105c58f1c22SToby Isaac 
210684f0b6dfSMatthew G. Knepley /*@
2107c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
2108c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
2109c58f1c22SToby Isaac 
21105b5e7992SMatthew G. Knepley   Collective on sf
21115b5e7992SMatthew G. Knepley 
2112c58f1c22SToby Isaac   Input Parameters:
2113c58f1c22SToby Isaac + s - The PetscSection for the local field layout
2114c58f1c22SToby Isaac . sf - The SF describing parallel layout of the section points
2115c58f1c22SToby Isaac . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
2116c58f1c22SToby Isaac . label - The label specifying the points
2117c58f1c22SToby Isaac - labelValue - The label stratum specifying the points
2118c58f1c22SToby Isaac 
2119c58f1c22SToby Isaac   Output Parameter:
2120c58f1c22SToby Isaac . gsection - The PetscSection for the global field layout
2121c58f1c22SToby Isaac 
2122c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
2123c58f1c22SToby Isaac 
2124c58f1c22SToby Isaac   Level: developer
2125c58f1c22SToby Isaac 
2126db781477SPatrick Sanan .seealso: `PetscSectionCreate()`
2127c58f1c22SToby Isaac @*/
2128c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
2129c58f1c22SToby Isaac {
2130c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
2131c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
2132c58f1c22SToby Isaac 
2133c58f1c22SToby Isaac   PetscFunctionBegin;
2134d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2135d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
2136d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
21379566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection));
21389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
21399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*gsection, pStart, pEnd));
21409566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
2141c58f1c22SToby Isaac   if (nroots >= 0) {
214263a3b9bcSJacob Faibussowitsch     PetscCheck(nroots >= pEnd-pStart,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %" PetscInt_FMT " < %" PetscInt_FMT " section size", nroots, pEnd-pStart);
21439566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(nroots, &neg));
2144c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
21459566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nroots, &tmpOff));
2146c58f1c22SToby Isaac     } else {
2147c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
2148c58f1c22SToby Isaac     }
2149c58f1c22SToby Isaac   }
2150c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
2151c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
2152c58f1c22SToby Isaac     PetscInt value;
2153c58f1c22SToby Isaac 
21549566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, p, &value));
2155c58f1c22SToby Isaac     if (value != labelValue) continue;
21569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(s, p, &dof));
21579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*gsection, p, dof));
21589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
21599566063dSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) PetscCall(PetscSectionSetConstraintDof(*gsection, p, cdof));
2160c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
2161c58f1c22SToby Isaac   }
21629566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUpBC(*gsection));
2163c58f1c22SToby Isaac   if (nroots >= 0) {
21649566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
21659566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
2166c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
2167c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
2168c58f1c22SToby Isaac     }
2169c58f1c22SToby Isaac   }
2170c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
2171c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
2172c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
2173c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
2174c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
2175c58f1c22SToby Isaac   }
21769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s)));
2177c58f1c22SToby Isaac   globalOff -= off;
2178c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
2179c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2180c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
2181c58f1c22SToby Isaac   }
2182c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2183c58f1c22SToby Isaac   if (nroots >= 0) {
21849566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
21859566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
2186c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
2187c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
2188c58f1c22SToby Isaac     }
2189c58f1c22SToby Isaac   }
21909566063dSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd-pStart) PetscCall(PetscFree(tmpOff));
21919566063dSJacob Faibussowitsch   PetscCall(PetscFree(neg));
2192c58f1c22SToby Isaac   PetscFunctionReturn(0);
2193c58f1c22SToby Isaac }
2194c58f1c22SToby Isaac 
21955fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
21965fdea053SToby Isaac {
21975fdea053SToby Isaac   DMLabel           label;
21985fdea053SToby Isaac   PetscCopyMode     *modes;
21995fdea053SToby Isaac   PetscInt          *sizes;
22005fdea053SToby Isaac   const PetscInt    ***perms;
22015fdea053SToby Isaac   const PetscScalar ***rots;
22025fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
22035fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
22045fdea053SToby Isaac } PetscSectionSym_Label;
22055fdea053SToby Isaac 
22065fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
22075fdea053SToby Isaac {
22085fdea053SToby Isaac   PetscInt              i, j;
22095fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
22105fdea053SToby Isaac 
22115fdea053SToby Isaac   PetscFunctionBegin;
22125fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
22135fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
22145fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22159566063dSJacob Faibussowitsch         if (sl->perms[i]) PetscCall(PetscFree(sl->perms[i][j]));
22169566063dSJacob Faibussowitsch         if (sl->rots[i]) PetscCall(PetscFree(sl->rots[i][j]));
22175fdea053SToby Isaac       }
22185fdea053SToby Isaac       if (sl->perms[i]) {
22195fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
22205fdea053SToby Isaac 
22219566063dSJacob Faibussowitsch         PetscCall(PetscFree(perms));
22225fdea053SToby Isaac       }
22235fdea053SToby Isaac       if (sl->rots[i]) {
22245fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
22255fdea053SToby Isaac 
22269566063dSJacob Faibussowitsch         PetscCall(PetscFree(rots));
22275fdea053SToby Isaac       }
22285fdea053SToby Isaac     }
22295fdea053SToby Isaac   }
22309566063dSJacob Faibussowitsch   PetscCall(PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients));
22319566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&sl->label));
22325fdea053SToby Isaac   sl->numStrata = 0;
22335fdea053SToby Isaac   PetscFunctionReturn(0);
22345fdea053SToby Isaac }
22355fdea053SToby Isaac 
22365fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
22375fdea053SToby Isaac {
22385fdea053SToby Isaac   PetscFunctionBegin;
22399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelReset(sym));
22409566063dSJacob Faibussowitsch   PetscCall(PetscFree(sym->data));
22415fdea053SToby Isaac   PetscFunctionReturn(0);
22425fdea053SToby Isaac }
22435fdea053SToby Isaac 
22445fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
22455fdea053SToby Isaac {
22465fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
22475fdea053SToby Isaac   PetscBool             isAscii;
22485fdea053SToby Isaac   DMLabel               label = sl->label;
2249d67d17b1SMatthew G. Knepley   const char           *name;
22505fdea053SToby Isaac 
22515fdea053SToby Isaac   PetscFunctionBegin;
22529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii));
22535fdea053SToby Isaac   if (isAscii) {
22545fdea053SToby Isaac     PetscInt          i, j, k;
22555fdea053SToby Isaac     PetscViewerFormat format;
22565fdea053SToby Isaac 
22579566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer,&format));
22585fdea053SToby Isaac     if (label) {
22599566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetFormat(viewer,&format));
22605fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
22629566063dSJacob Faibussowitsch         PetscCall(DMLabelView(label, viewer));
22639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
22645fdea053SToby Isaac       } else {
22659566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
22669566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name));
22675fdea053SToby Isaac       }
22685fdea053SToby Isaac     } else {
22699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "No label given\n"));
22705fdea053SToby Isaac     }
22719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
22725fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
22735fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
22745fdea053SToby Isaac 
22755fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
227663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point): no symmetries\n", value, sl->sizes[i]));
22775fdea053SToby Isaac       } else {
227863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %" PetscInt_FMT " (%" PetscInt_FMT " dofs per point):\n", value, sl->sizes[i]));
22799566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
228063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation range: [%" PetscInt_FMT ", %" PetscInt_FMT ")\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
22815fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
22829566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPushTab(viewer));
22835fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
22845fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
228563a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ": identity\n",j));
22865fdea053SToby Isaac             } else {
22875fdea053SToby Isaac               PetscInt tab;
22885fdea053SToby Isaac 
228963a3b9bcSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPrintf(viewer, "Orientation %" PetscInt_FMT ":\n",j));
22909566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPushTab(viewer));
22919566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIGetTab(viewer,&tab));
22925fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
22939566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"Permutation:"));
22949566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,0));
229563a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT,sl->perms[i][j][k]));
22969566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
22979566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,tab));
22985fdea053SToby Isaac               }
22995fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
23009566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"Rotations:  "));
23019566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,0));
23025fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
230363a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %+g+i*%+g",(double)PetscRealPart(sl->rots[i][j][k]),(double)PetscImaginaryPart(sl->rots[i][j][k])));
23045fdea053SToby Isaac #else
230563a3b9bcSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) PetscCall(PetscViewerASCIIPrintf(viewer," %+g",(double)sl->rots[i][j][k]));
23065fdea053SToby Isaac #endif
23079566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
23089566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISetTab(viewer,tab));
23095fdea053SToby Isaac               }
23109566063dSJacob Faibussowitsch               PetscCall(PetscViewerASCIIPopTab(viewer));
23115fdea053SToby Isaac             }
23125fdea053SToby Isaac           }
23139566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPopTab(viewer));
23145fdea053SToby Isaac         }
23159566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
23165fdea053SToby Isaac       }
23175fdea053SToby Isaac     }
23189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
23195fdea053SToby Isaac   }
23205fdea053SToby Isaac   PetscFunctionReturn(0);
23215fdea053SToby Isaac }
23225fdea053SToby Isaac 
23235fdea053SToby Isaac /*@
23245fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
23255fdea053SToby Isaac 
23265fdea053SToby Isaac   Logically collective on sym
23275fdea053SToby Isaac 
23285fdea053SToby Isaac   Input parameters:
23295fdea053SToby Isaac + sym - the section symmetries
23305fdea053SToby Isaac - label - the DMLabel describing the types of points
23315fdea053SToby Isaac 
23325fdea053SToby Isaac   Level: developer:
23335fdea053SToby Isaac 
2334db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreateLabel()`, `PetscSectionGetPointSyms()`
23355fdea053SToby Isaac @*/
23365fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
23375fdea053SToby Isaac {
23385fdea053SToby Isaac   PetscSectionSym_Label *sl;
23395fdea053SToby Isaac 
23405fdea053SToby Isaac   PetscFunctionBegin;
23415fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
23425fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
23439566063dSJacob Faibussowitsch   if (sl->label && sl->label != label) PetscCall(PetscSectionSymLabelReset(sym));
23445fdea053SToby Isaac   if (label) {
23455fdea053SToby Isaac     sl->label = label;
23469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) label));
23479566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label,&sl->numStrata));
23489566063dSJacob 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));
23499566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode)));
23509566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt)));
23519566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **)));
23529566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **)));
23539566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2])));
23545fdea053SToby Isaac   }
23555fdea053SToby Isaac   PetscFunctionReturn(0);
23565fdea053SToby Isaac }
23575fdea053SToby Isaac 
23585fdea053SToby Isaac /*@C
2359b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2360b004864fSMatthew G. Knepley 
2361b004864fSMatthew G. Knepley   Logically collective on sym
2362b004864fSMatthew G. Knepley 
2363b004864fSMatthew G. Knepley   Input Parameters:
2364b004864fSMatthew G. Knepley + sym       - the section symmetries
2365b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2366b004864fSMatthew G. Knepley 
2367b004864fSMatthew G. Knepley   Output Parameters:
2368b004864fSMatthew G. Knepley + size      - the number of dofs for points in the stratum of the label
2369b004864fSMatthew G. Knepley . minOrient - the smallest orientation for a point in this stratum
2370b004864fSMatthew G. Knepley . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2371b004864fSMatthew G. Knepley . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2372b004864fSMatthew 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
2373b004864fSMatthew G. Knepley 
2374b004864fSMatthew G. Knepley   Level: developer
2375b004864fSMatthew G. Knepley 
2376db781477SPatrick Sanan .seealso: `PetscSectionSymLabelSetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
2377b004864fSMatthew G. Knepley @*/
2378b004864fSMatthew G. Knepley PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2379b004864fSMatthew G. Knepley {
2380b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2381b004864fSMatthew G. Knepley   const char            *name;
2382b004864fSMatthew G. Knepley   PetscInt               i;
2383b004864fSMatthew G. Knepley 
2384b004864fSMatthew G. Knepley   PetscFunctionBegin;
2385b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
2386b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *) sym->data;
2387b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2388b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2389b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2390b004864fSMatthew G. Knepley 
2391b004864fSMatthew G. Knepley     if (stratum == value) break;
2392b004864fSMatthew G. Knepley   }
23939566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
2394b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
2395b004864fSMatthew G. Knepley   if (size)      {PetscValidIntPointer(size, 3);      *size      = sl->sizes[i];}
2396b004864fSMatthew G. Knepley   if (minOrient) {PetscValidIntPointer(minOrient, 4); *minOrient = sl->minMaxOrients[i][0];}
2397b004864fSMatthew G. Knepley   if (maxOrient) {PetscValidIntPointer(maxOrient, 5); *maxOrient = sl->minMaxOrients[i][1];}
2398b004864fSMatthew G. Knepley   if (perms)     {PetscValidPointer(perms, 6);        *perms     = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;}
2399b004864fSMatthew G. Knepley   if (rots)      {PetscValidPointer(rots, 7);         *rots      = sl->rots[i]  ? &sl->rots[i][sl->minMaxOrients[i][0]]  : NULL;}
2400b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2401b004864fSMatthew G. Knepley }
2402b004864fSMatthew G. Knepley 
2403b004864fSMatthew G. Knepley /*@C
24045fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
24055fdea053SToby Isaac 
24065b5e7992SMatthew G. Knepley   Logically collective on sym
24075fdea053SToby Isaac 
24085fdea053SToby Isaac   InputParameters:
24095b5e7992SMatthew G. Knepley + sym       - the section symmetries
24105fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
24115fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
24125fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
24135fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
24145fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
24155fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2416a2b725a8SWilliam 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
24175fdea053SToby Isaac 
24185fdea053SToby Isaac   Level: developer
24195fdea053SToby Isaac 
2420db781477SPatrick Sanan .seealso: `PetscSectionSymLabelGetStratum()`, `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetPointSyms()`, `PetscSectionSymCreateLabel()`
24215fdea053SToby Isaac @*/
24225fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
24235fdea053SToby Isaac {
24245fdea053SToby Isaac   PetscSectionSym_Label *sl;
2425d67d17b1SMatthew G. Knepley   const char            *name;
2426d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
24275fdea053SToby Isaac 
24285fdea053SToby Isaac   PetscFunctionBegin;
24295fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
24305fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
2431b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
24325fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
24335fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
24345fdea053SToby Isaac 
24355fdea053SToby Isaac     if (stratum == value) break;
24365fdea053SToby Isaac   }
24379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) sl->label, &name));
243863a3b9bcSJacob Faibussowitsch   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
24395fdea053SToby Isaac   sl->sizes[i] = size;
24405fdea053SToby Isaac   sl->modes[i] = mode;
24415fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
24425fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
24435fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
24445fdea053SToby Isaac     if (perms) {
24455fdea053SToby Isaac       PetscInt    **ownPerms;
24465fdea053SToby Isaac 
24479566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient,&ownPerms));
24485fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
24495fdea053SToby Isaac         if (perms[j]) {
24509566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size,&ownPerms[j]));
24515fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
24525fdea053SToby Isaac         }
24535fdea053SToby Isaac       }
24545fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
24555fdea053SToby Isaac     }
24565fdea053SToby Isaac     if (rots) {
24575fdea053SToby Isaac       PetscScalar **ownRots;
24585fdea053SToby Isaac 
24599566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(maxOrient - minOrient,&ownRots));
24605fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
24615fdea053SToby Isaac         if (rots[j]) {
24629566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size,&ownRots[j]));
24635fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
24645fdea053SToby Isaac         }
24655fdea053SToby Isaac       }
24665fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
24675fdea053SToby Isaac     }
24685fdea053SToby Isaac   } else {
24695fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
24705fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
24715fdea053SToby Isaac   }
24725fdea053SToby Isaac   PetscFunctionReturn(0);
24735fdea053SToby Isaac }
24745fdea053SToby Isaac 
24755fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
24765fdea053SToby Isaac {
24775fdea053SToby Isaac   PetscInt              i, j, numStrata;
24785fdea053SToby Isaac   PetscSectionSym_Label *sl;
24795fdea053SToby Isaac   DMLabel               label;
24805fdea053SToby Isaac 
24815fdea053SToby Isaac   PetscFunctionBegin;
24825fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
24835fdea053SToby Isaac   numStrata = sl->numStrata;
24845fdea053SToby Isaac   label     = sl->label;
24855fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
24865fdea053SToby Isaac     PetscInt point = points[2*i];
24875fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
24885fdea053SToby Isaac 
24895fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
24905fdea053SToby Isaac       if (label->validIS[j]) {
24915fdea053SToby Isaac         PetscInt k;
24925fdea053SToby Isaac 
24939566063dSJacob Faibussowitsch         PetscCall(ISLocate(label->points[j],point,&k));
24945fdea053SToby Isaac         if (k >= 0) break;
24955fdea053SToby Isaac       } else {
24965fdea053SToby Isaac         PetscBool has;
24975fdea053SToby Isaac 
24989566063dSJacob Faibussowitsch         PetscCall(PetscHSetIHas(label->ht[j], point, &has));
24995fdea053SToby Isaac         if (has) break;
25005fdea053SToby Isaac       }
25015fdea053SToby Isaac     }
250263a3b9bcSJacob Faibussowitsch     PetscCheck(!(sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) || !(ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1]),PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"point %" PetscInt_FMT " orientation %" PetscInt_FMT " not in range [%" PetscInt_FMT ", %" PetscInt_FMT ") for stratum %" PetscInt_FMT,point,ornt,sl->minMaxOrients[j][0],sl->minMaxOrients[j][1],j < numStrata ? label->stratumValues[j] : label->defaultValue);
25035fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
25045fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
25055fdea053SToby Isaac   }
25065fdea053SToby Isaac   PetscFunctionReturn(0);
25075fdea053SToby Isaac }
25085fdea053SToby Isaac 
2509b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2510b004864fSMatthew G. Knepley {
2511b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) nsym->data;
2512b004864fSMatthew G. Knepley   IS                     valIS;
2513b004864fSMatthew G. Knepley   const PetscInt        *values;
2514b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2515b004864fSMatthew G. Knepley 
2516b004864fSMatthew G. Knepley   PetscFunctionBegin;
25179566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(sl->label, &Nv));
25189566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValueIS(sl->label, &valIS));
25199566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(valIS, &values));
2520b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2521b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2522b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2523b004864fSMatthew G. Knepley     const PetscInt    **perms;
2524b004864fSMatthew G. Knepley     const PetscScalar **rots;
2525b004864fSMatthew G. Knepley 
25269566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelGetStratum(sym,  val, &size, &minOrient, &maxOrient, &perms, &rots));
25279566063dSJacob Faibussowitsch     PetscCall(PetscSectionSymLabelSetStratum(nsym, val,  size,  minOrient,  maxOrient, PETSC_COPY_VALUES, perms, rots));
2528b004864fSMatthew G. Knepley   }
25299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&valIS));
2530b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2531b004864fSMatthew G. Knepley }
2532b004864fSMatthew G. Knepley 
2533b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2534b004864fSMatthew G. Knepley {
2535b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
2536b004864fSMatthew G. Knepley   DMLabel                dlabel;
2537b004864fSMatthew G. Knepley 
2538b004864fSMatthew G. Knepley   PetscFunctionBegin;
25399566063dSJacob Faibussowitsch   PetscCall(DMLabelDistribute(sl->label, migrationSF, &dlabel));
25409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject) sym), dlabel, dsym));
25419566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dlabel));
25429566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCopy(sym, *dsym));
2543b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2544b004864fSMatthew G. Knepley }
2545b004864fSMatthew G. Knepley 
25465fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
25475fdea053SToby Isaac {
25485fdea053SToby Isaac   PetscSectionSym_Label *sl;
25495fdea053SToby Isaac 
25505fdea053SToby Isaac   PetscFunctionBegin;
25519566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(sym,&sl));
25525fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2553b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2554b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
25555fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
25565fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
25575fdea053SToby Isaac   sym->data            = (void *) sl;
25585fdea053SToby Isaac   PetscFunctionReturn(0);
25595fdea053SToby Isaac }
25605fdea053SToby Isaac 
25615fdea053SToby Isaac /*@
25625fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
25635fdea053SToby Isaac 
25645fdea053SToby Isaac   Collective
25655fdea053SToby Isaac 
25665fdea053SToby Isaac   Input Parameters:
25675fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
25685fdea053SToby Isaac - label - the label defining the strata
25695fdea053SToby Isaac 
25705fdea053SToby Isaac   Output Parameters:
25715fdea053SToby Isaac . sym - the section symmetries
25725fdea053SToby Isaac 
25735fdea053SToby Isaac   Level: developer
25745fdea053SToby Isaac 
2575db781477SPatrick Sanan .seealso: `PetscSectionSymCreate()`, `PetscSectionSetSym()`, `PetscSectionGetSym()`, `PetscSectionSymLabelSetStratum()`, `PetscSectionGetPointSyms()`
25765fdea053SToby Isaac @*/
25775fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
25785fdea053SToby Isaac {
25795fdea053SToby Isaac   PetscFunctionBegin;
25809566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
25819566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymCreate(comm,sym));
25829566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL));
25839566063dSJacob Faibussowitsch   PetscCall(PetscSectionSymLabelSetLabel(*sym,label));
25845fdea053SToby Isaac   PetscFunctionReturn(0);
25855fdea053SToby Isaac }
2586