xref: /petsc/src/dm/label/dmlabel.c (revision 76bd3646d776ac16fc835ea742fa097f15759704)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h>   /*I      "petscdmlabel.h"   I*/
3ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h>   /*I      "petscsection.h"   I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5ea844a1aSMatthew Knepley #include <petscsection.h>
6c58f1c22SToby Isaac 
7c58f1c22SToby Isaac /*@C
8c58f1c22SToby Isaac   DMLabelCreate - Create a DMLabel object, which is a multimap
9c58f1c22SToby Isaac 
105b5e7992SMatthew G. Knepley   Collective
115b5e7992SMatthew G. Knepley 
12d67d17b1SMatthew G. Knepley   Input parameters:
13d67d17b1SMatthew G. Knepley + comm - The communicator, usually PETSC_COMM_SELF
14d67d17b1SMatthew G. Knepley - name - The label name
15c58f1c22SToby Isaac 
16c58f1c22SToby Isaac   Output parameter:
17c58f1c22SToby Isaac . label - The DMLabel
18c58f1c22SToby Isaac 
19c58f1c22SToby Isaac   Level: beginner
20c58f1c22SToby Isaac 
2105ab7a9fSVaclav Hapla   Notes:
2205ab7a9fSVaclav Hapla   The label name is actually usual PetscObject name.
2305ab7a9fSVaclav Hapla   One can get/set it with PetscObjectGetName()/PetscObjectSetName().
2405ab7a9fSVaclav Hapla 
25c58f1c22SToby Isaac .seealso: DMLabelDestroy()
26c58f1c22SToby Isaac @*/
27d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
28c58f1c22SToby Isaac {
29c58f1c22SToby Isaac   PetscErrorCode ierr;
30c58f1c22SToby Isaac 
31c58f1c22SToby Isaac   PetscFunctionBegin;
32d67d17b1SMatthew G. Knepley   PetscValidPointer(label,2);
33d67d17b1SMatthew G. Knepley   ierr = DMInitializePackage();CHKERRQ(ierr);
34c58f1c22SToby Isaac 
35d67d17b1SMatthew G. Knepley   ierr = PetscHeaderCreate(*label,DMLABEL_CLASSID,"DMLabel","DMLabel","DM",comm,DMLabelDestroy,DMLabelView);CHKERRQ(ierr);
36d67d17b1SMatthew G. Knepley 
37c58f1c22SToby Isaac   (*label)->numStrata      = 0;
385aa44df4SToby Isaac   (*label)->defaultValue   = -1;
39c58f1c22SToby Isaac   (*label)->stratumValues  = NULL;
40ad8374ffSToby Isaac   (*label)->validIS        = NULL;
41c58f1c22SToby Isaac   (*label)->stratumSizes   = NULL;
42c58f1c22SToby Isaac   (*label)->points         = NULL;
43c58f1c22SToby Isaac   (*label)->ht             = NULL;
44c58f1c22SToby Isaac   (*label)->pStart         = -1;
45c58f1c22SToby Isaac   (*label)->pEnd           = -1;
46c58f1c22SToby Isaac   (*label)->bt             = NULL;
47b9907514SLisandro Dalcin   ierr = PetscHMapICreate(&(*label)->hmap);CHKERRQ(ierr);
48d67d17b1SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *label, name);CHKERRQ(ierr);
49c58f1c22SToby Isaac   PetscFunctionReturn(0);
50c58f1c22SToby Isaac }
51c58f1c22SToby Isaac 
52c58f1c22SToby Isaac /*
53c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
54c58f1c22SToby Isaac 
555b5e7992SMatthew G. Knepley   Not collective
565b5e7992SMatthew G. Knepley 
57c58f1c22SToby Isaac   Input parameter:
58c58f1c22SToby Isaac + label - The DMLabel
59c58f1c22SToby Isaac - v - The stratum value
60c58f1c22SToby Isaac 
61c58f1c22SToby Isaac   Output parameter:
62c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
63c58f1c22SToby Isaac 
64c58f1c22SToby Isaac   Level: developer
65c58f1c22SToby Isaac 
66c58f1c22SToby Isaac .seealso: DMLabelCreate()
67c58f1c22SToby Isaac */
68c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
69c58f1c22SToby Isaac {
70277ea44aSLisandro Dalcin   IS             is;
71b9907514SLisandro Dalcin   PetscInt       off = 0, *pointArray, p;
72c58f1c22SToby Isaac   PetscErrorCode ierr;
73c58f1c22SToby Isaac 
74b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
75c58f1c22SToby Isaac   PetscFunctionBegin;
760c3c4a36SLisandro Dalcin   if (v < 0 || v >= label->numStrata) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeValid_Private\n", v);
77e8f14785SLisandro Dalcin   ierr = PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]);CHKERRQ(ierr);
78ad8374ffSToby Isaac   ierr = PetscMalloc1(label->stratumSizes[v], &pointArray);CHKERRQ(ierr);
79e8f14785SLisandro Dalcin   ierr = PetscHSetIGetElems(label->ht[v], &off, pointArray);CHKERRQ(ierr);
80b9907514SLisandro Dalcin   ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr);
81ad8374ffSToby Isaac   ierr = PetscSortInt(label->stratumSizes[v], pointArray);CHKERRQ(ierr);
82c58f1c22SToby Isaac   if (label->bt) {
83c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
84ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
85c58f1c22SToby Isaac       if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
86c58f1c22SToby Isaac       ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr);
87c58f1c22SToby Isaac     }
88c58f1c22SToby Isaac   }
89ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v]-1] == pointArray[0] + label->stratumSizes[v]-1) {
90ba2698f1SMatthew G. Knepley     ierr = ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is);CHKERRQ(ierr);
91ba2698f1SMatthew G. Knepley     ierr = PetscFree(pointArray);CHKERRQ(ierr);
92ba2698f1SMatthew G. Knepley   } else {
93277ea44aSLisandro Dalcin     ierr = ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is);CHKERRQ(ierr);
94ba2698f1SMatthew G. Knepley   }
95277ea44aSLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) is, "indices");CHKERRQ(ierr);
96277ea44aSLisandro Dalcin   label->points[v]  = is;
97ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
98d67d17b1SMatthew G. Knepley   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
99c58f1c22SToby Isaac   PetscFunctionReturn(0);
100c58f1c22SToby Isaac }
101c58f1c22SToby Isaac 
102c58f1c22SToby Isaac /*
103c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
104c58f1c22SToby Isaac 
1055b5e7992SMatthew G. Knepley   Not collective
1065b5e7992SMatthew G. Knepley 
107c58f1c22SToby Isaac   Input parameter:
108c58f1c22SToby Isaac . label - The DMLabel
109c58f1c22SToby Isaac 
110c58f1c22SToby Isaac   Output parameter:
111c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
112c58f1c22SToby Isaac 
113c58f1c22SToby Isaac   Level: developer
114c58f1c22SToby Isaac 
115c58f1c22SToby Isaac .seealso: DMLabelCreate()
116c58f1c22SToby Isaac */
117c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
118c58f1c22SToby Isaac {
119c58f1c22SToby Isaac   PetscInt       v;
120c58f1c22SToby Isaac   PetscErrorCode ierr;
121c58f1c22SToby Isaac 
122c58f1c22SToby Isaac   PetscFunctionBegin;
123c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; v++){
124c58f1c22SToby Isaac     ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
125c58f1c22SToby Isaac   }
126c58f1c22SToby Isaac   PetscFunctionReturn(0);
127c58f1c22SToby Isaac }
128c58f1c22SToby Isaac 
129c58f1c22SToby Isaac /*
130c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
131c58f1c22SToby Isaac 
1325b5e7992SMatthew G. Knepley   Not collective
1335b5e7992SMatthew G. Knepley 
134c58f1c22SToby Isaac   Input parameter:
135c58f1c22SToby Isaac + label - The DMLabel
136c58f1c22SToby Isaac - v - The stratum value
137c58f1c22SToby Isaac 
138c58f1c22SToby Isaac   Output parameter:
139c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
140c58f1c22SToby Isaac 
141c58f1c22SToby Isaac   Level: developer
142c58f1c22SToby Isaac 
143c58f1c22SToby Isaac .seealso: DMLabelCreate()
144c58f1c22SToby Isaac */
145c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
146c58f1c22SToby Isaac {
147c58f1c22SToby Isaac   PetscInt       p;
148ad8374ffSToby Isaac   const PetscInt *points;
149c58f1c22SToby Isaac   PetscErrorCode ierr;
150c58f1c22SToby Isaac 
151b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
152c58f1c22SToby Isaac   PetscFunctionBegin;
1530c3c4a36SLisandro Dalcin   if (v < 0 || v >= label->numStrata) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeInvalid_Private\n", v);
154ad8374ffSToby Isaac   if (label->points[v]) {
155ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
156e8f14785SLisandro Dalcin     for (p = 0; p < label->stratumSizes[v]; ++p) {
157e8f14785SLisandro Dalcin       ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);
158e8f14785SLisandro Dalcin     }
159ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr);
160ad8374ffSToby Isaac     ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr);
161ad8374ffSToby Isaac   }
162ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
163c58f1c22SToby Isaac   PetscFunctionReturn(0);
164c58f1c22SToby Isaac }
165c58f1c22SToby Isaac 
166b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
167b9907514SLisandro Dalcin #define DMLABEL_LOOKUP_THRESHOLD 16
168b9907514SLisandro Dalcin #endif
169b9907514SLisandro Dalcin 
1700c3c4a36SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
1710c3c4a36SLisandro Dalcin {
1720c3c4a36SLisandro Dalcin   PetscInt       v;
173b9907514SLisandro Dalcin   PetscErrorCode ierr;
1740e79e033SBarry Smith 
1750c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1760e79e033SBarry Smith   *index = -1;
177b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
178b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
179b9907514SLisandro Dalcin       if (label->stratumValues[v] == value) {*index = v; break;}
180b9907514SLisandro Dalcin   } else {
181b9907514SLisandro Dalcin     ierr = PetscHMapIGet(label->hmap, value, index);CHKERRQ(ierr);
1820e79e033SBarry Smith   }
183*76bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */
18490e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
18590e9b2aeSLisandro Dalcin     ierr = PetscHMapIGetSize(label->hmap, &len);CHKERRQ(ierr);
18690e9b2aeSLisandro Dalcin     if (len != label->numStrata) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
18790e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
18890e9b2aeSLisandro Dalcin       ierr = PetscHMapIGet(label->hmap, value, &loc);CHKERRQ(ierr);
18990e9b2aeSLisandro Dalcin     } else {
19090e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
19190e9b2aeSLisandro Dalcin         if (label->stratumValues[v] == value) {loc = v; break;}
19290e9b2aeSLisandro Dalcin     }
19390e9b2aeSLisandro Dalcin     if (loc != *index) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
19490e9b2aeSLisandro Dalcin   }
1950c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
1960c3c4a36SLisandro Dalcin }
1970c3c4a36SLisandro Dalcin 
198b9907514SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
199c58f1c22SToby Isaac {
200b9907514SLisandro Dalcin   PetscInt       v;
201b9907514SLisandro Dalcin   PetscInt      *tmpV;
202b9907514SLisandro Dalcin   PetscInt      *tmpS;
203b9907514SLisandro Dalcin   PetscHSetI    *tmpH, ht;
204b9907514SLisandro Dalcin   IS            *tmpP, is;
205c58f1c22SToby Isaac   PetscBool     *tmpB;
206b9907514SLisandro Dalcin   PetscHMapI     hmap = label->hmap;
207c58f1c22SToby Isaac   PetscErrorCode ierr;
208c58f1c22SToby Isaac 
209c58f1c22SToby Isaac   PetscFunctionBegin;
210b9907514SLisandro Dalcin   v    = label->numStrata;
211b9907514SLisandro Dalcin   tmpV = label->stratumValues;
212b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
213b9907514SLisandro Dalcin   tmpH = label->ht;
214b9907514SLisandro Dalcin   tmpP = label->points;
215b9907514SLisandro Dalcin   tmpB = label->validIS;
2168e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2178e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2188e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2198e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2208e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2218e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2228e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpV), &tmpV);CHKERRQ(ierr);
2238e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpS), &tmpS);CHKERRQ(ierr);
2248e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpH), &tmpH);CHKERRQ(ierr);
2258e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpP), &tmpP);CHKERRQ(ierr);
2268e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpB), &tmpB);CHKERRQ(ierr);
227580bdb30SBarry Smith     ierr = PetscArraycpy(tmpV, oldV, v);CHKERRQ(ierr);
228580bdb30SBarry Smith     ierr = PetscArraycpy(tmpS, oldS, v);CHKERRQ(ierr);
229580bdb30SBarry Smith     ierr = PetscArraycpy(tmpH, oldH, v);CHKERRQ(ierr);
230580bdb30SBarry Smith     ierr = PetscArraycpy(tmpP, oldP, v);CHKERRQ(ierr);
231580bdb30SBarry Smith     ierr = PetscArraycpy(tmpB, oldB, v);CHKERRQ(ierr);
2328e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldV);CHKERRQ(ierr);
2338e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldS);CHKERRQ(ierr);
2348e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldH);CHKERRQ(ierr);
2358e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldP);CHKERRQ(ierr);
2368e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldB);CHKERRQ(ierr);
2378e1f8cf0SLisandro Dalcin   }
238b9907514SLisandro Dalcin   label->numStrata     = v+1;
239c58f1c22SToby Isaac   label->stratumValues = tmpV;
240c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
241c58f1c22SToby Isaac   label->ht            = tmpH;
242c58f1c22SToby Isaac   label->points        = tmpP;
243ad8374ffSToby Isaac   label->validIS       = tmpB;
244b9907514SLisandro Dalcin   ierr = PetscHSetICreate(&ht);CHKERRQ(ierr);
245b9907514SLisandro Dalcin   ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr);
246b9907514SLisandro Dalcin   ierr = PetscHMapISet(hmap, value, v);CHKERRQ(ierr);
247b9907514SLisandro Dalcin   tmpV[v] = value;
248b9907514SLisandro Dalcin   tmpS[v] = 0;
249b9907514SLisandro Dalcin   tmpH[v] = ht;
250b9907514SLisandro Dalcin   tmpP[v] = is;
251b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
252277ea44aSLisandro Dalcin   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
2530c3c4a36SLisandro Dalcin   *index = v;
2540c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2550c3c4a36SLisandro Dalcin }
2560c3c4a36SLisandro Dalcin 
257b9907514SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
258b9907514SLisandro Dalcin {
259b9907514SLisandro Dalcin   PetscErrorCode ierr;
260b9907514SLisandro Dalcin   PetscFunctionBegin;
261b9907514SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, index);CHKERRQ(ierr);
262b9907514SLisandro Dalcin   if (*index < 0) {ierr = DMLabelNewStratum(label, value, index);CHKERRQ(ierr);}
263b9907514SLisandro Dalcin   PetscFunctionReturn(0);
264b9907514SLisandro Dalcin }
265b9907514SLisandro Dalcin 
266b9907514SLisandro Dalcin /*@
267b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
268b9907514SLisandro Dalcin 
269b9907514SLisandro Dalcin   Input Parameter:
270b9907514SLisandro Dalcin + label - The DMLabel
271b9907514SLisandro Dalcin - value - The stratum value
272b9907514SLisandro Dalcin 
273b9907514SLisandro Dalcin   Level: beginner
274b9907514SLisandro Dalcin 
275b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
276b9907514SLisandro Dalcin @*/
2770c3c4a36SLisandro Dalcin PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
2780c3c4a36SLisandro Dalcin {
2790c3c4a36SLisandro Dalcin   PetscInt       v;
2800c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
2810c3c4a36SLisandro Dalcin 
2820c3c4a36SLisandro Dalcin   PetscFunctionBegin;
283d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
284b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
285b9907514SLisandro Dalcin   PetscFunctionReturn(0);
286b9907514SLisandro Dalcin }
287b9907514SLisandro Dalcin 
288b9907514SLisandro Dalcin /*@
289b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
290b9907514SLisandro Dalcin 
2915b5e7992SMatthew G. Knepley   Not collective
2925b5e7992SMatthew G. Knepley 
293b9907514SLisandro Dalcin   Input Parameter:
294b9907514SLisandro Dalcin + label - The DMLabel
295b9907514SLisandro Dalcin . numStrata - The number of stratum values
296b9907514SLisandro Dalcin - stratumValues - The stratum values
297b9907514SLisandro Dalcin 
298b9907514SLisandro Dalcin   Level: beginner
299b9907514SLisandro Dalcin 
300b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
301b9907514SLisandro Dalcin @*/
302b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
303b9907514SLisandro Dalcin {
304b9907514SLisandro Dalcin   PetscInt       *values, v;
305b9907514SLisandro Dalcin   PetscErrorCode ierr;
306b9907514SLisandro Dalcin 
307b9907514SLisandro Dalcin   PetscFunctionBegin;
308b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
309b9907514SLisandro Dalcin   if (numStrata) PetscValidIntPointer(stratumValues, 3);
310b9907514SLisandro Dalcin   ierr = PetscMalloc1(numStrata, &values);CHKERRQ(ierr);
311580bdb30SBarry Smith   ierr = PetscArraycpy(values, stratumValues, numStrata);CHKERRQ(ierr);
312b9907514SLisandro Dalcin   ierr = PetscSortRemoveDupsInt(&numStrata, values);CHKERRQ(ierr);
313b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
314b9907514SLisandro Dalcin     PetscInt   *tmpV;
315b9907514SLisandro Dalcin     PetscInt   *tmpS;
316b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
317b9907514SLisandro Dalcin     IS         *tmpP, is;
318b9907514SLisandro Dalcin     PetscBool  *tmpB;
319b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
320b9907514SLisandro Dalcin 
321b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpV);CHKERRQ(ierr);
322b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpS);CHKERRQ(ierr);
323b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpH);CHKERRQ(ierr);
324b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpP);CHKERRQ(ierr);
325b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpB);CHKERRQ(ierr);
326b9907514SLisandro Dalcin     label->numStrata     = numStrata;
327b9907514SLisandro Dalcin     label->stratumValues = tmpV;
328b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
329b9907514SLisandro Dalcin     label->ht            = tmpH;
330b9907514SLisandro Dalcin     label->points        = tmpP;
331b9907514SLisandro Dalcin     label->validIS       = tmpB;
332b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
333b9907514SLisandro Dalcin       ierr = PetscHSetICreate(&ht);CHKERRQ(ierr);
334b9907514SLisandro Dalcin       ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr);
335b9907514SLisandro Dalcin       ierr = PetscHMapISet(hmap, values[v], v);CHKERRQ(ierr);
336b9907514SLisandro Dalcin       tmpV[v] = values[v];
337b9907514SLisandro Dalcin       tmpS[v] = 0;
338b9907514SLisandro Dalcin       tmpH[v] = ht;
339b9907514SLisandro Dalcin       tmpP[v] = is;
340b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
341b9907514SLisandro Dalcin     }
342277ea44aSLisandro Dalcin     ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
343b9907514SLisandro Dalcin   } else {
344b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
345b9907514SLisandro Dalcin       ierr = DMLabelAddStratum(label, values[v]);CHKERRQ(ierr);
346b9907514SLisandro Dalcin     }
347b9907514SLisandro Dalcin   }
348b9907514SLisandro Dalcin   ierr = PetscFree(values);CHKERRQ(ierr);
349b9907514SLisandro Dalcin   PetscFunctionReturn(0);
350b9907514SLisandro Dalcin }
351b9907514SLisandro Dalcin 
352b9907514SLisandro Dalcin /*@
353b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
354b9907514SLisandro Dalcin 
3555b5e7992SMatthew G. Knepley   Not collective
3565b5e7992SMatthew G. Knepley 
357b9907514SLisandro Dalcin   Input Parameter:
358b9907514SLisandro Dalcin + label - The DMLabel
359b9907514SLisandro Dalcin - valueIS - Index set with stratum values
360b9907514SLisandro Dalcin 
361b9907514SLisandro Dalcin   Level: beginner
362b9907514SLisandro Dalcin 
363b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
364b9907514SLisandro Dalcin @*/
365b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
366b9907514SLisandro Dalcin {
367b9907514SLisandro Dalcin   PetscInt       numStrata;
368b9907514SLisandro Dalcin   const PetscInt *stratumValues;
369b9907514SLisandro Dalcin   PetscErrorCode ierr;
370b9907514SLisandro Dalcin 
371b9907514SLisandro Dalcin   PetscFunctionBegin;
372b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
373b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
374b9907514SLisandro Dalcin   ierr = ISGetLocalSize(valueIS, &numStrata);CHKERRQ(ierr);
375b9907514SLisandro Dalcin   ierr = ISGetIndices(valueIS, &stratumValues);CHKERRQ(ierr);
376b9907514SLisandro Dalcin   ierr = DMLabelAddStrata(label, numStrata, stratumValues);CHKERRQ(ierr);
377c58f1c22SToby Isaac   PetscFunctionReturn(0);
378c58f1c22SToby Isaac }
379c58f1c22SToby Isaac 
380c58f1c22SToby Isaac static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer)
381c58f1c22SToby Isaac {
382c58f1c22SToby Isaac   PetscInt       v;
383c58f1c22SToby Isaac   PetscMPIInt    rank;
384c58f1c22SToby Isaac   PetscErrorCode ierr;
385c58f1c22SToby Isaac 
386c58f1c22SToby Isaac   PetscFunctionBegin;
387c58f1c22SToby Isaac   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr);
388c58f1c22SToby Isaac   ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
389c58f1c22SToby Isaac   if (label) {
390d67d17b1SMatthew G. Knepley     const char *name;
391d67d17b1SMatthew G. Knepley 
392d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
393d67d17b1SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name);CHKERRQ(ierr);
394c58f1c22SToby Isaac     if (label->bt) {ierr = PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%D, %D)\n", label->pStart, label->pEnd);CHKERRQ(ierr);}
395c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
396c58f1c22SToby Isaac       const PetscInt value = label->stratumValues[v];
397ad8374ffSToby Isaac       const PetscInt *points;
398c58f1c22SToby Isaac       PetscInt       p;
399c58f1c22SToby Isaac 
400ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
401c58f1c22SToby Isaac       for (p = 0; p < label->stratumSizes[v]; ++p) {
402ad8374ffSToby Isaac         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D (%D)\n", rank, points[p], value);CHKERRQ(ierr);
403c58f1c22SToby Isaac       }
404ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr);
405c58f1c22SToby Isaac     }
406c58f1c22SToby Isaac   }
407c58f1c22SToby Isaac   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
408c58f1c22SToby Isaac   ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
409c58f1c22SToby Isaac   PetscFunctionReturn(0);
410c58f1c22SToby Isaac }
411c58f1c22SToby Isaac 
412c58f1c22SToby Isaac /*@C
413c58f1c22SToby Isaac   DMLabelView - View the label
414c58f1c22SToby Isaac 
4155b5e7992SMatthew G. Knepley   Collective on viewer
4165b5e7992SMatthew G. Knepley 
417c58f1c22SToby Isaac   Input Parameters:
418c58f1c22SToby Isaac + label - The DMLabel
419c58f1c22SToby Isaac - viewer - The PetscViewer
420c58f1c22SToby Isaac 
421c58f1c22SToby Isaac   Level: intermediate
422c58f1c22SToby Isaac 
423c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelDestroy()
424c58f1c22SToby Isaac @*/
425c58f1c22SToby Isaac PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
426c58f1c22SToby Isaac {
427c58f1c22SToby Isaac   PetscBool      iascii;
428c58f1c22SToby Isaac   PetscErrorCode ierr;
429c58f1c22SToby Isaac 
430c58f1c22SToby Isaac   PetscFunctionBegin;
431d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
432b9907514SLisandro Dalcin   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer);CHKERRQ(ierr);}
433c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
434c58f1c22SToby Isaac   if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);}
435c58f1c22SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
436c58f1c22SToby Isaac   if (iascii) {
437c58f1c22SToby Isaac     ierr = DMLabelView_Ascii(label, viewer);CHKERRQ(ierr);
438c58f1c22SToby Isaac   }
439c58f1c22SToby Isaac   PetscFunctionReturn(0);
440c58f1c22SToby Isaac }
441c58f1c22SToby Isaac 
44284f0b6dfSMatthew G. Knepley /*@
443d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
444d67d17b1SMatthew G. Knepley 
4455b5e7992SMatthew G. Knepley   Not collective
4465b5e7992SMatthew G. Knepley 
447d67d17b1SMatthew G. Knepley   Input Parameter:
448d67d17b1SMatthew G. Knepley . label - The DMLabel
449d67d17b1SMatthew G. Knepley 
450d67d17b1SMatthew G. Knepley   Level: beginner
451d67d17b1SMatthew G. Knepley 
452d67d17b1SMatthew G. Knepley .seealso: DMLabelDestroy(), DMLabelCreate()
453d67d17b1SMatthew G. Knepley @*/
454d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelReset(DMLabel label)
455d67d17b1SMatthew G. Knepley {
456d67d17b1SMatthew G. Knepley   PetscInt       v;
457d67d17b1SMatthew G. Knepley   PetscErrorCode ierr;
458d67d17b1SMatthew G. Knepley 
459d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
460d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
461d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
462d67d17b1SMatthew G. Knepley     ierr = PetscHSetIDestroy(&label->ht[v]);CHKERRQ(ierr);
463d67d17b1SMatthew G. Knepley     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
464d67d17b1SMatthew G. Knepley   }
465b9907514SLisandro Dalcin   label->numStrata = 0;
466b9907514SLisandro Dalcin   ierr = PetscFree(label->stratumValues);CHKERRQ(ierr);
467b9907514SLisandro Dalcin   ierr = PetscFree(label->stratumSizes);CHKERRQ(ierr);
468d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->ht);CHKERRQ(ierr);
469d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->points);CHKERRQ(ierr);
470d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->validIS);CHKERRQ(ierr);
471b9907514SLisandro Dalcin   ierr = PetscHMapIReset(label->hmap);CHKERRQ(ierr);
472b9907514SLisandro Dalcin   label->pStart = -1;
473b9907514SLisandro Dalcin   label->pEnd   = -1;
474d67d17b1SMatthew G. Knepley   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
475d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
476d67d17b1SMatthew G. Knepley }
477d67d17b1SMatthew G. Knepley 
478d67d17b1SMatthew G. Knepley /*@
47984f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
48084f0b6dfSMatthew G. Knepley 
4815b5e7992SMatthew G. Knepley   Collective on label
4825b5e7992SMatthew G. Knepley 
48384f0b6dfSMatthew G. Knepley   Input Parameter:
48484f0b6dfSMatthew G. Knepley . label - The DMLabel
48584f0b6dfSMatthew G. Knepley 
48684f0b6dfSMatthew G. Knepley   Level: beginner
48784f0b6dfSMatthew G. Knepley 
488d67d17b1SMatthew G. Knepley .seealso: DMLabelReset(), DMLabelCreate()
48984f0b6dfSMatthew G. Knepley @*/
490c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
491c58f1c22SToby Isaac {
492c58f1c22SToby Isaac   PetscErrorCode ierr;
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);}
498d67d17b1SMatthew G. Knepley   ierr = DMLabelReset(*label);CHKERRQ(ierr);
499b9907514SLisandro Dalcin   ierr = PetscHMapIDestroy(&(*label)->hmap);CHKERRQ(ierr);
500d67d17b1SMatthew G. Knepley   ierr = PetscHeaderDestroy(label);CHKERRQ(ierr);
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 
51784f0b6dfSMatthew G. Knepley .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   PetscErrorCode ierr;
524c58f1c22SToby Isaac 
525c58f1c22SToby Isaac   PetscFunctionBegin;
526d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
527c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
528d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
529d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew);CHKERRQ(ierr);
530c58f1c22SToby Isaac 
531c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5325aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
533c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues);CHKERRQ(ierr);
534c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes);CHKERRQ(ierr);
535c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->ht);CHKERRQ(ierr);
536c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->points);CHKERRQ(ierr);
537ad8374ffSToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->validIS);CHKERRQ(ierr);
538c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
539e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelnew)->ht[v]);CHKERRQ(ierr);
540c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
541c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
542ad8374ffSToby Isaac     ierr = PetscObjectReference((PetscObject) (label->points[v]));CHKERRQ(ierr);
543ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
544b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
545c58f1c22SToby Isaac   }
546f14fe40dSLisandro Dalcin   ierr = PetscHMapIDestroy(&(*labelnew)->hmap);CHKERRQ(ierr);
547b9907514SLisandro Dalcin   ierr = PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap);CHKERRQ(ierr);
548c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
549c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
550c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
551c58f1c22SToby Isaac   PetscFunctionReturn(0);
552c58f1c22SToby Isaac }
553c58f1c22SToby Isaac 
554c6a43d28SMatthew G. Knepley /*@
555c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
556c6a43d28SMatthew G. Knepley 
5575b5e7992SMatthew G. Knepley   Not collective
5585b5e7992SMatthew G. Knepley 
559c6a43d28SMatthew G. Knepley   Input Parameter:
560c6a43d28SMatthew G. Knepley . label  - The DMLabel
561c6a43d28SMatthew G. Knepley 
562c6a43d28SMatthew G. Knepley   Level: intermediate
563c6a43d28SMatthew G. Knepley 
564c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
565c6a43d28SMatthew G. Knepley @*/
566c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
567c6a43d28SMatthew G. Knepley {
568c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
569c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
570c6a43d28SMatthew G. Knepley 
571c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
572c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
573c6a43d28SMatthew G. Knepley   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
574c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
575c6a43d28SMatthew G. Knepley     const PetscInt *points;
576c6a43d28SMatthew G. Knepley     PetscInt       i;
577c6a43d28SMatthew G. Knepley 
578c6a43d28SMatthew G. Knepley     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
579c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
580c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
581c6a43d28SMatthew G. Knepley 
582c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
583c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
584c6a43d28SMatthew G. Knepley     }
585c6a43d28SMatthew G. Knepley     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
586c6a43d28SMatthew G. Knepley   }
587c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
588c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
589c6a43d28SMatthew G. Knepley   ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
590c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
591c6a43d28SMatthew G. Knepley }
592c6a43d28SMatthew G. Knepley 
593c6a43d28SMatthew G. Knepley /*@
594c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
595c6a43d28SMatthew G. Knepley 
5965b5e7992SMatthew G. Knepley   Not collective
5975b5e7992SMatthew G. Knepley 
598c6a43d28SMatthew G. Knepley   Input Parameters:
599c6a43d28SMatthew G. Knepley + label  - The DMLabel
600c6a43d28SMatthew G. Knepley . pStart - The smallest point
601c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
602c6a43d28SMatthew G. Knepley 
603c6a43d28SMatthew G. Knepley   Level: intermediate
604c6a43d28SMatthew G. Knepley 
605c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelComputeIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
606c6a43d28SMatthew G. Knepley @*/
607c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
608c58f1c22SToby Isaac {
609c58f1c22SToby Isaac   PetscInt       v;
610c58f1c22SToby Isaac   PetscErrorCode ierr;
611c58f1c22SToby Isaac 
612c58f1c22SToby Isaac   PetscFunctionBegin;
613d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6140c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
615c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
616c58f1c22SToby Isaac   label->pStart = pStart;
617c58f1c22SToby Isaac   label->pEnd   = pEnd;
618c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
619c58f1c22SToby Isaac   ierr = PetscBTCreate(pEnd - pStart, &label->bt);CHKERRQ(ierr);
620c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
621ad8374ffSToby Isaac     const PetscInt *points;
622c58f1c22SToby Isaac     PetscInt       i;
623c58f1c22SToby Isaac 
624ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
625c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
626ad8374ffSToby Isaac       const PetscInt point = points[i];
627c58f1c22SToby Isaac 
628c58f1c22SToby Isaac       if ((point < pStart) || (point >= pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, pStart, pEnd);
629c58f1c22SToby Isaac       ierr = PetscBTSet(label->bt, point - pStart);CHKERRQ(ierr);
630c58f1c22SToby Isaac     }
631ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
632c58f1c22SToby Isaac   }
633c58f1c22SToby Isaac   PetscFunctionReturn(0);
634c58f1c22SToby Isaac }
635c58f1c22SToby Isaac 
636c6a43d28SMatthew G. Knepley /*@
637c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
638c6a43d28SMatthew G. Knepley 
6395b5e7992SMatthew G. Knepley   Not collective
6405b5e7992SMatthew G. Knepley 
641c6a43d28SMatthew G. Knepley   Input Parameter:
642c6a43d28SMatthew G. Knepley . label - the DMLabel
643c6a43d28SMatthew G. Knepley 
644c6a43d28SMatthew G. Knepley   Level: intermediate
645c6a43d28SMatthew G. Knepley 
646c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
647c6a43d28SMatthew G. Knepley @*/
648c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
649c58f1c22SToby Isaac {
650c58f1c22SToby Isaac   PetscErrorCode ierr;
651c58f1c22SToby Isaac 
652c58f1c22SToby Isaac   PetscFunctionBegin;
653d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
654c58f1c22SToby Isaac   label->pStart = -1;
655c58f1c22SToby Isaac   label->pEnd   = -1;
6560c3c4a36SLisandro Dalcin   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
657c58f1c22SToby Isaac   PetscFunctionReturn(0);
658c58f1c22SToby Isaac }
659c58f1c22SToby Isaac 
660c58f1c22SToby Isaac /*@
661c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
662c6a43d28SMatthew G. Knepley 
6635b5e7992SMatthew G. Knepley   Not collective
6645b5e7992SMatthew G. Knepley 
665c6a43d28SMatthew G. Knepley   Input Parameter:
666c6a43d28SMatthew G. Knepley . label - the DMLabel
667c6a43d28SMatthew G. Knepley 
668c6a43d28SMatthew G. Knepley   Output Parameters:
669c6a43d28SMatthew G. Knepley + pStart - The smallest point
670c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
671c6a43d28SMatthew G. Knepley 
672c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
673c6a43d28SMatthew G. Knepley 
674c6a43d28SMatthew G. Knepley   Level: intermediate
675c6a43d28SMatthew G. Knepley 
676c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
677c6a43d28SMatthew G. Knepley @*/
678c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
679c6a43d28SMatthew G. Knepley {
680c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
681c6a43d28SMatthew G. Knepley 
682c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
683c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
684c6a43d28SMatthew G. Knepley   if ((label->pStart == -1) && (label->pEnd == -1)) {ierr = DMLabelComputeIndex(label);CHKERRQ(ierr);}
685c6a43d28SMatthew G. Knepley   if (pStart) {
686534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
687c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
688c6a43d28SMatthew G. Knepley   }
689c6a43d28SMatthew G. Knepley   if (pEnd) {
690534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
691c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
692c6a43d28SMatthew G. Knepley   }
693c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
694c6a43d28SMatthew G. Knepley }
695c6a43d28SMatthew G. Knepley 
696c6a43d28SMatthew G. Knepley /*@
697c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
698c58f1c22SToby Isaac 
6995b5e7992SMatthew G. Knepley   Not collective
7005b5e7992SMatthew G. Knepley 
701c58f1c22SToby Isaac   Input Parameters:
702c58f1c22SToby Isaac + label - the DMLabel
703c58f1c22SToby Isaac - value - the value
704c58f1c22SToby Isaac 
705c58f1c22SToby Isaac   Output Parameter:
706c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
707c58f1c22SToby Isaac 
708c58f1c22SToby Isaac   Level: developer
709c58f1c22SToby Isaac 
710c58f1c22SToby Isaac .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue()
711c58f1c22SToby Isaac @*/
712c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
713c58f1c22SToby Isaac {
714c58f1c22SToby Isaac   PetscInt v;
7150c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
716c58f1c22SToby Isaac 
717c58f1c22SToby Isaac   PetscFunctionBegin;
718d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
719534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
7200c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
7210c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
722c58f1c22SToby Isaac   PetscFunctionReturn(0);
723c58f1c22SToby Isaac }
724c58f1c22SToby Isaac 
725c58f1c22SToby Isaac /*@
726c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
727c58f1c22SToby Isaac 
7285b5e7992SMatthew G. Knepley   Not collective
7295b5e7992SMatthew G. Knepley 
730c58f1c22SToby Isaac   Input Parameters:
731c58f1c22SToby Isaac + label - the DMLabel
732c58f1c22SToby Isaac - point - the point
733c58f1c22SToby Isaac 
734c58f1c22SToby Isaac   Output Parameter:
735c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
736c58f1c22SToby Isaac 
737c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
738c58f1c22SToby Isaac 
739c58f1c22SToby Isaac   Level: developer
740c58f1c22SToby Isaac 
741c58f1c22SToby Isaac .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
742c58f1c22SToby Isaac @*/
743c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
744c58f1c22SToby Isaac {
745c58f1c22SToby Isaac   PetscErrorCode ierr;
746c58f1c22SToby Isaac 
747c58f1c22SToby Isaac   PetscFunctionBeginHot;
748d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
749534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
750c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
751*76bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
752c58f1c22SToby Isaac     if (!label->bt) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
753c58f1c22SToby Isaac     if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
754*76bd3646SJed Brown   }
755c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
756c58f1c22SToby Isaac   PetscFunctionReturn(0);
757c58f1c22SToby Isaac }
758c58f1c22SToby Isaac 
759c58f1c22SToby Isaac /*@
760c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
761c58f1c22SToby Isaac 
7625b5e7992SMatthew G. Knepley   Not collective
7635b5e7992SMatthew G. Knepley 
764c58f1c22SToby Isaac   Input Parameters:
765c58f1c22SToby Isaac + label - the DMLabel
766c58f1c22SToby Isaac . value - the stratum value
767c58f1c22SToby Isaac - point - the point
768c58f1c22SToby Isaac 
769c58f1c22SToby Isaac   Output Parameter:
770c58f1c22SToby Isaac . contains - true if the stratum contains the point
771c58f1c22SToby Isaac 
772c58f1c22SToby Isaac   Level: intermediate
773c58f1c22SToby Isaac 
774c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue()
775c58f1c22SToby Isaac @*/
776c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
777c58f1c22SToby Isaac {
778c58f1c22SToby Isaac   PetscInt       v;
779c58f1c22SToby Isaac   PetscErrorCode ierr;
780c58f1c22SToby Isaac 
7810c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
782d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
783534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
784c58f1c22SToby Isaac   *contains = PETSC_FALSE;
7850c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
7860c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
7870c3c4a36SLisandro Dalcin 
788ad8374ffSToby Isaac   if (label->validIS[v]) {
789c58f1c22SToby Isaac     PetscInt i;
790c58f1c22SToby Isaac 
791a2d74346SToby Isaac     ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
7920c3c4a36SLisandro Dalcin     if (i >= 0) *contains = PETSC_TRUE;
793c58f1c22SToby Isaac   } else {
794c58f1c22SToby Isaac     PetscBool has;
795c58f1c22SToby Isaac 
796b9907514SLisandro Dalcin     ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
7970c3c4a36SLisandro Dalcin     if (has) *contains = PETSC_TRUE;
798c58f1c22SToby Isaac   }
799c58f1c22SToby Isaac   PetscFunctionReturn(0);
800c58f1c22SToby Isaac }
801c58f1c22SToby Isaac 
80284f0b6dfSMatthew G. Knepley /*@
8035aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8045aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8055aa44df4SToby Isaac 
8065b5e7992SMatthew G. Knepley   Not collective
8075b5e7992SMatthew G. Knepley 
8085aa44df4SToby Isaac   Input parameter:
8095aa44df4SToby Isaac . label - a DMLabel object
8105aa44df4SToby Isaac 
8115aa44df4SToby Isaac   Output parameter:
8125aa44df4SToby Isaac . defaultValue - the default value
8135aa44df4SToby Isaac 
8145aa44df4SToby Isaac   Level: beginner
8155aa44df4SToby Isaac 
8165aa44df4SToby Isaac .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
81784f0b6dfSMatthew G. Knepley @*/
8185aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
8195aa44df4SToby Isaac {
8205aa44df4SToby Isaac   PetscFunctionBegin;
821d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8225aa44df4SToby Isaac   *defaultValue = label->defaultValue;
8235aa44df4SToby Isaac   PetscFunctionReturn(0);
8245aa44df4SToby Isaac }
8255aa44df4SToby Isaac 
82684f0b6dfSMatthew G. Knepley /*@
8275aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8285aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8295aa44df4SToby Isaac 
8305b5e7992SMatthew G. Knepley   Not collective
8315b5e7992SMatthew G. Knepley 
8325aa44df4SToby Isaac   Input parameter:
8335aa44df4SToby Isaac . label - a DMLabel object
8345aa44df4SToby Isaac 
8355aa44df4SToby Isaac   Output parameter:
8365aa44df4SToby Isaac . defaultValue - the default value
8375aa44df4SToby Isaac 
8385aa44df4SToby Isaac   Level: beginner
8395aa44df4SToby Isaac 
8405aa44df4SToby Isaac .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
84184f0b6dfSMatthew G. Knepley @*/
8425aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
8435aa44df4SToby Isaac {
8445aa44df4SToby Isaac   PetscFunctionBegin;
845d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8465aa44df4SToby Isaac   label->defaultValue = defaultValue;
8475aa44df4SToby Isaac   PetscFunctionReturn(0);
8485aa44df4SToby Isaac }
8495aa44df4SToby Isaac 
850c58f1c22SToby Isaac /*@
8515aa44df4SToby 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())
852c58f1c22SToby Isaac 
8535b5e7992SMatthew G. Knepley   Not collective
8545b5e7992SMatthew G. Knepley 
855c58f1c22SToby Isaac   Input Parameters:
856c58f1c22SToby Isaac + label - the DMLabel
857c58f1c22SToby Isaac - point - the point
858c58f1c22SToby Isaac 
859c58f1c22SToby Isaac   Output Parameter:
8608e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
861c58f1c22SToby Isaac 
862c58f1c22SToby Isaac   Level: intermediate
863c58f1c22SToby Isaac 
8645aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
865c58f1c22SToby Isaac @*/
866c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
867c58f1c22SToby Isaac {
868c58f1c22SToby Isaac   PetscInt       v;
869c58f1c22SToby Isaac   PetscErrorCode ierr;
870c58f1c22SToby Isaac 
8710c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
872d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
873c58f1c22SToby Isaac   PetscValidPointer(value, 3);
8745aa44df4SToby Isaac   *value = label->defaultValue;
875c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
876ad8374ffSToby Isaac     if (label->validIS[v]) {
877c58f1c22SToby Isaac       PetscInt i;
878c58f1c22SToby Isaac 
879a2d74346SToby Isaac       ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
880c58f1c22SToby Isaac       if (i >= 0) {
881c58f1c22SToby Isaac         *value = label->stratumValues[v];
882c58f1c22SToby Isaac         break;
883c58f1c22SToby Isaac       }
884c58f1c22SToby Isaac     } else {
885c58f1c22SToby Isaac       PetscBool has;
886c58f1c22SToby Isaac 
887b9907514SLisandro Dalcin       ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
888c58f1c22SToby Isaac       if (has) {
889c58f1c22SToby Isaac         *value = label->stratumValues[v];
890c58f1c22SToby Isaac         break;
891c58f1c22SToby Isaac       }
892c58f1c22SToby Isaac     }
893c58f1c22SToby Isaac   }
894c58f1c22SToby Isaac   PetscFunctionReturn(0);
895c58f1c22SToby Isaac }
896c58f1c22SToby Isaac 
897c58f1c22SToby Isaac /*@
898367003a6SStefano 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.
899c58f1c22SToby Isaac 
9005b5e7992SMatthew G. Knepley   Not collective
9015b5e7992SMatthew G. Knepley 
902c58f1c22SToby Isaac   Input Parameters:
903c58f1c22SToby Isaac + label - the DMLabel
904c58f1c22SToby Isaac . point - the point
905c58f1c22SToby Isaac - value - The point value
906c58f1c22SToby Isaac 
907c58f1c22SToby Isaac   Level: intermediate
908c58f1c22SToby Isaac 
9095aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
910c58f1c22SToby Isaac @*/
911c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
912c58f1c22SToby Isaac {
913c58f1c22SToby Isaac   PetscInt       v;
914c58f1c22SToby Isaac   PetscErrorCode ierr;
915c58f1c22SToby Isaac 
916c58f1c22SToby Isaac   PetscFunctionBegin;
917d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9180c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
9195aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
920b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
921c58f1c22SToby Isaac   /* Set key */
9220c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
923e8f14785SLisandro Dalcin   ierr = PetscHSetIAdd(label->ht[v], point);CHKERRQ(ierr);
924c58f1c22SToby Isaac   PetscFunctionReturn(0);
925c58f1c22SToby Isaac }
926c58f1c22SToby Isaac 
927c58f1c22SToby Isaac /*@
928c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
929c58f1c22SToby Isaac 
9305b5e7992SMatthew G. Knepley   Not collective
9315b5e7992SMatthew G. Knepley 
932c58f1c22SToby Isaac   Input Parameters:
933c58f1c22SToby Isaac + label - the DMLabel
934c58f1c22SToby Isaac . point - the point
935c58f1c22SToby Isaac - value - The point value
936c58f1c22SToby Isaac 
937c58f1c22SToby Isaac   Level: intermediate
938c58f1c22SToby Isaac 
939c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue()
940c58f1c22SToby Isaac @*/
941c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
942c58f1c22SToby Isaac {
943ad8374ffSToby Isaac   PetscInt       v;
944c58f1c22SToby Isaac   PetscErrorCode ierr;
945c58f1c22SToby Isaac 
946c58f1c22SToby Isaac   PetscFunctionBegin;
947d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
948c58f1c22SToby Isaac   /* Find label value */
9490c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
9500c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
9510c3c4a36SLisandro Dalcin 
952eeed21e7SToby Isaac   if (label->bt) {
953eeed21e7SToby Isaac     if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
954eeed21e7SToby Isaac     ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
955eeed21e7SToby Isaac   }
9560c3c4a36SLisandro Dalcin 
9570c3c4a36SLisandro Dalcin   /* Delete key */
9580c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
959e8f14785SLisandro Dalcin   ierr = PetscHSetIDel(label->ht[v], point);CHKERRQ(ierr);
960c58f1c22SToby Isaac   PetscFunctionReturn(0);
961c58f1c22SToby Isaac }
962c58f1c22SToby Isaac 
963c58f1c22SToby Isaac /*@
964c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
965c58f1c22SToby Isaac 
9665b5e7992SMatthew G. Knepley   Not collective
9675b5e7992SMatthew G. Knepley 
968c58f1c22SToby Isaac   Input Parameters:
969c58f1c22SToby Isaac + label - the DMLabel
970c58f1c22SToby Isaac . is    - the point IS
971c58f1c22SToby Isaac - value - The point value
972c58f1c22SToby Isaac 
973c58f1c22SToby Isaac   Level: intermediate
974c58f1c22SToby Isaac 
975c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
976c58f1c22SToby Isaac @*/
977c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
978c58f1c22SToby Isaac {
9790c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
980c58f1c22SToby Isaac   const PetscInt *points;
981c58f1c22SToby Isaac   PetscErrorCode  ierr;
982c58f1c22SToby Isaac 
983c58f1c22SToby Isaac   PetscFunctionBegin;
984d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
985c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9860c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
9870c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
988b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
9890c3c4a36SLisandro Dalcin   /* Set keys */
9900c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
991c58f1c22SToby Isaac   ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr);
992c58f1c22SToby Isaac   ierr = ISGetIndices(is, &points);CHKERRQ(ierr);
993e8f14785SLisandro Dalcin   for (p = 0; p < n; ++p) {ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);}
994c58f1c22SToby Isaac   ierr = ISRestoreIndices(is, &points);CHKERRQ(ierr);
995c58f1c22SToby Isaac   PetscFunctionReturn(0);
996c58f1c22SToby Isaac }
997c58f1c22SToby Isaac 
99884f0b6dfSMatthew G. Knepley /*@
99984f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
100084f0b6dfSMatthew G. Knepley 
10015b5e7992SMatthew G. Knepley   Not collective
10025b5e7992SMatthew G. Knepley 
100384f0b6dfSMatthew G. Knepley   Input Parameter:
100484f0b6dfSMatthew G. Knepley . label - the DMLabel
100584f0b6dfSMatthew G. Knepley 
100684f0b6dfSMatthew G. Knepley   Output Paramater:
100784f0b6dfSMatthew G. Knepley . numValues - the number of values
100884f0b6dfSMatthew G. Knepley 
100984f0b6dfSMatthew G. Knepley   Level: intermediate
101084f0b6dfSMatthew G. Knepley 
101184f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
101284f0b6dfSMatthew G. Knepley @*/
1013c58f1c22SToby Isaac PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1014c58f1c22SToby Isaac {
1015c58f1c22SToby Isaac   PetscFunctionBegin;
1016d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1017c58f1c22SToby Isaac   PetscValidPointer(numValues, 2);
1018c58f1c22SToby Isaac   *numValues = label->numStrata;
1019c58f1c22SToby Isaac   PetscFunctionReturn(0);
1020c58f1c22SToby Isaac }
1021c58f1c22SToby Isaac 
102284f0b6dfSMatthew G. Knepley /*@
102384f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
102484f0b6dfSMatthew G. Knepley 
10255b5e7992SMatthew G. Knepley   Not collective
10265b5e7992SMatthew G. Knepley 
102784f0b6dfSMatthew G. Knepley   Input Parameter:
102884f0b6dfSMatthew G. Knepley . label - the DMLabel
102984f0b6dfSMatthew G. Knepley 
103084f0b6dfSMatthew G. Knepley   Output Paramater:
103184f0b6dfSMatthew G. Knepley . is    - the value IS
103284f0b6dfSMatthew G. Knepley 
103384f0b6dfSMatthew G. Knepley   Level: intermediate
103484f0b6dfSMatthew G. Knepley 
103584f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
103684f0b6dfSMatthew G. Knepley @*/
1037c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1038c58f1c22SToby Isaac {
1039c58f1c22SToby Isaac   PetscErrorCode ierr;
1040c58f1c22SToby Isaac 
1041c58f1c22SToby Isaac   PetscFunctionBegin;
1042d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1043c58f1c22SToby Isaac   PetscValidPointer(values, 2);
1044c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values);CHKERRQ(ierr);
1045c58f1c22SToby Isaac   PetscFunctionReturn(0);
1046c58f1c22SToby Isaac }
1047c58f1c22SToby Isaac 
104884f0b6dfSMatthew G. Knepley /*@
104984f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
105084f0b6dfSMatthew G. Knepley 
10515b5e7992SMatthew G. Knepley   Not collective
10525b5e7992SMatthew G. Knepley 
105384f0b6dfSMatthew G. Knepley   Input Parameters:
105484f0b6dfSMatthew G. Knepley + label - the DMLabel
105584f0b6dfSMatthew G. Knepley - value - the stratum value
105684f0b6dfSMatthew G. Knepley 
105784f0b6dfSMatthew G. Knepley   Output Paramater:
105884f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
105984f0b6dfSMatthew G. Knepley 
106084f0b6dfSMatthew G. Knepley   Level: intermediate
106184f0b6dfSMatthew G. Knepley 
106284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
106384f0b6dfSMatthew G. Knepley @*/
1064fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1065fada774cSMatthew G. Knepley {
1066fada774cSMatthew G. Knepley   PetscInt       v;
10670c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
1068fada774cSMatthew G. Knepley 
1069fada774cSMatthew G. Knepley   PetscFunctionBegin;
1070d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1071fada774cSMatthew G. Knepley   PetscValidPointer(exists, 3);
10720c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
10730c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1074fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1075fada774cSMatthew G. Knepley }
1076fada774cSMatthew G. Knepley 
107784f0b6dfSMatthew G. Knepley /*@
107884f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
107984f0b6dfSMatthew G. Knepley 
10805b5e7992SMatthew G. Knepley   Not collective
10815b5e7992SMatthew G. Knepley 
108284f0b6dfSMatthew G. Knepley   Input Parameters:
108384f0b6dfSMatthew G. Knepley + label - the DMLabel
108484f0b6dfSMatthew G. Knepley - value - the stratum value
108584f0b6dfSMatthew G. Knepley 
108684f0b6dfSMatthew G. Knepley   Output Paramater:
108784f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
108884f0b6dfSMatthew G. Knepley 
108984f0b6dfSMatthew G. Knepley   Level: intermediate
109084f0b6dfSMatthew G. Knepley 
109184f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
109284f0b6dfSMatthew G. Knepley @*/
1093c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1094c58f1c22SToby Isaac {
1095c58f1c22SToby Isaac   PetscInt       v;
1096c58f1c22SToby Isaac   PetscErrorCode ierr;
1097c58f1c22SToby Isaac 
1098c58f1c22SToby Isaac   PetscFunctionBegin;
1099d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1100c58f1c22SToby Isaac   PetscValidPointer(size, 3);
1101c58f1c22SToby Isaac   *size = 0;
11020c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11030c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1104c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1105c58f1c22SToby Isaac   *size = label->stratumSizes[v];
1106c58f1c22SToby Isaac   PetscFunctionReturn(0);
1107c58f1c22SToby Isaac }
1108c58f1c22SToby Isaac 
110984f0b6dfSMatthew G. Knepley /*@
111084f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
111184f0b6dfSMatthew G. Knepley 
11125b5e7992SMatthew G. Knepley   Not collective
11135b5e7992SMatthew G. Knepley 
111484f0b6dfSMatthew G. Knepley   Input Parameters:
111584f0b6dfSMatthew G. Knepley + label - the DMLabel
111684f0b6dfSMatthew G. Knepley - value - the stratum value
111784f0b6dfSMatthew G. Knepley 
111884f0b6dfSMatthew G. Knepley   Output Paramaters:
111984f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
112084f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
112184f0b6dfSMatthew G. Knepley 
112284f0b6dfSMatthew G. Knepley   Level: intermediate
112384f0b6dfSMatthew G. Knepley 
112484f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
112584f0b6dfSMatthew G. Knepley @*/
1126c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1127c58f1c22SToby Isaac {
11280c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1129c58f1c22SToby Isaac   PetscErrorCode ierr;
1130c58f1c22SToby Isaac 
1131c58f1c22SToby Isaac   PetscFunctionBegin;
1132d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1133412e9a14SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = label->defaultValue;}
1134412e9a14SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = label->defaultValue;}
11350c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11360c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1137c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
11380c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
1139d6cb179aSToby Isaac   ierr = ISGetMinMax(label->points[v], &min, &max);CHKERRQ(ierr);
1140d6cb179aSToby Isaac   if (start) *start = min;
1141d6cb179aSToby Isaac   if (end)   *end   = max+1;
1142c58f1c22SToby Isaac   PetscFunctionReturn(0);
1143c58f1c22SToby Isaac }
1144c58f1c22SToby Isaac 
114584f0b6dfSMatthew G. Knepley /*@
114684f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
114784f0b6dfSMatthew G. Knepley 
11485b5e7992SMatthew G. Knepley   Not collective
11495b5e7992SMatthew G. Knepley 
115084f0b6dfSMatthew G. Knepley   Input Parameters:
115184f0b6dfSMatthew G. Knepley + label - the DMLabel
115284f0b6dfSMatthew G. Knepley - value - the stratum value
115384f0b6dfSMatthew G. Knepley 
115484f0b6dfSMatthew G. Knepley   Output Paramater:
115584f0b6dfSMatthew G. Knepley . points - The stratum points
115684f0b6dfSMatthew G. Knepley 
115784f0b6dfSMatthew G. Knepley   Level: intermediate
115884f0b6dfSMatthew G. Knepley 
1159593ce467SVaclav Hapla   Notes:
1160593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1161593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1162593ce467SVaclav Hapla 
116384f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
116484f0b6dfSMatthew G. Knepley @*/
1165c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1166c58f1c22SToby Isaac {
1167c58f1c22SToby Isaac   PetscInt       v;
1168c58f1c22SToby Isaac   PetscErrorCode ierr;
1169c58f1c22SToby Isaac 
1170c58f1c22SToby Isaac   PetscFunctionBegin;
1171d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1172c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1173c58f1c22SToby Isaac   *points = NULL;
11740c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11750c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1176c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1177ad8374ffSToby Isaac   ierr = PetscObjectReference((PetscObject) label->points[v]);CHKERRQ(ierr);
1178ad8374ffSToby Isaac   *points = label->points[v];
1179c58f1c22SToby Isaac   PetscFunctionReturn(0);
1180c58f1c22SToby Isaac }
1181c58f1c22SToby Isaac 
118284f0b6dfSMatthew G. Knepley /*@
118384f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
118484f0b6dfSMatthew G. Knepley 
11855b5e7992SMatthew G. Knepley   Not collective
11865b5e7992SMatthew G. Knepley 
118784f0b6dfSMatthew G. Knepley   Input Parameters:
118884f0b6dfSMatthew G. Knepley + label - the DMLabel
118984f0b6dfSMatthew G. Knepley . value - the stratum value
119084f0b6dfSMatthew G. Knepley - points - The stratum points
119184f0b6dfSMatthew G. Knepley 
119284f0b6dfSMatthew G. Knepley   Level: intermediate
119384f0b6dfSMatthew G. Knepley 
119484f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
119584f0b6dfSMatthew G. Knepley @*/
11964de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
11974de306b1SToby Isaac {
11980c3c4a36SLisandro Dalcin   PetscInt       v;
11994de306b1SToby Isaac   PetscErrorCode ierr;
12004de306b1SToby Isaac 
12014de306b1SToby Isaac   PetscFunctionBegin;
1202d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1203d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
1204b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
12054de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
12064de306b1SToby Isaac   ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr);
12074de306b1SToby Isaac   ierr = ISGetLocalSize(is, &(label->stratumSizes[v]));CHKERRQ(ierr);
12084de306b1SToby Isaac   ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
12094de306b1SToby Isaac   ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr);
12100c3c4a36SLisandro Dalcin   label->points[v]  = is;
12110c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
1212277ea44aSLisandro Dalcin   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
12134de306b1SToby Isaac   if (label->bt) {
12144de306b1SToby Isaac     const PetscInt *points;
12154de306b1SToby Isaac     PetscInt p;
12164de306b1SToby Isaac 
12174de306b1SToby Isaac     ierr = ISGetIndices(is,&points);CHKERRQ(ierr);
12184de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
12194de306b1SToby Isaac       const PetscInt point = points[p];
12204de306b1SToby Isaac 
12214de306b1SToby Isaac       if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
12224de306b1SToby Isaac       ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr);
12234de306b1SToby Isaac     }
12244de306b1SToby Isaac   }
12254de306b1SToby Isaac   PetscFunctionReturn(0);
12264de306b1SToby Isaac }
12274de306b1SToby Isaac 
122884f0b6dfSMatthew G. Knepley /*@
122984f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
12304de306b1SToby Isaac 
12315b5e7992SMatthew G. Knepley   Not collective
12325b5e7992SMatthew G. Knepley 
123384f0b6dfSMatthew G. Knepley   Input Parameters:
123484f0b6dfSMatthew G. Knepley + label - the DMLabel
123584f0b6dfSMatthew G. Knepley - value - the stratum value
123684f0b6dfSMatthew G. Knepley 
123784f0b6dfSMatthew G. Knepley   Level: intermediate
123884f0b6dfSMatthew G. Knepley 
123984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
124084f0b6dfSMatthew G. Knepley @*/
1241c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1242c58f1c22SToby Isaac {
1243c58f1c22SToby Isaac   PetscInt       v;
1244c58f1c22SToby Isaac   PetscErrorCode ierr;
1245c58f1c22SToby Isaac 
1246c58f1c22SToby Isaac   PetscFunctionBegin;
1247d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12480c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
12490c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
12504de306b1SToby Isaac   if (label->validIS[v]) {
12514de306b1SToby Isaac     if (label->bt) {
1252c58f1c22SToby Isaac       PetscInt       i;
1253ad8374ffSToby Isaac       const PetscInt *points;
1254c58f1c22SToby Isaac 
1255ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
1256c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1257ad8374ffSToby Isaac         const PetscInt point = points[i];
1258c58f1c22SToby Isaac 
1259c58f1c22SToby Isaac         if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
1260c58f1c22SToby Isaac         ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
1261c58f1c22SToby Isaac       }
1262ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
1263c58f1c22SToby Isaac     }
1264c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
12650c3c4a36SLisandro Dalcin     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
1266277ea44aSLisandro Dalcin     ierr = ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]);CHKERRQ(ierr);
12670c3c4a36SLisandro Dalcin     ierr = PetscObjectSetName((PetscObject) label->points[v], "indices");CHKERRQ(ierr);
1268277ea44aSLisandro Dalcin     ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
1269c58f1c22SToby Isaac   } else {
1270b9907514SLisandro Dalcin     ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr);
1271c58f1c22SToby Isaac   }
1272c58f1c22SToby Isaac   PetscFunctionReturn(0);
1273c58f1c22SToby Isaac }
1274c58f1c22SToby Isaac 
127584f0b6dfSMatthew G. Knepley /*@
1276412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1277412e9a14SMatthew G. Knepley 
1278412e9a14SMatthew G. Knepley   Not collective
1279412e9a14SMatthew G. Knepley 
1280412e9a14SMatthew G. Knepley   Input Parameters:
1281412e9a14SMatthew G. Knepley + label  - The DMLabel
1282412e9a14SMatthew G. Knepley . value  - The label value for all points
1283412e9a14SMatthew G. Knepley . pStart - The first point
1284412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1285412e9a14SMatthew G. Knepley 
1286412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1287412e9a14SMatthew G. Knepley 
1288412e9a14SMatthew G. Knepley   Level: intermediate
1289412e9a14SMatthew G. Knepley 
1290412e9a14SMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelSetStratumIS(), DMLabelGetStratumIS()
1291412e9a14SMatthew G. Knepley @*/
1292412e9a14SMatthew G. Knepley PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1293412e9a14SMatthew G. Knepley {
1294412e9a14SMatthew G. Knepley   IS             pIS;
1295412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1296412e9a14SMatthew G. Knepley 
1297412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1298412e9a14SMatthew G. Knepley   ierr = ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS);CHKERRQ(ierr);
1299412e9a14SMatthew G. Knepley   ierr = DMLabelSetStratumIS(label, value, pIS);CHKERRQ(ierr);
1300412e9a14SMatthew G. Knepley   ierr = ISDestroy(&pIS);CHKERRQ(ierr);
1301412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1302412e9a14SMatthew G. Knepley }
1303412e9a14SMatthew G. Knepley 
1304412e9a14SMatthew G. Knepley /*@
130584f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
130684f0b6dfSMatthew G. Knepley 
13075b5e7992SMatthew G. Knepley   Not collective
13085b5e7992SMatthew G. Knepley 
130984f0b6dfSMatthew G. Knepley   Input Parameters:
131084f0b6dfSMatthew G. Knepley + label - the DMLabel
131122cd2cdaSVaclav Hapla . start - the first point kept
131222cd2cdaSVaclav Hapla - end - one more than the last point kept
131384f0b6dfSMatthew G. Knepley 
131484f0b6dfSMatthew G. Knepley   Level: intermediate
131584f0b6dfSMatthew G. Knepley 
131684f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
131784f0b6dfSMatthew G. Knepley @*/
1318c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1319c58f1c22SToby Isaac {
1320c58f1c22SToby Isaac   PetscInt       v;
1321c58f1c22SToby Isaac   PetscErrorCode ierr;
1322c58f1c22SToby Isaac 
1323c58f1c22SToby Isaac   PetscFunctionBegin;
1324d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13250c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
1326c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1327c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
13289106b633SVaclav Hapla     ierr = ISGeneralFilter(label->points[v], start, end);CHKERRQ(ierr);
1329c58f1c22SToby Isaac   }
1330c58f1c22SToby Isaac   ierr = DMLabelCreateIndex(label, start, end);CHKERRQ(ierr);
1331c58f1c22SToby Isaac   PetscFunctionReturn(0);
1332c58f1c22SToby Isaac }
1333c58f1c22SToby Isaac 
133484f0b6dfSMatthew G. Knepley /*@
133584f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
133684f0b6dfSMatthew G. Knepley 
13375b5e7992SMatthew G. Knepley   Not collective
13385b5e7992SMatthew G. Knepley 
133984f0b6dfSMatthew G. Knepley   Input Parameters:
134084f0b6dfSMatthew G. Knepley + label - the DMLabel
134184f0b6dfSMatthew G. Knepley - permutation - the point permutation
134284f0b6dfSMatthew G. Knepley 
134384f0b6dfSMatthew G. Knepley   Output Parameter:
134484f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
134584f0b6dfSMatthew G. Knepley 
134684f0b6dfSMatthew G. Knepley   Level: intermediate
134784f0b6dfSMatthew G. Knepley 
134884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
134984f0b6dfSMatthew G. Knepley @*/
1350c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1351c58f1c22SToby Isaac {
1352c58f1c22SToby Isaac   const PetscInt *perm;
1353c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1354c58f1c22SToby Isaac   PetscErrorCode  ierr;
1355c58f1c22SToby Isaac 
1356c58f1c22SToby Isaac   PetscFunctionBegin;
1357d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1358d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
1359c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1360c58f1c22SToby Isaac   ierr = DMLabelDuplicate(label, labelNew);CHKERRQ(ierr);
1361c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(*labelNew, &numValues);CHKERRQ(ierr);
1362c58f1c22SToby Isaac   ierr = ISGetLocalSize(permutation, &numPoints);CHKERRQ(ierr);
1363c58f1c22SToby Isaac   ierr = ISGetIndices(permutation, &perm);CHKERRQ(ierr);
1364c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1365c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1366ad8374ffSToby Isaac     const PetscInt *points;
1367ad8374ffSToby Isaac     PetscInt *pointsNew;
1368c58f1c22SToby Isaac 
1369ad8374ffSToby Isaac     ierr = ISGetIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1370ad8374ffSToby Isaac     ierr = PetscMalloc1(size,&pointsNew);CHKERRQ(ierr);
1371c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1372ad8374ffSToby Isaac       const PetscInt point = points[q];
1373c58f1c22SToby Isaac 
1374c58f1c22SToby Isaac       if ((point < 0) || (point >= numPoints)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [0, %D) for the remapping", point, numPoints);
1375ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1376c58f1c22SToby Isaac     }
1377ad8374ffSToby Isaac     ierr = ISRestoreIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1378ad8374ffSToby Isaac     ierr = PetscSortInt(size, pointsNew);CHKERRQ(ierr);
1379ad8374ffSToby Isaac     ierr = ISDestroy(&((*labelNew)->points[v]));CHKERRQ(ierr);
1380fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
1381fa8e8ae5SToby Isaac       ierr = ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v]));CHKERRQ(ierr);
1382fa8e8ae5SToby Isaac       ierr = PetscFree(pointsNew);CHKERRQ(ierr);
1383fa8e8ae5SToby Isaac     } else {
1384ad8374ffSToby Isaac       ierr = ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v]));CHKERRQ(ierr);
1385fa8e8ae5SToby Isaac     }
1386ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices");CHKERRQ(ierr);
1387c58f1c22SToby Isaac   }
1388c58f1c22SToby Isaac   ierr = ISRestoreIndices(permutation, &perm);CHKERRQ(ierr);
1389c58f1c22SToby Isaac   if (label->bt) {
1390c58f1c22SToby Isaac     ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
1391c58f1c22SToby Isaac     ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
1392c58f1c22SToby Isaac   }
1393c58f1c22SToby Isaac   PetscFunctionReturn(0);
1394c58f1c22SToby Isaac }
1395c58f1c22SToby Isaac 
139626c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
139726c55118SMichael Lange {
139826c55118SMichael Lange   MPI_Comm       comm;
139926c55118SMichael Lange   PetscInt       s, l, nroots, nleaves, dof, offset, size;
140026c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
140126c55118SMichael Lange   PetscSection   rootSection;
140226c55118SMichael Lange   PetscSF        labelSF;
140326c55118SMichael Lange   PetscErrorCode ierr;
140426c55118SMichael Lange 
140526c55118SMichael Lange   PetscFunctionBegin;
140626c55118SMichael Lange   if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);}
140726c55118SMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
140826c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
140926c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
141026c55118SMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL);CHKERRQ(ierr);
141126c55118SMichael Lange   ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr);
141226c55118SMichael Lange   ierr = PetscSectionSetChart(rootSection, 0, nroots);CHKERRQ(ierr);
141326c55118SMichael Lange   if (label) {
141426c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1415ad8374ffSToby Isaac       const PetscInt *points;
1416ad8374ffSToby Isaac 
1417ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
141826c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1419ad8374ffSToby Isaac         ierr = PetscSectionGetDof(rootSection, points[l], &dof);CHKERRQ(ierr);
1420ad8374ffSToby Isaac         ierr = PetscSectionSetDof(rootSection, points[l], dof+1);CHKERRQ(ierr);
142126c55118SMichael Lange       }
1422ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
142326c55118SMichael Lange     }
142426c55118SMichael Lange   }
142526c55118SMichael Lange   ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr);
142626c55118SMichael Lange   /* Create a point-wise array of stratum values */
142726c55118SMichael Lange   ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr);
142826c55118SMichael Lange   ierr = PetscMalloc1(size, &rootStrata);CHKERRQ(ierr);
142926c55118SMichael Lange   ierr = PetscCalloc1(nroots, &rootIdx);CHKERRQ(ierr);
143026c55118SMichael Lange   if (label) {
143126c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1432ad8374ffSToby Isaac       const PetscInt *points;
1433ad8374ffSToby Isaac 
1434ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
143526c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1436ad8374ffSToby Isaac         const PetscInt p = points[l];
143726c55118SMichael Lange         ierr = PetscSectionGetOffset(rootSection, p, &offset);CHKERRQ(ierr);
143826c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
143926c55118SMichael Lange       }
1440ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
144126c55118SMichael Lange     }
144226c55118SMichael Lange   }
144326c55118SMichael Lange   /* Build SF that maps label points to remote processes */
144426c55118SMichael Lange   ierr = PetscSectionCreate(comm, leafSection);CHKERRQ(ierr);
144526c55118SMichael Lange   ierr = PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection);CHKERRQ(ierr);
144626c55118SMichael Lange   ierr = PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF);CHKERRQ(ierr);
144726c55118SMichael Lange   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
144826c55118SMichael Lange   /* Send the strata for each point over the derived SF */
144926c55118SMichael Lange   ierr = PetscSectionGetStorageSize(*leafSection, &size);CHKERRQ(ierr);
145026c55118SMichael Lange   ierr = PetscMalloc1(size, leafStrata);CHKERRQ(ierr);
145126c55118SMichael Lange   ierr = PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata);CHKERRQ(ierr);
145226c55118SMichael Lange   ierr = PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata);CHKERRQ(ierr);
145326c55118SMichael Lange   /* Clean up */
145426c55118SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
145526c55118SMichael Lange   ierr = PetscFree(rootIdx);CHKERRQ(ierr);
145626c55118SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
145726c55118SMichael Lange   ierr = PetscSFDestroy(&labelSF);CHKERRQ(ierr);
145826c55118SMichael Lange   PetscFunctionReturn(0);
145926c55118SMichael Lange }
146026c55118SMichael Lange 
146184f0b6dfSMatthew G. Knepley /*@
146284f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
146384f0b6dfSMatthew G. Knepley 
14645b5e7992SMatthew G. Knepley   Collective on sf
14655b5e7992SMatthew G. Knepley 
146684f0b6dfSMatthew G. Knepley   Input Parameters:
146784f0b6dfSMatthew G. Knepley + label - the DMLabel
146884f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
146984f0b6dfSMatthew G. Knepley 
147084f0b6dfSMatthew G. Knepley   Output Parameter:
147184f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
147284f0b6dfSMatthew G. Knepley 
147384f0b6dfSMatthew G. Knepley   Level: intermediate
147484f0b6dfSMatthew G. Knepley 
147584f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
147684f0b6dfSMatthew G. Knepley @*/
1477c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1478c58f1c22SToby Isaac {
1479c58f1c22SToby Isaac   MPI_Comm       comm;
148026c55118SMichael Lange   PetscSection   leafSection;
148126c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
148226c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1483ad8374ffSToby Isaac   PetscInt     **points;
1484d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1485c58f1c22SToby Isaac   char          *name;
1486c58f1c22SToby Isaac   PetscInt       nameSize;
1487e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1488c58f1c22SToby Isaac   size_t         len = 0;
148926c55118SMichael Lange   PetscMPIInt    rank;
1490c58f1c22SToby Isaac   PetscErrorCode ierr;
1491c58f1c22SToby Isaac 
1492c58f1c22SToby Isaac   PetscFunctionBegin;
1493d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1494f018e600SMatthew G. Knepley   if (label) {
1495f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1496f018e600SMatthew G. Knepley     ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1497f018e600SMatthew G. Knepley   }
1498c58f1c22SToby Isaac   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
1499c58f1c22SToby Isaac   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1500c58f1c22SToby Isaac   /* Bcast name */
1501d67d17b1SMatthew G. Knepley   if (!rank) {
1502d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1503d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1504d67d17b1SMatthew G. Knepley   }
1505c58f1c22SToby Isaac   nameSize = len;
1506c58f1c22SToby Isaac   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
1507c58f1c22SToby Isaac   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1508580bdb30SBarry Smith   if (!rank) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
1509c58f1c22SToby Isaac   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr);
1510d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
1511c58f1c22SToby Isaac   ierr = PetscFree(name);CHKERRQ(ierr);
151277d236dfSMichael Lange   /* Bcast defaultValue */
151377d236dfSMichael Lange   if (!rank) (*labelNew)->defaultValue = label->defaultValue;
151477d236dfSMichael Lange   ierr = MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
151526c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
151626c55118SMichael Lange   ierr = DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata);CHKERRQ(ierr);
15175cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
1518e8f14785SLisandro Dalcin   ierr = PetscHSetICreate(&stratumHash);CHKERRQ(ierr);
151926c55118SMichael Lange   ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr);
1520e8f14785SLisandro Dalcin   for (p = 0; p < size; ++p) {ierr = PetscHSetIAdd(stratumHash, leafStrata[p]);CHKERRQ(ierr);}
1521e8f14785SLisandro Dalcin   ierr = PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata);CHKERRQ(ierr);
1522ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS);CHKERRQ(ierr);
1523ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
15245cbdf6fcSMichael Lange   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues);CHKERRQ(ierr);
15255cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
15265cbdf6fcSMichael Lange   offset = 0;
1527e8f14785SLisandro Dalcin   ierr = PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues);CHKERRQ(ierr);
1528a205f1fdSToby Isaac   ierr = PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues);CHKERRQ(ierr);
152990e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
153090e9b2aeSLisandro Dalcin     ierr = PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s);CHKERRQ(ierr);
153190e9b2aeSLisandro Dalcin   }
15325cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1533231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1534231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
15355cbdf6fcSMichael Lange     }
15365cbdf6fcSMichael Lange   }
1537c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
1538c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes);CHKERRQ(ierr);
1539c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1540c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1541c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1542c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1543c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1544c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1545c58f1c22SToby Isaac     }
1546c58f1c22SToby Isaac   }
1547c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht);CHKERRQ(ierr);
1548c58f1c22SToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points);CHKERRQ(ierr);
1549ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&points);CHKERRQ(ierr);
1550c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
1551e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelNew)->ht[s]);CHKERRQ(ierr);
1552ad8374ffSToby Isaac     ierr = PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s]));CHKERRQ(ierr);
1553c58f1c22SToby Isaac   }
1554c58f1c22SToby Isaac   /* Insert points into new strata */
1555c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata, &strataIdx);CHKERRQ(ierr);
1556c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1557c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1558c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1559c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1560c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1561c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1562ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1563c58f1c22SToby Isaac     }
1564c58f1c22SToby Isaac   }
1565ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1566ad8374ffSToby Isaac     ierr = ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s]));CHKERRQ(ierr);
1567ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices");CHKERRQ(ierr);
1568ad8374ffSToby Isaac   }
1569ad8374ffSToby Isaac   ierr = PetscFree(points);CHKERRQ(ierr);
1570e8f14785SLisandro Dalcin   ierr = PetscHSetIDestroy(&stratumHash);CHKERRQ(ierr);
1571c58f1c22SToby Isaac   ierr = PetscFree(leafStrata);CHKERRQ(ierr);
1572c58f1c22SToby Isaac   ierr = PetscFree(strataIdx);CHKERRQ(ierr);
1573c58f1c22SToby Isaac   ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr);
1574c58f1c22SToby Isaac   PetscFunctionReturn(0);
1575c58f1c22SToby Isaac }
1576c58f1c22SToby Isaac 
15777937d9ceSMichael Lange /*@
15787937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
15797937d9ceSMichael Lange 
15805b5e7992SMatthew G. Knepley   Collective on sf
15815b5e7992SMatthew G. Knepley 
15827937d9ceSMichael Lange   Input Parameters:
15837937d9ceSMichael Lange + label - the DMLabel
158484f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
15857937d9ceSMichael Lange 
158684f0b6dfSMatthew G. Knepley   Output Parameters:
158784f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
15887937d9ceSMichael Lange 
15897937d9ceSMichael Lange   Level: developer
15907937d9ceSMichael Lange 
15917937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
15927937d9ceSMichael Lange 
15937937d9ceSMichael Lange .seealso: DMLabelDistribute()
15947937d9ceSMichael Lange @*/
15957937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
15967937d9ceSMichael Lange {
15977937d9ceSMichael Lange   MPI_Comm       comm;
15987937d9ceSMichael Lange   PetscSection   rootSection;
15997937d9ceSMichael Lange   PetscSF        sfLabel;
16007937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
16017937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
16027937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
16037937d9ceSMichael Lange   PetscInt       *rootStrata;
1604d67d17b1SMatthew G. Knepley   const char    *lname;
16057937d9ceSMichael Lange   char          *name;
16067937d9ceSMichael Lange   PetscInt       nameSize;
16077937d9ceSMichael Lange   size_t         len = 0;
16089852e123SBarry Smith   PetscMPIInt    rank, size;
16097937d9ceSMichael Lange   PetscErrorCode ierr;
16107937d9ceSMichael Lange 
16117937d9ceSMichael Lange   PetscFunctionBegin;
1612d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1613d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
16147937d9ceSMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
16157937d9ceSMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
16169852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
16177937d9ceSMichael Lange   /* Bcast name */
1618d67d17b1SMatthew G. Knepley   if (!rank) {
1619d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1620d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1621d67d17b1SMatthew G. Knepley   }
16227937d9ceSMichael Lange   nameSize = len;
16237937d9ceSMichael Lange   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
16247937d9ceSMichael Lange   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1625580bdb30SBarry Smith   if (!rank) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
16267937d9ceSMichael Lange   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr);
1627d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
16287937d9ceSMichael Lange   ierr = PetscFree(name);CHKERRQ(ierr);
16297937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
16307937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
16317937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
16327937d9ceSMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL);CHKERRQ(ierr);
1633dc53bc9bSMatthew G. Knepley   ierr = PetscMalloc1(nroots, &leafPoints);CHKERRQ(ierr);
1634dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
16357937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
16368212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
16378212dd46SStefano Zampini 
16388212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
16398212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
16407937d9ceSMichael Lange   }
16417937d9ceSMichael Lange   ierr = PetscSFComputeDegreeBegin(sf, &rootDegree);CHKERRQ(ierr);
16427937d9ceSMichael Lange   ierr = PetscSFComputeDegreeEnd(sf, &rootDegree);CHKERRQ(ierr);
16437937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
16447937d9ceSMichael Lange   ierr = PetscMalloc1(nmultiroots, &rootPoints);CHKERRQ(ierr);
16457937d9ceSMichael Lange   ierr = PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
16467937d9ceSMichael Lange   ierr = PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
16477937d9ceSMichael Lange   ierr = PetscSFCreate(comm,& sfLabel);CHKERRQ(ierr);
16487937d9ceSMichael Lange   ierr = PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
16497937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
16507937d9ceSMichael Lange   ierr = DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata);CHKERRQ(ierr);
16517937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
16527937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
16537937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
16547937d9ceSMichael Lange       ierr = PetscSectionGetDof(rootSection, idx+d, &dof);CHKERRQ(ierr);
16557937d9ceSMichael Lange       ierr = PetscSectionGetOffset(rootSection, idx+d, &offset);CHKERRQ(ierr);
16567937d9ceSMichael Lange       for (s = 0; s < dof; s++) {ierr = DMLabelSetValue(*labelNew, p, rootStrata[offset+s]);CHKERRQ(ierr);}
16577937d9ceSMichael Lange     }
16587937d9ceSMichael Lange     idx += rootDegree[p];
16597937d9ceSMichael Lange   }
166077e0c0e7SMichael Lange   ierr = PetscFree(leafPoints);CHKERRQ(ierr);
166177e0c0e7SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
166277e0c0e7SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
166377e0c0e7SMichael Lange   ierr = PetscSFDestroy(&sfLabel);CHKERRQ(ierr);
16647937d9ceSMichael Lange   PetscFunctionReturn(0);
16657937d9ceSMichael Lange }
16667937d9ceSMichael Lange 
166784f0b6dfSMatthew G. Knepley /*@
166884f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
166984f0b6dfSMatthew G. Knepley 
16705b5e7992SMatthew G. Knepley   Not collective
16715b5e7992SMatthew G. Knepley 
167284f0b6dfSMatthew G. Knepley   Input Parameter:
167384f0b6dfSMatthew G. Knepley . label - the DMLabel
167484f0b6dfSMatthew G. Knepley 
167584f0b6dfSMatthew G. Knepley   Output Parameters:
167684f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
167784f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
167884f0b6dfSMatthew G. Knepley 
167984f0b6dfSMatthew G. Knepley   Level: developer
168084f0b6dfSMatthew G. Knepley 
168184f0b6dfSMatthew G. Knepley .seealso: DMLabelDistribute()
168284f0b6dfSMatthew G. Knepley @*/
1683c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
1684c58f1c22SToby Isaac {
1685c58f1c22SToby Isaac   IS              vIS;
1686c58f1c22SToby Isaac   const PetscInt *values;
1687c58f1c22SToby Isaac   PetscInt       *points;
1688c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
1689c58f1c22SToby Isaac   PetscErrorCode  ierr;
1690c58f1c22SToby Isaac 
1691c58f1c22SToby Isaac   PetscFunctionBegin;
1692d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1693c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(label, &nV);CHKERRQ(ierr);
1694c58f1c22SToby Isaac   ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr);
1695c58f1c22SToby Isaac   ierr = ISGetIndices(vIS, &values);CHKERRQ(ierr);
1696c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
1697c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
1698c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
1699c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
1700c58f1c22SToby Isaac   }
1701c58f1c22SToby Isaac   ierr = PetscSectionCreate(PETSC_COMM_SELF, section);CHKERRQ(ierr);
1702c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*section, vS, vE);CHKERRQ(ierr);
1703c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1704c58f1c22SToby Isaac     PetscInt n;
1705c58f1c22SToby Isaac 
1706c58f1c22SToby Isaac     ierr = DMLabelGetStratumSize(label, values[v], &n);CHKERRQ(ierr);
1707c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*section, values[v], n);CHKERRQ(ierr);
1708c58f1c22SToby Isaac   }
1709c58f1c22SToby Isaac   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
1710c58f1c22SToby Isaac   ierr = PetscSectionGetStorageSize(*section, &N);CHKERRQ(ierr);
1711c58f1c22SToby Isaac   ierr = PetscMalloc1(N, &points);CHKERRQ(ierr);
1712c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1713c58f1c22SToby Isaac     IS              is;
1714c58f1c22SToby Isaac     const PetscInt *spoints;
1715c58f1c22SToby Isaac     PetscInt        dof, off, p;
1716c58f1c22SToby Isaac 
1717c58f1c22SToby Isaac     ierr = PetscSectionGetDof(*section, values[v], &dof);CHKERRQ(ierr);
1718c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(*section, values[v], &off);CHKERRQ(ierr);
1719c58f1c22SToby Isaac     ierr = DMLabelGetStratumIS(label, values[v], &is);CHKERRQ(ierr);
1720c58f1c22SToby Isaac     ierr = ISGetIndices(is, &spoints);CHKERRQ(ierr);
1721c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
1722c58f1c22SToby Isaac     ierr = ISRestoreIndices(is, &spoints);CHKERRQ(ierr);
1723c58f1c22SToby Isaac     ierr = ISDestroy(&is);CHKERRQ(ierr);
1724c58f1c22SToby Isaac   }
1725c58f1c22SToby Isaac   ierr = ISRestoreIndices(vIS, &values);CHKERRQ(ierr);
1726c58f1c22SToby Isaac   ierr = ISDestroy(&vIS);CHKERRQ(ierr);
1727c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is);CHKERRQ(ierr);
1728c58f1c22SToby Isaac   PetscFunctionReturn(0);
1729c58f1c22SToby Isaac }
1730c58f1c22SToby Isaac 
173184f0b6dfSMatthew G. Knepley /*@
1732c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
1733c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
1734c58f1c22SToby Isaac 
17355b5e7992SMatthew G. Knepley   Collective on sf
17365b5e7992SMatthew G. Knepley 
1737c58f1c22SToby Isaac   Input Parameters:
1738c58f1c22SToby Isaac   + s - The PetscSection for the local field layout
1739c58f1c22SToby Isaac   . sf - The SF describing parallel layout of the section points
1740c58f1c22SToby Isaac   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1741c58f1c22SToby Isaac   . label - The label specifying the points
1742c58f1c22SToby Isaac   - labelValue - The label stratum specifying the points
1743c58f1c22SToby Isaac 
1744c58f1c22SToby Isaac   Output Parameter:
1745c58f1c22SToby Isaac   . gsection - The PetscSection for the global field layout
1746c58f1c22SToby Isaac 
1747c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
1748c58f1c22SToby Isaac 
1749c58f1c22SToby Isaac   Level: developer
1750c58f1c22SToby Isaac 
1751c58f1c22SToby Isaac .seealso: PetscSectionCreate()
1752c58f1c22SToby Isaac @*/
1753c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
1754c58f1c22SToby Isaac {
1755c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
1756c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
1757c58f1c22SToby Isaac   PetscErrorCode ierr;
1758c58f1c22SToby Isaac 
1759c58f1c22SToby Isaac   PetscFunctionBegin;
1760d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1761d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1762d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
1763c58f1c22SToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
1764c58f1c22SToby Isaac   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1765c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
1766c58f1c22SToby Isaac   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
1767c58f1c22SToby Isaac   if (nroots >= 0) {
1768c58f1c22SToby Isaac     if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
1769c58f1c22SToby Isaac     ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr);
1770c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1771c58f1c22SToby Isaac       ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr);
1772c58f1c22SToby Isaac     } else {
1773c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
1774c58f1c22SToby Isaac     }
1775c58f1c22SToby Isaac   }
1776c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
1777c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
1778c58f1c22SToby Isaac     PetscInt value;
1779c58f1c22SToby Isaac 
1780c58f1c22SToby Isaac     ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr);
1781c58f1c22SToby Isaac     if (value != labelValue) continue;
1782c58f1c22SToby Isaac     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1783c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr);
1784c58f1c22SToby Isaac     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1785c58f1c22SToby Isaac     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);}
1786c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
1787c58f1c22SToby Isaac   }
1788c58f1c22SToby Isaac   ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr);
1789c58f1c22SToby Isaac   if (nroots >= 0) {
1790c58f1c22SToby Isaac     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1791c58f1c22SToby Isaac     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1792c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1793c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
1794c58f1c22SToby Isaac     }
1795c58f1c22SToby Isaac   }
1796c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
1797c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1798c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
1799c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
1800c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
1801c58f1c22SToby Isaac   }
1802c58f1c22SToby Isaac   ierr       = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr);
1803c58f1c22SToby Isaac   globalOff -= off;
1804c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1805c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
1806c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
1807c58f1c22SToby Isaac   }
1808c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
1809c58f1c22SToby Isaac   if (nroots >= 0) {
1810c58f1c22SToby Isaac     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1811c58f1c22SToby Isaac     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1812c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1813c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
1814c58f1c22SToby Isaac     }
1815c58f1c22SToby Isaac   }
1816c58f1c22SToby Isaac   if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);}
1817c58f1c22SToby Isaac   ierr = PetscFree(neg);CHKERRQ(ierr);
1818c58f1c22SToby Isaac   PetscFunctionReturn(0);
1819c58f1c22SToby Isaac }
1820c58f1c22SToby Isaac 
18215fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
18225fdea053SToby Isaac {
18235fdea053SToby Isaac   DMLabel           label;
18245fdea053SToby Isaac   PetscCopyMode     *modes;
18255fdea053SToby Isaac   PetscInt          *sizes;
18265fdea053SToby Isaac   const PetscInt    ***perms;
18275fdea053SToby Isaac   const PetscScalar ***rots;
18285fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
18295fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
18305fdea053SToby Isaac } PetscSectionSym_Label;
18315fdea053SToby Isaac 
18325fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
18335fdea053SToby Isaac {
18345fdea053SToby Isaac   PetscInt              i, j;
18355fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
18365fdea053SToby Isaac   PetscErrorCode        ierr;
18375fdea053SToby Isaac 
18385fdea053SToby Isaac   PetscFunctionBegin;
18395fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
18405fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
18415fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
18425fdea053SToby Isaac         if (sl->perms[i]) {ierr = PetscFree(sl->perms[i][j]);CHKERRQ(ierr);}
18435fdea053SToby Isaac         if (sl->rots[i]) {ierr = PetscFree(sl->rots[i][j]);CHKERRQ(ierr);}
18445fdea053SToby Isaac       }
18455fdea053SToby Isaac       if (sl->perms[i]) {
18465fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
18475fdea053SToby Isaac 
18485fdea053SToby Isaac         ierr = PetscFree(perms);CHKERRQ(ierr);
18495fdea053SToby Isaac       }
18505fdea053SToby Isaac       if (sl->rots[i]) {
18515fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
18525fdea053SToby Isaac 
18535fdea053SToby Isaac         ierr = PetscFree(rots);CHKERRQ(ierr);
18545fdea053SToby Isaac       }
18555fdea053SToby Isaac     }
18565fdea053SToby Isaac   }
18575fdea053SToby Isaac   ierr = PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients);CHKERRQ(ierr);
18585fdea053SToby Isaac   ierr = DMLabelDestroy(&sl->label);CHKERRQ(ierr);
18595fdea053SToby Isaac   sl->numStrata = 0;
18605fdea053SToby Isaac   PetscFunctionReturn(0);
18615fdea053SToby Isaac }
18625fdea053SToby Isaac 
18635fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
18645fdea053SToby Isaac {
18655fdea053SToby Isaac   PetscErrorCode ierr;
18665fdea053SToby Isaac 
18675fdea053SToby Isaac   PetscFunctionBegin;
18685fdea053SToby Isaac   ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);
18695fdea053SToby Isaac   ierr = PetscFree(sym->data);CHKERRQ(ierr);
18705fdea053SToby Isaac   PetscFunctionReturn(0);
18715fdea053SToby Isaac }
18725fdea053SToby Isaac 
18735fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
18745fdea053SToby Isaac {
18755fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
18765fdea053SToby Isaac   PetscBool             isAscii;
18775fdea053SToby Isaac   DMLabel               label = sl->label;
1878d67d17b1SMatthew G. Knepley   const char           *name;
18795fdea053SToby Isaac   PetscErrorCode        ierr;
18805fdea053SToby Isaac 
18815fdea053SToby Isaac   PetscFunctionBegin;
18825fdea053SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii);CHKERRQ(ierr);
18835fdea053SToby Isaac   if (isAscii) {
18845fdea053SToby Isaac     PetscInt          i, j, k;
18855fdea053SToby Isaac     PetscViewerFormat format;
18865fdea053SToby Isaac 
18875fdea053SToby Isaac     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
18885fdea053SToby Isaac     if (label) {
18895fdea053SToby Isaac       ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
18905fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
18915fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
18925fdea053SToby Isaac         ierr = DMLabelView(label, viewer);CHKERRQ(ierr);
18935fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
18945fdea053SToby Isaac       } else {
1895d67d17b1SMatthew G. Knepley         ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
1896d67d17b1SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name);CHKERRQ(ierr);
18975fdea053SToby Isaac       }
18985fdea053SToby Isaac     } else {
18995fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "No label given\n");CHKERRQ(ierr);
19005fdea053SToby Isaac     }
19015fdea053SToby Isaac     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19025fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
19035fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
19045fdea053SToby Isaac 
19055fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
19065fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point): no symmetries\n", value, sl->sizes[i]);CHKERRQ(ierr);
19075fdea053SToby Isaac       } else {
19085fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point):\n", value, sl->sizes[i]);CHKERRQ(ierr);
19095fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19105fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Orientation range: [%D, %D)\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]);CHKERRQ(ierr);
19115fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
19125fdea053SToby Isaac           ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19135fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
19145fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
19155fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D: identity\n",j);CHKERRQ(ierr);
19165fdea053SToby Isaac             } else {
19175fdea053SToby Isaac               PetscInt tab;
19185fdea053SToby Isaac 
19195fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D:\n",j);CHKERRQ(ierr);
19205fdea053SToby Isaac               ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19215fdea053SToby Isaac               ierr = PetscViewerASCIIGetTab(viewer,&tab);CHKERRQ(ierr);
19225fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
19235fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Permutation:");CHKERRQ(ierr);
19245fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
19255fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %D",sl->perms[i][j][k]);CHKERRQ(ierr);}
19265fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
19275fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
19285fdea053SToby Isaac               }
19295fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
19305fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Rotations:  ");CHKERRQ(ierr);
19315fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
19325fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
19335fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f+i*%+f",PetscRealPart(sl->rots[i][j][k]),PetscImaginaryPart(sl->rots[i][j][k]));CHKERRQ(ierr);}
19345fdea053SToby Isaac #else
19355fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f",sl->rots[i][j][k]);CHKERRQ(ierr);}
19365fdea053SToby Isaac #endif
19375fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
19385fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
19395fdea053SToby Isaac               }
19405fdea053SToby Isaac               ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19415fdea053SToby Isaac             }
19425fdea053SToby Isaac           }
19435fdea053SToby Isaac           ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19445fdea053SToby Isaac         }
19455fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19465fdea053SToby Isaac       }
19475fdea053SToby Isaac     }
19485fdea053SToby Isaac     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19495fdea053SToby Isaac   }
19505fdea053SToby Isaac   PetscFunctionReturn(0);
19515fdea053SToby Isaac }
19525fdea053SToby Isaac 
19535fdea053SToby Isaac /*@
19545fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
19555fdea053SToby Isaac 
19565fdea053SToby Isaac   Logically collective on sym
19575fdea053SToby Isaac 
19585fdea053SToby Isaac   Input parameters:
19595fdea053SToby Isaac + sym - the section symmetries
19605fdea053SToby Isaac - label - the DMLabel describing the types of points
19615fdea053SToby Isaac 
19625fdea053SToby Isaac   Level: developer:
19635fdea053SToby Isaac 
19645fdea053SToby Isaac .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreateLabel(), PetscSectionGetPointSyms()
19655fdea053SToby Isaac @*/
19665fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
19675fdea053SToby Isaac {
19685fdea053SToby Isaac   PetscSectionSym_Label *sl;
19695fdea053SToby Isaac   PetscErrorCode        ierr;
19705fdea053SToby Isaac 
19715fdea053SToby Isaac   PetscFunctionBegin;
19725fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
19735fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
19745fdea053SToby Isaac   if (sl->label && sl->label != label) {ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);}
19755fdea053SToby Isaac   if (label) {
19765fdea053SToby Isaac     sl->label = label;
1977d67d17b1SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
19785fdea053SToby Isaac     ierr = DMLabelGetNumValues(label,&sl->numStrata);CHKERRQ(ierr);
19791a834cf9SToby Isaac     ierr = 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);CHKERRQ(ierr);
19801a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode));CHKERRQ(ierr);
19811a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt));CHKERRQ(ierr);
19821a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **));CHKERRQ(ierr);
19831a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **));CHKERRQ(ierr);
19841a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2]));CHKERRQ(ierr);
19855fdea053SToby Isaac   }
19865fdea053SToby Isaac   PetscFunctionReturn(0);
19875fdea053SToby Isaac }
19885fdea053SToby Isaac 
19895fdea053SToby Isaac /*@C
19905fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
19915fdea053SToby Isaac 
19925b5e7992SMatthew G. Knepley   Logically collective on sym
19935fdea053SToby Isaac 
19945fdea053SToby Isaac   InputParameters:
19955b5e7992SMatthew G. Knepley + sym       - the section symmetries
19965fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
19975fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
19985fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
19995fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
20005fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
20015fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2002a2b725a8SWilliam 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
20035fdea053SToby Isaac 
20045fdea053SToby Isaac   Level: developer
20055fdea053SToby Isaac 
20065fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
20075fdea053SToby Isaac @*/
20085fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
20095fdea053SToby Isaac {
20105fdea053SToby Isaac   PetscSectionSym_Label *sl;
2011d67d17b1SMatthew G. Knepley   const char            *name;
2012d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
20135fdea053SToby Isaac   PetscErrorCode         ierr;
20145fdea053SToby Isaac 
20155fdea053SToby Isaac   PetscFunctionBegin;
20165fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
20175fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
20185fdea053SToby Isaac   if (!sl->label) SETERRQ(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_WRONGSTATE,"No label set yet");
20195fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
20205fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
20215fdea053SToby Isaac 
20225fdea053SToby Isaac     if (stratum == value) break;
20235fdea053SToby Isaac   }
2024d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
2025d67d17b1SMatthew G. Knepley   if (i > sl->numStrata) SETERRQ2(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_OUTOFRANGE,"Stratum %D not found in label %s\n",stratum,name);
20265fdea053SToby Isaac   sl->sizes[i] = size;
20275fdea053SToby Isaac   sl->modes[i] = mode;
20285fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
20295fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
20305fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
20315fdea053SToby Isaac     if (perms) {
20325fdea053SToby Isaac       PetscInt    **ownPerms;
20335fdea053SToby Isaac 
20345fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownPerms);CHKERRQ(ierr);
20355fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
20365fdea053SToby Isaac         if (perms[j]) {
20375fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownPerms[j]);CHKERRQ(ierr);
20385fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
20395fdea053SToby Isaac         }
20405fdea053SToby Isaac       }
20415fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
20425fdea053SToby Isaac     }
20435fdea053SToby Isaac     if (rots) {
20445fdea053SToby Isaac       PetscScalar **ownRots;
20455fdea053SToby Isaac 
20465fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownRots);CHKERRQ(ierr);
20475fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
20485fdea053SToby Isaac         if (rots[j]) {
20495fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownRots[j]);CHKERRQ(ierr);
20505fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
20515fdea053SToby Isaac         }
20525fdea053SToby Isaac       }
20535fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
20545fdea053SToby Isaac     }
20555fdea053SToby Isaac   } else {
20565fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
20575fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
20585fdea053SToby Isaac   }
20595fdea053SToby Isaac   PetscFunctionReturn(0);
20605fdea053SToby Isaac }
20615fdea053SToby Isaac 
20625fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
20635fdea053SToby Isaac {
20645fdea053SToby Isaac   PetscInt              i, j, numStrata;
20655fdea053SToby Isaac   PetscSectionSym_Label *sl;
20665fdea053SToby Isaac   DMLabel               label;
20675fdea053SToby Isaac   PetscErrorCode        ierr;
20685fdea053SToby Isaac 
20695fdea053SToby Isaac   PetscFunctionBegin;
20705fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
20715fdea053SToby Isaac   numStrata = sl->numStrata;
20725fdea053SToby Isaac   label     = sl->label;
20735fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
20745fdea053SToby Isaac     PetscInt point = points[2*i];
20755fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
20765fdea053SToby Isaac 
20775fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
20785fdea053SToby Isaac       if (label->validIS[j]) {
20795fdea053SToby Isaac         PetscInt k;
20805fdea053SToby Isaac 
20815fdea053SToby Isaac         ierr = ISLocate(label->points[j],point,&k);CHKERRQ(ierr);
20825fdea053SToby Isaac         if (k >= 0) break;
20835fdea053SToby Isaac       } else {
20845fdea053SToby Isaac         PetscBool has;
20855fdea053SToby Isaac 
2086b9907514SLisandro Dalcin         ierr = PetscHSetIHas(label->ht[j], point, &has);CHKERRQ(ierr);
20875fdea053SToby Isaac         if (has) break;
20885fdea053SToby Isaac       }
20895fdea053SToby Isaac     }
20905fdea053SToby Isaac     if ((sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) && (ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1])) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"point %D orientation %D not in range [%D, %D) for stratum %D",point,ornt,sl->minMaxOrients[j][0],sl->minMaxOrients[j][1],j < numStrata ? label->stratumValues[j] : label->defaultValue);
20915fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
20925fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
20935fdea053SToby Isaac   }
20945fdea053SToby Isaac   PetscFunctionReturn(0);
20955fdea053SToby Isaac }
20965fdea053SToby Isaac 
20975fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
20985fdea053SToby Isaac {
20995fdea053SToby Isaac   PetscSectionSym_Label *sl;
21005fdea053SToby Isaac   PetscErrorCode        ierr;
21015fdea053SToby Isaac 
21025fdea053SToby Isaac   PetscFunctionBegin;
21035fdea053SToby Isaac   ierr = PetscNewLog(sym,&sl);CHKERRQ(ierr);
21045fdea053SToby Isaac   sym->ops->getpoints = PetscSectionSymGetPoints_Label;
21055fdea053SToby Isaac   sym->ops->view      = PetscSectionSymView_Label;
21065fdea053SToby Isaac   sym->ops->destroy   = PetscSectionSymDestroy_Label;
21075fdea053SToby Isaac   sym->data           = (void *) sl;
21085fdea053SToby Isaac   PetscFunctionReturn(0);
21095fdea053SToby Isaac }
21105fdea053SToby Isaac 
21115fdea053SToby Isaac /*@
21125fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
21135fdea053SToby Isaac 
21145fdea053SToby Isaac   Collective
21155fdea053SToby Isaac 
21165fdea053SToby Isaac   Input Parameters:
21175fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
21185fdea053SToby Isaac - label - the label defining the strata
21195fdea053SToby Isaac 
21205fdea053SToby Isaac   Output Parameters:
21215fdea053SToby Isaac . sym - the section symmetries
21225fdea053SToby Isaac 
21235fdea053SToby Isaac   Level: developer
21245fdea053SToby Isaac 
21255fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms()
21265fdea053SToby Isaac @*/
21275fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
21285fdea053SToby Isaac {
21295fdea053SToby Isaac   PetscErrorCode        ierr;
21305fdea053SToby Isaac 
21315fdea053SToby Isaac   PetscFunctionBegin;
21325fdea053SToby Isaac   ierr = DMInitializePackage();CHKERRQ(ierr);
21335fdea053SToby Isaac   ierr = PetscSectionSymCreate(comm,sym);CHKERRQ(ierr);
21345fdea053SToby Isaac   ierr = PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL);CHKERRQ(ierr);
21355fdea053SToby Isaac   ierr = PetscSectionSymLabelSetLabel(*sym,label);CHKERRQ(ierr);
21365fdea053SToby Isaac   PetscFunctionReturn(0);
21375fdea053SToby Isaac }
2138