xref: /petsc/src/dm/label/dmlabel.c (revision d8d19677bbccf95218448bee62e6b87f4513e133)
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;
32064a246eSJacob Faibussowitsch   PetscValidPointer(label,3);
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   }
18376bd3646SJed 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 
269*d8d19677SJose E. Roman   Input Parameters:
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 
293*d8d19677SJose E. Roman   Input Parameters:
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 
357*d8d19677SJose E. Roman   Input Parameters:
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;
387ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(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);
471f9244615SMatthew G. Knepley   label->stratumValues = NULL;
472f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
473f9244615SMatthew G. Knepley   label->ht            = NULL;
474f9244615SMatthew G. Knepley   label->points        = NULL;
475f9244615SMatthew G. Knepley   label->validIS       = NULL;
476b9907514SLisandro Dalcin   ierr = PetscHMapIReset(label->hmap);CHKERRQ(ierr);
477b9907514SLisandro Dalcin   label->pStart = -1;
478b9907514SLisandro Dalcin   label->pEnd   = -1;
479d67d17b1SMatthew G. Knepley   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
480d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
481d67d17b1SMatthew G. Knepley }
482d67d17b1SMatthew G. Knepley 
483d67d17b1SMatthew G. Knepley /*@
48484f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
48584f0b6dfSMatthew G. Knepley 
4865b5e7992SMatthew G. Knepley   Collective on label
4875b5e7992SMatthew G. Knepley 
48884f0b6dfSMatthew G. Knepley   Input Parameter:
48984f0b6dfSMatthew G. Knepley . label - The DMLabel
49084f0b6dfSMatthew G. Knepley 
49184f0b6dfSMatthew G. Knepley   Level: beginner
49284f0b6dfSMatthew G. Knepley 
493d67d17b1SMatthew G. Knepley .seealso: DMLabelReset(), DMLabelCreate()
49484f0b6dfSMatthew G. Knepley @*/
495c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
496c58f1c22SToby Isaac {
497c58f1c22SToby Isaac   PetscErrorCode ierr;
498c58f1c22SToby Isaac 
499c58f1c22SToby Isaac   PetscFunctionBegin;
500d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
501d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1);
502b9907514SLisandro Dalcin   if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);}
503d67d17b1SMatthew G. Knepley   ierr = DMLabelReset(*label);CHKERRQ(ierr);
504b9907514SLisandro Dalcin   ierr = PetscHMapIDestroy(&(*label)->hmap);CHKERRQ(ierr);
505d67d17b1SMatthew G. Knepley   ierr = PetscHeaderDestroy(label);CHKERRQ(ierr);
506c58f1c22SToby Isaac   PetscFunctionReturn(0);
507c58f1c22SToby Isaac }
508c58f1c22SToby Isaac 
50984f0b6dfSMatthew G. Knepley /*@
51084f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
51184f0b6dfSMatthew G. Knepley 
5125b5e7992SMatthew G. Knepley   Collective on label
5135b5e7992SMatthew G. Knepley 
51484f0b6dfSMatthew G. Knepley   Input Parameter:
51584f0b6dfSMatthew G. Knepley . label - The DMLabel
51684f0b6dfSMatthew G. Knepley 
51784f0b6dfSMatthew G. Knepley   Output Parameter:
51884f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
51984f0b6dfSMatthew G. Knepley 
52084f0b6dfSMatthew G. Knepley   Level: intermediate
52184f0b6dfSMatthew G. Knepley 
52284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelDestroy()
52384f0b6dfSMatthew G. Knepley @*/
524c58f1c22SToby Isaac PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
525c58f1c22SToby Isaac {
526d67d17b1SMatthew G. Knepley   const char    *name;
527ad8374ffSToby Isaac   PetscInt       v;
528c58f1c22SToby Isaac   PetscErrorCode ierr;
529c58f1c22SToby Isaac 
530c58f1c22SToby Isaac   PetscFunctionBegin;
531d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
532c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
533d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
534d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew);CHKERRQ(ierr);
535c58f1c22SToby Isaac 
536c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5375aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
538c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues);CHKERRQ(ierr);
539c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes);CHKERRQ(ierr);
540c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->ht);CHKERRQ(ierr);
541c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->points);CHKERRQ(ierr);
542ad8374ffSToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->validIS);CHKERRQ(ierr);
543c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
544e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelnew)->ht[v]);CHKERRQ(ierr);
545c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
546c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
547ad8374ffSToby Isaac     ierr = PetscObjectReference((PetscObject) (label->points[v]));CHKERRQ(ierr);
548ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
549b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
550c58f1c22SToby Isaac   }
551f14fe40dSLisandro Dalcin   ierr = PetscHMapIDestroy(&(*labelnew)->hmap);CHKERRQ(ierr);
552b9907514SLisandro Dalcin   ierr = PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap);CHKERRQ(ierr);
553c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
554c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
555c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
556c58f1c22SToby Isaac   PetscFunctionReturn(0);
557c58f1c22SToby Isaac }
558c58f1c22SToby Isaac 
559c6a43d28SMatthew G. Knepley /*@
560c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
561c6a43d28SMatthew G. Knepley 
5625b5e7992SMatthew G. Knepley   Not collective
5635b5e7992SMatthew G. Knepley 
564c6a43d28SMatthew G. Knepley   Input Parameter:
565c6a43d28SMatthew G. Knepley . label  - The DMLabel
566c6a43d28SMatthew G. Knepley 
567c6a43d28SMatthew G. Knepley   Level: intermediate
568c6a43d28SMatthew G. Knepley 
569c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
570c6a43d28SMatthew G. Knepley @*/
571c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
572c6a43d28SMatthew G. Knepley {
573c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
574c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
575c6a43d28SMatthew G. Knepley 
576c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
577c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
578c6a43d28SMatthew G. Knepley   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
579c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
580c6a43d28SMatthew G. Knepley     const PetscInt *points;
581c6a43d28SMatthew G. Knepley     PetscInt       i;
582c6a43d28SMatthew G. Knepley 
583c6a43d28SMatthew G. Knepley     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
584c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
585c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
586c6a43d28SMatthew G. Knepley 
587c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
588c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
589c6a43d28SMatthew G. Knepley     }
590c6a43d28SMatthew G. Knepley     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
591c6a43d28SMatthew G. Knepley   }
592c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
593c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
594c6a43d28SMatthew G. Knepley   ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
595c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
596c6a43d28SMatthew G. Knepley }
597c6a43d28SMatthew G. Knepley 
598c6a43d28SMatthew G. Knepley /*@
599c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
600c6a43d28SMatthew G. Knepley 
6015b5e7992SMatthew G. Knepley   Not collective
6025b5e7992SMatthew G. Knepley 
603c6a43d28SMatthew G. Knepley   Input Parameters:
604c6a43d28SMatthew G. Knepley + label  - The DMLabel
605c6a43d28SMatthew G. Knepley . pStart - The smallest point
606c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
607c6a43d28SMatthew G. Knepley 
608c6a43d28SMatthew G. Knepley   Level: intermediate
609c6a43d28SMatthew G. Knepley 
610c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelComputeIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
611c6a43d28SMatthew G. Knepley @*/
612c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
613c58f1c22SToby Isaac {
614c58f1c22SToby Isaac   PetscInt       v;
615c58f1c22SToby Isaac   PetscErrorCode ierr;
616c58f1c22SToby Isaac 
617c58f1c22SToby Isaac   PetscFunctionBegin;
618d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6190c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
620c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
621c58f1c22SToby Isaac   label->pStart = pStart;
622c58f1c22SToby Isaac   label->pEnd   = pEnd;
623c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
624c58f1c22SToby Isaac   ierr = PetscBTCreate(pEnd - pStart, &label->bt);CHKERRQ(ierr);
625c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
626ad8374ffSToby Isaac     const PetscInt *points;
627c58f1c22SToby Isaac     PetscInt       i;
628c58f1c22SToby Isaac 
629ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
630c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
631ad8374ffSToby Isaac       const PetscInt point = points[i];
632c58f1c22SToby Isaac 
633c58f1c22SToby 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);
634c58f1c22SToby Isaac       ierr = PetscBTSet(label->bt, point - pStart);CHKERRQ(ierr);
635c58f1c22SToby Isaac     }
636ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
637c58f1c22SToby Isaac   }
638c58f1c22SToby Isaac   PetscFunctionReturn(0);
639c58f1c22SToby Isaac }
640c58f1c22SToby Isaac 
641c6a43d28SMatthew G. Knepley /*@
642c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
643c6a43d28SMatthew G. Knepley 
6445b5e7992SMatthew G. Knepley   Not collective
6455b5e7992SMatthew G. Knepley 
646c6a43d28SMatthew G. Knepley   Input Parameter:
647c6a43d28SMatthew G. Knepley . label - the DMLabel
648c6a43d28SMatthew G. Knepley 
649c6a43d28SMatthew G. Knepley   Level: intermediate
650c6a43d28SMatthew G. Knepley 
651c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
652c6a43d28SMatthew G. Knepley @*/
653c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
654c58f1c22SToby Isaac {
655c58f1c22SToby Isaac   PetscErrorCode ierr;
656c58f1c22SToby Isaac 
657c58f1c22SToby Isaac   PetscFunctionBegin;
658d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
659c58f1c22SToby Isaac   label->pStart = -1;
660c58f1c22SToby Isaac   label->pEnd   = -1;
6610c3c4a36SLisandro Dalcin   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
662c58f1c22SToby Isaac   PetscFunctionReturn(0);
663c58f1c22SToby Isaac }
664c58f1c22SToby Isaac 
665c58f1c22SToby Isaac /*@
666c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
667c6a43d28SMatthew G. Knepley 
6685b5e7992SMatthew G. Knepley   Not collective
6695b5e7992SMatthew G. Knepley 
670c6a43d28SMatthew G. Knepley   Input Parameter:
671c6a43d28SMatthew G. Knepley . label - the DMLabel
672c6a43d28SMatthew G. Knepley 
673c6a43d28SMatthew G. Knepley   Output Parameters:
674c6a43d28SMatthew G. Knepley + pStart - The smallest point
675c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
676c6a43d28SMatthew G. Knepley 
677c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
678c6a43d28SMatthew G. Knepley 
679c6a43d28SMatthew G. Knepley   Level: intermediate
680c6a43d28SMatthew G. Knepley 
681c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
682c6a43d28SMatthew G. Knepley @*/
683c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
684c6a43d28SMatthew G. Knepley {
685c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
686c6a43d28SMatthew G. Knepley 
687c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
688c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
689c6a43d28SMatthew G. Knepley   if ((label->pStart == -1) && (label->pEnd == -1)) {ierr = DMLabelComputeIndex(label);CHKERRQ(ierr);}
690c6a43d28SMatthew G. Knepley   if (pStart) {
691534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
692c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
693c6a43d28SMatthew G. Knepley   }
694c6a43d28SMatthew G. Knepley   if (pEnd) {
695534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
696c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
697c6a43d28SMatthew G. Knepley   }
698c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
699c6a43d28SMatthew G. Knepley }
700c6a43d28SMatthew G. Knepley 
701c6a43d28SMatthew G. Knepley /*@
702c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
703c58f1c22SToby Isaac 
7045b5e7992SMatthew G. Knepley   Not collective
7055b5e7992SMatthew G. Knepley 
706c58f1c22SToby Isaac   Input Parameters:
707c58f1c22SToby Isaac + label - the DMLabel
708c58f1c22SToby Isaac - value - the value
709c58f1c22SToby Isaac 
710c58f1c22SToby Isaac   Output Parameter:
711c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
712c58f1c22SToby Isaac 
713c58f1c22SToby Isaac   Level: developer
714c58f1c22SToby Isaac 
715c58f1c22SToby Isaac .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue()
716c58f1c22SToby Isaac @*/
717c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
718c58f1c22SToby Isaac {
719c58f1c22SToby Isaac   PetscInt v;
7200c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
721c58f1c22SToby Isaac 
722c58f1c22SToby Isaac   PetscFunctionBegin;
723d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
724534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
7250c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
7260c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
727c58f1c22SToby Isaac   PetscFunctionReturn(0);
728c58f1c22SToby Isaac }
729c58f1c22SToby Isaac 
730c58f1c22SToby Isaac /*@
731c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
732c58f1c22SToby Isaac 
7335b5e7992SMatthew G. Knepley   Not collective
7345b5e7992SMatthew G. Knepley 
735c58f1c22SToby Isaac   Input Parameters:
736c58f1c22SToby Isaac + label - the DMLabel
737c58f1c22SToby Isaac - point - the point
738c58f1c22SToby Isaac 
739c58f1c22SToby Isaac   Output Parameter:
740c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
741c58f1c22SToby Isaac 
742c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
743c58f1c22SToby Isaac 
744c58f1c22SToby Isaac   Level: developer
745c58f1c22SToby Isaac 
746c58f1c22SToby Isaac .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
747c58f1c22SToby Isaac @*/
748c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
749c58f1c22SToby Isaac {
750c58f1c22SToby Isaac   PetscErrorCode ierr;
751c58f1c22SToby Isaac 
752c58f1c22SToby Isaac   PetscFunctionBeginHot;
753d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
754534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
755c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
75676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
757c58f1c22SToby Isaac     if (!label->bt) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
758c58f1c22SToby 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);
75976bd3646SJed Brown   }
760c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
761c58f1c22SToby Isaac   PetscFunctionReturn(0);
762c58f1c22SToby Isaac }
763c58f1c22SToby Isaac 
764c58f1c22SToby Isaac /*@
765c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
766c58f1c22SToby Isaac 
7675b5e7992SMatthew G. Knepley   Not collective
7685b5e7992SMatthew G. Knepley 
769c58f1c22SToby Isaac   Input Parameters:
770c58f1c22SToby Isaac + label - the DMLabel
771c58f1c22SToby Isaac . value - the stratum value
772c58f1c22SToby Isaac - point - the point
773c58f1c22SToby Isaac 
774c58f1c22SToby Isaac   Output Parameter:
775c58f1c22SToby Isaac . contains - true if the stratum contains the point
776c58f1c22SToby Isaac 
777c58f1c22SToby Isaac   Level: intermediate
778c58f1c22SToby Isaac 
779c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue()
780c58f1c22SToby Isaac @*/
781c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
782c58f1c22SToby Isaac {
783c58f1c22SToby Isaac   PetscInt       v;
784c58f1c22SToby Isaac   PetscErrorCode ierr;
785c58f1c22SToby Isaac 
7860c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
787d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
788534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
789c58f1c22SToby Isaac   *contains = PETSC_FALSE;
7900c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
7910c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
7920c3c4a36SLisandro Dalcin 
793ad8374ffSToby Isaac   if (label->validIS[v]) {
794c58f1c22SToby Isaac     PetscInt i;
795c58f1c22SToby Isaac 
796a2d74346SToby Isaac     ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
7970c3c4a36SLisandro Dalcin     if (i >= 0) *contains = PETSC_TRUE;
798c58f1c22SToby Isaac   } else {
799c58f1c22SToby Isaac     PetscBool has;
800c58f1c22SToby Isaac 
801b9907514SLisandro Dalcin     ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
8020c3c4a36SLisandro Dalcin     if (has) *contains = PETSC_TRUE;
803c58f1c22SToby Isaac   }
804c58f1c22SToby Isaac   PetscFunctionReturn(0);
805c58f1c22SToby Isaac }
806c58f1c22SToby Isaac 
80784f0b6dfSMatthew G. Knepley /*@
8085aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8095aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8105aa44df4SToby Isaac 
8115b5e7992SMatthew G. Knepley   Not collective
8125b5e7992SMatthew G. Knepley 
8135aa44df4SToby Isaac   Input parameter:
8145aa44df4SToby Isaac . label - a DMLabel object
8155aa44df4SToby Isaac 
8165aa44df4SToby Isaac   Output parameter:
8175aa44df4SToby Isaac . defaultValue - the default value
8185aa44df4SToby Isaac 
8195aa44df4SToby Isaac   Level: beginner
8205aa44df4SToby Isaac 
8215aa44df4SToby Isaac .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
82284f0b6dfSMatthew G. Knepley @*/
8235aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
8245aa44df4SToby Isaac {
8255aa44df4SToby Isaac   PetscFunctionBegin;
826d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8275aa44df4SToby Isaac   *defaultValue = label->defaultValue;
8285aa44df4SToby Isaac   PetscFunctionReturn(0);
8295aa44df4SToby Isaac }
8305aa44df4SToby Isaac 
83184f0b6dfSMatthew G. Knepley /*@
8325aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8335aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8345aa44df4SToby Isaac 
8355b5e7992SMatthew G. Knepley   Not collective
8365b5e7992SMatthew G. Knepley 
8375aa44df4SToby Isaac   Input parameter:
8385aa44df4SToby Isaac . label - a DMLabel object
8395aa44df4SToby Isaac 
8405aa44df4SToby Isaac   Output parameter:
8415aa44df4SToby Isaac . defaultValue - the default value
8425aa44df4SToby Isaac 
8435aa44df4SToby Isaac   Level: beginner
8445aa44df4SToby Isaac 
8455aa44df4SToby Isaac .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
84684f0b6dfSMatthew G. Knepley @*/
8475aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
8485aa44df4SToby Isaac {
8495aa44df4SToby Isaac   PetscFunctionBegin;
850d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8515aa44df4SToby Isaac   label->defaultValue = defaultValue;
8525aa44df4SToby Isaac   PetscFunctionReturn(0);
8535aa44df4SToby Isaac }
8545aa44df4SToby Isaac 
855c58f1c22SToby Isaac /*@
8565aa44df4SToby 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())
857c58f1c22SToby Isaac 
8585b5e7992SMatthew G. Knepley   Not collective
8595b5e7992SMatthew G. Knepley 
860c58f1c22SToby Isaac   Input Parameters:
861c58f1c22SToby Isaac + label - the DMLabel
862c58f1c22SToby Isaac - point - the point
863c58f1c22SToby Isaac 
864c58f1c22SToby Isaac   Output Parameter:
8658e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
866c58f1c22SToby Isaac 
867c58f1c22SToby Isaac   Level: intermediate
868c58f1c22SToby Isaac 
8695aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
870c58f1c22SToby Isaac @*/
871c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
872c58f1c22SToby Isaac {
873c58f1c22SToby Isaac   PetscInt       v;
874c58f1c22SToby Isaac   PetscErrorCode ierr;
875c58f1c22SToby Isaac 
8760c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
877d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
878c58f1c22SToby Isaac   PetscValidPointer(value, 3);
8795aa44df4SToby Isaac   *value = label->defaultValue;
880c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
881ad8374ffSToby Isaac     if (label->validIS[v]) {
882c58f1c22SToby Isaac       PetscInt i;
883c58f1c22SToby Isaac 
884a2d74346SToby Isaac       ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
885c58f1c22SToby Isaac       if (i >= 0) {
886c58f1c22SToby Isaac         *value = label->stratumValues[v];
887c58f1c22SToby Isaac         break;
888c58f1c22SToby Isaac       }
889c58f1c22SToby Isaac     } else {
890c58f1c22SToby Isaac       PetscBool has;
891c58f1c22SToby Isaac 
892b9907514SLisandro Dalcin       ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
893c58f1c22SToby Isaac       if (has) {
894c58f1c22SToby Isaac         *value = label->stratumValues[v];
895c58f1c22SToby Isaac         break;
896c58f1c22SToby Isaac       }
897c58f1c22SToby Isaac     }
898c58f1c22SToby Isaac   }
899c58f1c22SToby Isaac   PetscFunctionReturn(0);
900c58f1c22SToby Isaac }
901c58f1c22SToby Isaac 
902c58f1c22SToby Isaac /*@
903367003a6SStefano 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.
904c58f1c22SToby Isaac 
9055b5e7992SMatthew G. Knepley   Not collective
9065b5e7992SMatthew G. Knepley 
907c58f1c22SToby Isaac   Input Parameters:
908c58f1c22SToby Isaac + label - the DMLabel
909c58f1c22SToby Isaac . point - the point
910c58f1c22SToby Isaac - value - The point value
911c58f1c22SToby Isaac 
912c58f1c22SToby Isaac   Level: intermediate
913c58f1c22SToby Isaac 
9145aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
915c58f1c22SToby Isaac @*/
916c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
917c58f1c22SToby Isaac {
918c58f1c22SToby Isaac   PetscInt       v;
919c58f1c22SToby Isaac   PetscErrorCode ierr;
920c58f1c22SToby Isaac 
921c58f1c22SToby Isaac   PetscFunctionBegin;
922d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9230c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
9245aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
925b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
926c58f1c22SToby Isaac   /* Set key */
9270c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
928e8f14785SLisandro Dalcin   ierr = PetscHSetIAdd(label->ht[v], point);CHKERRQ(ierr);
929c58f1c22SToby Isaac   PetscFunctionReturn(0);
930c58f1c22SToby Isaac }
931c58f1c22SToby Isaac 
932c58f1c22SToby Isaac /*@
933c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
934c58f1c22SToby Isaac 
9355b5e7992SMatthew G. Knepley   Not collective
9365b5e7992SMatthew G. Knepley 
937c58f1c22SToby Isaac   Input Parameters:
938c58f1c22SToby Isaac + label - the DMLabel
939c58f1c22SToby Isaac . point - the point
940c58f1c22SToby Isaac - value - The point value
941c58f1c22SToby Isaac 
942c58f1c22SToby Isaac   Level: intermediate
943c58f1c22SToby Isaac 
944c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue()
945c58f1c22SToby Isaac @*/
946c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
947c58f1c22SToby Isaac {
948ad8374ffSToby Isaac   PetscInt       v;
949c58f1c22SToby Isaac   PetscErrorCode ierr;
950c58f1c22SToby Isaac 
951c58f1c22SToby Isaac   PetscFunctionBegin;
952d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
953c58f1c22SToby Isaac   /* Find label value */
9540c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
9550c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
9560c3c4a36SLisandro Dalcin 
957eeed21e7SToby Isaac   if (label->bt) {
958eeed21e7SToby 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);
959eeed21e7SToby Isaac     ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
960eeed21e7SToby Isaac   }
9610c3c4a36SLisandro Dalcin 
9620c3c4a36SLisandro Dalcin   /* Delete key */
9630c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
964e8f14785SLisandro Dalcin   ierr = PetscHSetIDel(label->ht[v], point);CHKERRQ(ierr);
965c58f1c22SToby Isaac   PetscFunctionReturn(0);
966c58f1c22SToby Isaac }
967c58f1c22SToby Isaac 
968c58f1c22SToby Isaac /*@
969c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
970c58f1c22SToby Isaac 
9715b5e7992SMatthew G. Knepley   Not collective
9725b5e7992SMatthew G. Knepley 
973c58f1c22SToby Isaac   Input Parameters:
974c58f1c22SToby Isaac + label - the DMLabel
975c58f1c22SToby Isaac . is    - the point IS
976c58f1c22SToby Isaac - value - The point value
977c58f1c22SToby Isaac 
978c58f1c22SToby Isaac   Level: intermediate
979c58f1c22SToby Isaac 
980c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
981c58f1c22SToby Isaac @*/
982c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
983c58f1c22SToby Isaac {
9840c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
985c58f1c22SToby Isaac   const PetscInt *points;
986c58f1c22SToby Isaac   PetscErrorCode  ierr;
987c58f1c22SToby Isaac 
988c58f1c22SToby Isaac   PetscFunctionBegin;
989d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
990c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9910c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
9920c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
993b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
9940c3c4a36SLisandro Dalcin   /* Set keys */
9950c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
996c58f1c22SToby Isaac   ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr);
997c58f1c22SToby Isaac   ierr = ISGetIndices(is, &points);CHKERRQ(ierr);
998e8f14785SLisandro Dalcin   for (p = 0; p < n; ++p) {ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);}
999c58f1c22SToby Isaac   ierr = ISRestoreIndices(is, &points);CHKERRQ(ierr);
1000c58f1c22SToby Isaac   PetscFunctionReturn(0);
1001c58f1c22SToby Isaac }
1002c58f1c22SToby Isaac 
100384f0b6dfSMatthew G. Knepley /*@
100484f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
100584f0b6dfSMatthew G. Knepley 
10065b5e7992SMatthew G. Knepley   Not collective
10075b5e7992SMatthew G. Knepley 
100884f0b6dfSMatthew G. Knepley   Input Parameter:
100984f0b6dfSMatthew G. Knepley . label - the DMLabel
101084f0b6dfSMatthew G. Knepley 
101101d2d390SJose E. Roman   Output Parameter:
101284f0b6dfSMatthew G. Knepley . numValues - the number of values
101384f0b6dfSMatthew G. Knepley 
101484f0b6dfSMatthew G. Knepley   Level: intermediate
101584f0b6dfSMatthew G. Knepley 
101684f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
101784f0b6dfSMatthew G. Knepley @*/
1018c58f1c22SToby Isaac PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1019c58f1c22SToby Isaac {
1020c58f1c22SToby Isaac   PetscFunctionBegin;
1021d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1022c58f1c22SToby Isaac   PetscValidPointer(numValues, 2);
1023c58f1c22SToby Isaac   *numValues = label->numStrata;
1024c58f1c22SToby Isaac   PetscFunctionReturn(0);
1025c58f1c22SToby Isaac }
1026c58f1c22SToby Isaac 
102784f0b6dfSMatthew G. Knepley /*@
102884f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
102984f0b6dfSMatthew G. Knepley 
10305b5e7992SMatthew G. Knepley   Not collective
10315b5e7992SMatthew G. Knepley 
103284f0b6dfSMatthew G. Knepley   Input Parameter:
103384f0b6dfSMatthew G. Knepley . label - the DMLabel
103484f0b6dfSMatthew G. Knepley 
103501d2d390SJose E. Roman   Output Parameter:
103684f0b6dfSMatthew G. Knepley . is    - the value IS
103784f0b6dfSMatthew G. Knepley 
103884f0b6dfSMatthew G. Knepley   Level: intermediate
103984f0b6dfSMatthew G. Knepley 
104084f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
104184f0b6dfSMatthew G. Knepley @*/
1042c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1043c58f1c22SToby Isaac {
1044c58f1c22SToby Isaac   PetscErrorCode ierr;
1045c58f1c22SToby Isaac 
1046c58f1c22SToby Isaac   PetscFunctionBegin;
1047d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1048c58f1c22SToby Isaac   PetscValidPointer(values, 2);
1049c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values);CHKERRQ(ierr);
1050c58f1c22SToby Isaac   PetscFunctionReturn(0);
1051c58f1c22SToby Isaac }
1052c58f1c22SToby Isaac 
105384f0b6dfSMatthew G. Knepley /*@
1054d123abd9SMatthew G. Knepley   DMLabelGetValueIndex - Get the index of a given value in the list of values for the DMlabel, or -1 if it is not present
1055d123abd9SMatthew G. Knepley 
1056d123abd9SMatthew G. Knepley   Not collective
1057d123abd9SMatthew G. Knepley 
1058d123abd9SMatthew G. Knepley   Input Parameters:
1059d123abd9SMatthew G. Knepley + label - the DMLabel
1060d123abd9SMatthew G. Knepley = value - the value
1061d123abd9SMatthew G. Knepley 
106201d2d390SJose E. Roman   Output Parameter:
1063d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1064d123abd9SMatthew G. Knepley 
1065d123abd9SMatthew G. Knepley   Level: intermediate
1066d123abd9SMatthew G. Knepley 
1067d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
1068d123abd9SMatthew G. Knepley @*/
1069d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1070d123abd9SMatthew G. Knepley {
1071d123abd9SMatthew G. Knepley   PetscInt v;
1072d123abd9SMatthew G. Knepley 
1073d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1074d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1075d123abd9SMatthew G. Knepley   PetscValidPointer(index, 3);
1076d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
1077d123abd9SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) if (label->stratumValues[v] == value) break;
1078d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1079d123abd9SMatthew G. Knepley   else                       *index = v;
1080d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1081d123abd9SMatthew G. Knepley }
1082d123abd9SMatthew G. Knepley 
1083d123abd9SMatthew G. Knepley /*@
108484f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
108584f0b6dfSMatthew G. Knepley 
10865b5e7992SMatthew G. Knepley   Not collective
10875b5e7992SMatthew G. Knepley 
108884f0b6dfSMatthew G. Knepley   Input Parameters:
108984f0b6dfSMatthew G. Knepley + label - the DMLabel
109084f0b6dfSMatthew G. Knepley - value - the stratum value
109184f0b6dfSMatthew G. Knepley 
109201d2d390SJose E. Roman   Output Parameter:
109384f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
109484f0b6dfSMatthew G. Knepley 
109584f0b6dfSMatthew G. Knepley   Level: intermediate
109684f0b6dfSMatthew G. Knepley 
109784f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
109884f0b6dfSMatthew G. Knepley @*/
1099fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1100fada774cSMatthew G. Knepley {
1101fada774cSMatthew G. Knepley   PetscInt       v;
11020c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
1103fada774cSMatthew G. Knepley 
1104fada774cSMatthew G. Knepley   PetscFunctionBegin;
1105d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1106fada774cSMatthew G. Knepley   PetscValidPointer(exists, 3);
11070c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11080c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1109fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1110fada774cSMatthew G. Knepley }
1111fada774cSMatthew G. Knepley 
111284f0b6dfSMatthew G. Knepley /*@
111384f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
111484f0b6dfSMatthew G. Knepley 
11155b5e7992SMatthew G. Knepley   Not collective
11165b5e7992SMatthew G. Knepley 
111784f0b6dfSMatthew G. Knepley   Input Parameters:
111884f0b6dfSMatthew G. Knepley + label - the DMLabel
111984f0b6dfSMatthew G. Knepley - value - the stratum value
112084f0b6dfSMatthew G. Knepley 
112101d2d390SJose E. Roman   Output Parameter:
112284f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
112384f0b6dfSMatthew G. Knepley 
112484f0b6dfSMatthew G. Knepley   Level: intermediate
112584f0b6dfSMatthew G. Knepley 
112684f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
112784f0b6dfSMatthew G. Knepley @*/
1128c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1129c58f1c22SToby Isaac {
1130c58f1c22SToby Isaac   PetscInt       v;
1131c58f1c22SToby Isaac   PetscErrorCode ierr;
1132c58f1c22SToby Isaac 
1133c58f1c22SToby Isaac   PetscFunctionBegin;
1134d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1135c58f1c22SToby Isaac   PetscValidPointer(size, 3);
1136c58f1c22SToby Isaac   *size = 0;
11370c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11380c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1139c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1140c58f1c22SToby Isaac   *size = label->stratumSizes[v];
1141c58f1c22SToby Isaac   PetscFunctionReturn(0);
1142c58f1c22SToby Isaac }
1143c58f1c22SToby Isaac 
114484f0b6dfSMatthew G. Knepley /*@
114584f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
114684f0b6dfSMatthew G. Knepley 
11475b5e7992SMatthew G. Knepley   Not collective
11485b5e7992SMatthew G. Knepley 
114984f0b6dfSMatthew G. Knepley   Input Parameters:
115084f0b6dfSMatthew G. Knepley + label - the DMLabel
115184f0b6dfSMatthew G. Knepley - value - the stratum value
115284f0b6dfSMatthew G. Knepley 
115301d2d390SJose E. Roman   Output Parameters:
115484f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
115584f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
115684f0b6dfSMatthew G. Knepley 
115784f0b6dfSMatthew G. Knepley   Level: intermediate
115884f0b6dfSMatthew G. Knepley 
115984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
116084f0b6dfSMatthew G. Knepley @*/
1161c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1162c58f1c22SToby Isaac {
11630c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1164c58f1c22SToby Isaac   PetscErrorCode ierr;
1165c58f1c22SToby Isaac 
1166c58f1c22SToby Isaac   PetscFunctionBegin;
1167d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1168412e9a14SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = label->defaultValue;}
1169412e9a14SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = label->defaultValue;}
11700c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11710c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1172c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
11730c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
1174d6cb179aSToby Isaac   ierr = ISGetMinMax(label->points[v], &min, &max);CHKERRQ(ierr);
1175d6cb179aSToby Isaac   if (start) *start = min;
1176d6cb179aSToby Isaac   if (end)   *end   = max+1;
1177c58f1c22SToby Isaac   PetscFunctionReturn(0);
1178c58f1c22SToby Isaac }
1179c58f1c22SToby Isaac 
118084f0b6dfSMatthew G. Knepley /*@
118184f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
118284f0b6dfSMatthew G. Knepley 
11835b5e7992SMatthew G. Knepley   Not collective
11845b5e7992SMatthew G. Knepley 
118584f0b6dfSMatthew G. Knepley   Input Parameters:
118684f0b6dfSMatthew G. Knepley + label - the DMLabel
118784f0b6dfSMatthew G. Knepley - value - the stratum value
118884f0b6dfSMatthew G. Knepley 
118901d2d390SJose E. Roman   Output Parameter:
119084f0b6dfSMatthew G. Knepley . points - The stratum points
119184f0b6dfSMatthew G. Knepley 
119284f0b6dfSMatthew G. Knepley   Level: intermediate
119384f0b6dfSMatthew G. Knepley 
1194593ce467SVaclav Hapla   Notes:
1195593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1196593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1197593ce467SVaclav Hapla 
119884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
119984f0b6dfSMatthew G. Knepley @*/
1200c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1201c58f1c22SToby Isaac {
1202c58f1c22SToby Isaac   PetscInt       v;
1203c58f1c22SToby Isaac   PetscErrorCode ierr;
1204c58f1c22SToby Isaac 
1205c58f1c22SToby Isaac   PetscFunctionBegin;
1206d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1207c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1208c58f1c22SToby Isaac   *points = NULL;
12090c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
12100c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1211c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1212ad8374ffSToby Isaac   ierr = PetscObjectReference((PetscObject) label->points[v]);CHKERRQ(ierr);
1213ad8374ffSToby Isaac   *points = label->points[v];
1214c58f1c22SToby Isaac   PetscFunctionReturn(0);
1215c58f1c22SToby Isaac }
1216c58f1c22SToby Isaac 
121784f0b6dfSMatthew G. Knepley /*@
121884f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
121984f0b6dfSMatthew G. Knepley 
12205b5e7992SMatthew G. Knepley   Not collective
12215b5e7992SMatthew G. Knepley 
122284f0b6dfSMatthew G. Knepley   Input Parameters:
122384f0b6dfSMatthew G. Knepley + label - the DMLabel
122484f0b6dfSMatthew G. Knepley . value - the stratum value
122584f0b6dfSMatthew G. Knepley - points - The stratum points
122684f0b6dfSMatthew G. Knepley 
122784f0b6dfSMatthew G. Knepley   Level: intermediate
122884f0b6dfSMatthew G. Knepley 
122984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
123084f0b6dfSMatthew G. Knepley @*/
12314de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
12324de306b1SToby Isaac {
12330c3c4a36SLisandro Dalcin   PetscInt       v;
12344de306b1SToby Isaac   PetscErrorCode ierr;
12354de306b1SToby Isaac 
12364de306b1SToby Isaac   PetscFunctionBegin;
1237d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1238d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
1239b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
12404de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
12414de306b1SToby Isaac   ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr);
12424de306b1SToby Isaac   ierr = ISGetLocalSize(is, &(label->stratumSizes[v]));CHKERRQ(ierr);
12434de306b1SToby Isaac   ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
12444de306b1SToby Isaac   ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr);
12450c3c4a36SLisandro Dalcin   label->points[v]  = is;
12460c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
1247277ea44aSLisandro Dalcin   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
12484de306b1SToby Isaac   if (label->bt) {
12494de306b1SToby Isaac     const PetscInt *points;
12504de306b1SToby Isaac     PetscInt p;
12514de306b1SToby Isaac 
12524de306b1SToby Isaac     ierr = ISGetIndices(is,&points);CHKERRQ(ierr);
12534de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
12544de306b1SToby Isaac       const PetscInt point = points[p];
12554de306b1SToby Isaac 
12564de306b1SToby 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);
12574de306b1SToby Isaac       ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr);
12584de306b1SToby Isaac     }
12594de306b1SToby Isaac   }
12604de306b1SToby Isaac   PetscFunctionReturn(0);
12614de306b1SToby Isaac }
12624de306b1SToby Isaac 
126384f0b6dfSMatthew G. Knepley /*@
126484f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
12654de306b1SToby Isaac 
12665b5e7992SMatthew G. Knepley   Not collective
12675b5e7992SMatthew G. Knepley 
126884f0b6dfSMatthew G. Knepley   Input Parameters:
126984f0b6dfSMatthew G. Knepley + label - the DMLabel
127084f0b6dfSMatthew G. Knepley - value - the stratum value
127184f0b6dfSMatthew G. Knepley 
127284f0b6dfSMatthew G. Knepley   Level: intermediate
127384f0b6dfSMatthew G. Knepley 
127484f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
127584f0b6dfSMatthew G. Knepley @*/
1276c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1277c58f1c22SToby Isaac {
1278c58f1c22SToby Isaac   PetscInt       v;
1279c58f1c22SToby Isaac   PetscErrorCode ierr;
1280c58f1c22SToby Isaac 
1281c58f1c22SToby Isaac   PetscFunctionBegin;
1282d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12830c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
12840c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
12854de306b1SToby Isaac   if (label->validIS[v]) {
12864de306b1SToby Isaac     if (label->bt) {
1287c58f1c22SToby Isaac       PetscInt       i;
1288ad8374ffSToby Isaac       const PetscInt *points;
1289c58f1c22SToby Isaac 
1290ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
1291c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1292ad8374ffSToby Isaac         const PetscInt point = points[i];
1293c58f1c22SToby Isaac 
1294c58f1c22SToby 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);
1295c58f1c22SToby Isaac         ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
1296c58f1c22SToby Isaac       }
1297ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
1298c58f1c22SToby Isaac     }
1299c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
13000c3c4a36SLisandro Dalcin     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
1301277ea44aSLisandro Dalcin     ierr = ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]);CHKERRQ(ierr);
13020c3c4a36SLisandro Dalcin     ierr = PetscObjectSetName((PetscObject) label->points[v], "indices");CHKERRQ(ierr);
1303277ea44aSLisandro Dalcin     ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
1304c58f1c22SToby Isaac   } else {
1305b9907514SLisandro Dalcin     ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr);
1306c58f1c22SToby Isaac   }
1307c58f1c22SToby Isaac   PetscFunctionReturn(0);
1308c58f1c22SToby Isaac }
1309c58f1c22SToby Isaac 
131084f0b6dfSMatthew G. Knepley /*@
1311412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1312412e9a14SMatthew G. Knepley 
1313412e9a14SMatthew G. Knepley   Not collective
1314412e9a14SMatthew G. Knepley 
1315412e9a14SMatthew G. Knepley   Input Parameters:
1316412e9a14SMatthew G. Knepley + label  - The DMLabel
1317412e9a14SMatthew G. Knepley . value  - The label value for all points
1318412e9a14SMatthew G. Knepley . pStart - The first point
1319412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1320412e9a14SMatthew G. Knepley 
1321412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1322412e9a14SMatthew G. Knepley 
1323412e9a14SMatthew G. Knepley   Level: intermediate
1324412e9a14SMatthew G. Knepley 
1325412e9a14SMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelSetStratumIS(), DMLabelGetStratumIS()
1326412e9a14SMatthew G. Knepley @*/
1327412e9a14SMatthew G. Knepley PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1328412e9a14SMatthew G. Knepley {
1329412e9a14SMatthew G. Knepley   IS             pIS;
1330412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1331412e9a14SMatthew G. Knepley 
1332412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1333412e9a14SMatthew G. Knepley   ierr = ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS);CHKERRQ(ierr);
1334412e9a14SMatthew G. Knepley   ierr = DMLabelSetStratumIS(label, value, pIS);CHKERRQ(ierr);
1335412e9a14SMatthew G. Knepley   ierr = ISDestroy(&pIS);CHKERRQ(ierr);
1336412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1337412e9a14SMatthew G. Knepley }
1338412e9a14SMatthew G. Knepley 
1339412e9a14SMatthew G. Knepley /*@
1340d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1341d123abd9SMatthew G. Knepley 
1342d123abd9SMatthew G. Knepley   Not collective
1343d123abd9SMatthew G. Knepley 
1344d123abd9SMatthew G. Knepley   Input Parameters:
1345d123abd9SMatthew G. Knepley + label  - The DMLabel
1346d123abd9SMatthew G. Knepley . value  - The label value
1347d123abd9SMatthew G. Knepley - p      - A point with this value
1348d123abd9SMatthew G. Knepley 
1349d123abd9SMatthew G. Knepley   Output Parameter:
1350d123abd9SMatthew G. Knepley . index  - The index of this point in the stratum, or -1 if the point is not in the stratum or the stratum does not exist
1351d123abd9SMatthew G. Knepley 
1352d123abd9SMatthew G. Knepley   Level: intermediate
1353d123abd9SMatthew G. Knepley 
1354d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIndex(), DMLabelGetStratumIS(), DMLabelCreate()
1355d123abd9SMatthew G. Knepley @*/
1356d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1357d123abd9SMatthew G. Knepley {
1358d123abd9SMatthew G. Knepley   const PetscInt *indices;
1359d123abd9SMatthew G. Knepley   PetscInt        v;
1360d123abd9SMatthew G. Knepley   PetscErrorCode  ierr;
1361d123abd9SMatthew G. Knepley 
1362d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1363d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1364d123abd9SMatthew G. Knepley   PetscValidPointer(index, 4);
1365d123abd9SMatthew G. Knepley   *index = -1;
1366d123abd9SMatthew G. Knepley   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
1367d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
1368d123abd9SMatthew G. Knepley   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1369d123abd9SMatthew G. Knepley   ierr = ISGetIndices(label->points[v], &indices);CHKERRQ(ierr);
1370d123abd9SMatthew G. Knepley   ierr = PetscFindInt(p, label->stratumSizes[v], indices, index);CHKERRQ(ierr);
1371d123abd9SMatthew G. Knepley   ierr = ISRestoreIndices(label->points[v], &indices);CHKERRQ(ierr);
1372d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1373d123abd9SMatthew G. Knepley }
1374d123abd9SMatthew G. Knepley 
1375d123abd9SMatthew G. Knepley /*@
137684f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
137784f0b6dfSMatthew G. Knepley 
13785b5e7992SMatthew G. Knepley   Not collective
13795b5e7992SMatthew G. Knepley 
138084f0b6dfSMatthew G. Knepley   Input Parameters:
138184f0b6dfSMatthew G. Knepley + label - the DMLabel
138222cd2cdaSVaclav Hapla . start - the first point kept
138322cd2cdaSVaclav Hapla - end - one more than the last point kept
138484f0b6dfSMatthew G. Knepley 
138584f0b6dfSMatthew G. Knepley   Level: intermediate
138684f0b6dfSMatthew G. Knepley 
138784f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
138884f0b6dfSMatthew G. Knepley @*/
1389c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1390c58f1c22SToby Isaac {
1391c58f1c22SToby Isaac   PetscInt       v;
1392c58f1c22SToby Isaac   PetscErrorCode ierr;
1393c58f1c22SToby Isaac 
1394c58f1c22SToby Isaac   PetscFunctionBegin;
1395d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13960c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
1397c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1398c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
13999106b633SVaclav Hapla     ierr = ISGeneralFilter(label->points[v], start, end);CHKERRQ(ierr);
1400c58f1c22SToby Isaac   }
1401c58f1c22SToby Isaac   ierr = DMLabelCreateIndex(label, start, end);CHKERRQ(ierr);
1402c58f1c22SToby Isaac   PetscFunctionReturn(0);
1403c58f1c22SToby Isaac }
1404c58f1c22SToby Isaac 
140584f0b6dfSMatthew G. Knepley /*@
140684f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
140784f0b6dfSMatthew G. Knepley 
14085b5e7992SMatthew G. Knepley   Not collective
14095b5e7992SMatthew G. Knepley 
141084f0b6dfSMatthew G. Knepley   Input Parameters:
141184f0b6dfSMatthew G. Knepley + label - the DMLabel
141284f0b6dfSMatthew G. Knepley - permutation - the point permutation
141384f0b6dfSMatthew G. Knepley 
141484f0b6dfSMatthew G. Knepley   Output Parameter:
141584f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
141684f0b6dfSMatthew G. Knepley 
141784f0b6dfSMatthew G. Knepley   Level: intermediate
141884f0b6dfSMatthew G. Knepley 
141984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
142084f0b6dfSMatthew G. Knepley @*/
1421c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1422c58f1c22SToby Isaac {
1423c58f1c22SToby Isaac   const PetscInt *perm;
1424c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1425c58f1c22SToby Isaac   PetscErrorCode  ierr;
1426c58f1c22SToby Isaac 
1427c58f1c22SToby Isaac   PetscFunctionBegin;
1428d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1429d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
1430c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1431c58f1c22SToby Isaac   ierr = DMLabelDuplicate(label, labelNew);CHKERRQ(ierr);
1432c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(*labelNew, &numValues);CHKERRQ(ierr);
1433c58f1c22SToby Isaac   ierr = ISGetLocalSize(permutation, &numPoints);CHKERRQ(ierr);
1434c58f1c22SToby Isaac   ierr = ISGetIndices(permutation, &perm);CHKERRQ(ierr);
1435c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1436c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1437ad8374ffSToby Isaac     const PetscInt *points;
1438ad8374ffSToby Isaac     PetscInt *pointsNew;
1439c58f1c22SToby Isaac 
1440ad8374ffSToby Isaac     ierr = ISGetIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1441ad8374ffSToby Isaac     ierr = PetscMalloc1(size,&pointsNew);CHKERRQ(ierr);
1442c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1443ad8374ffSToby Isaac       const PetscInt point = points[q];
1444c58f1c22SToby Isaac 
1445c58f1c22SToby 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);
1446ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1447c58f1c22SToby Isaac     }
1448ad8374ffSToby Isaac     ierr = ISRestoreIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1449ad8374ffSToby Isaac     ierr = PetscSortInt(size, pointsNew);CHKERRQ(ierr);
1450ad8374ffSToby Isaac     ierr = ISDestroy(&((*labelNew)->points[v]));CHKERRQ(ierr);
1451fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
1452fa8e8ae5SToby Isaac       ierr = ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v]));CHKERRQ(ierr);
1453fa8e8ae5SToby Isaac       ierr = PetscFree(pointsNew);CHKERRQ(ierr);
1454fa8e8ae5SToby Isaac     } else {
1455ad8374ffSToby Isaac       ierr = ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v]));CHKERRQ(ierr);
1456fa8e8ae5SToby Isaac     }
1457ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices");CHKERRQ(ierr);
1458c58f1c22SToby Isaac   }
1459c58f1c22SToby Isaac   ierr = ISRestoreIndices(permutation, &perm);CHKERRQ(ierr);
1460c58f1c22SToby Isaac   if (label->bt) {
1461c58f1c22SToby Isaac     ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
1462c58f1c22SToby Isaac     ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
1463c58f1c22SToby Isaac   }
1464c58f1c22SToby Isaac   PetscFunctionReturn(0);
1465c58f1c22SToby Isaac }
1466c58f1c22SToby Isaac 
146726c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
146826c55118SMichael Lange {
146926c55118SMichael Lange   MPI_Comm       comm;
147026c55118SMichael Lange   PetscInt       s, l, nroots, nleaves, dof, offset, size;
147126c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
147226c55118SMichael Lange   PetscSection   rootSection;
147326c55118SMichael Lange   PetscSF        labelSF;
147426c55118SMichael Lange   PetscErrorCode ierr;
147526c55118SMichael Lange 
147626c55118SMichael Lange   PetscFunctionBegin;
147726c55118SMichael Lange   if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);}
147826c55118SMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
147926c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
148026c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
148126c55118SMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL);CHKERRQ(ierr);
148226c55118SMichael Lange   ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr);
148326c55118SMichael Lange   ierr = PetscSectionSetChart(rootSection, 0, nroots);CHKERRQ(ierr);
148426c55118SMichael Lange   if (label) {
148526c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1486ad8374ffSToby Isaac       const PetscInt *points;
1487ad8374ffSToby Isaac 
1488ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
148926c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1490ad8374ffSToby Isaac         ierr = PetscSectionGetDof(rootSection, points[l], &dof);CHKERRQ(ierr);
1491ad8374ffSToby Isaac         ierr = PetscSectionSetDof(rootSection, points[l], dof+1);CHKERRQ(ierr);
149226c55118SMichael Lange       }
1493ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
149426c55118SMichael Lange     }
149526c55118SMichael Lange   }
149626c55118SMichael Lange   ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr);
149726c55118SMichael Lange   /* Create a point-wise array of stratum values */
149826c55118SMichael Lange   ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr);
149926c55118SMichael Lange   ierr = PetscMalloc1(size, &rootStrata);CHKERRQ(ierr);
150026c55118SMichael Lange   ierr = PetscCalloc1(nroots, &rootIdx);CHKERRQ(ierr);
150126c55118SMichael Lange   if (label) {
150226c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1503ad8374ffSToby Isaac       const PetscInt *points;
1504ad8374ffSToby Isaac 
1505ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
150626c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1507ad8374ffSToby Isaac         const PetscInt p = points[l];
150826c55118SMichael Lange         ierr = PetscSectionGetOffset(rootSection, p, &offset);CHKERRQ(ierr);
150926c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
151026c55118SMichael Lange       }
1511ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
151226c55118SMichael Lange     }
151326c55118SMichael Lange   }
151426c55118SMichael Lange   /* Build SF that maps label points to remote processes */
151526c55118SMichael Lange   ierr = PetscSectionCreate(comm, leafSection);CHKERRQ(ierr);
151626c55118SMichael Lange   ierr = PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection);CHKERRQ(ierr);
151726c55118SMichael Lange   ierr = PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF);CHKERRQ(ierr);
151826c55118SMichael Lange   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
151926c55118SMichael Lange   /* Send the strata for each point over the derived SF */
152026c55118SMichael Lange   ierr = PetscSectionGetStorageSize(*leafSection, &size);CHKERRQ(ierr);
152126c55118SMichael Lange   ierr = PetscMalloc1(size, leafStrata);CHKERRQ(ierr);
1522ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE);CHKERRQ(ierr);
1523ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE);CHKERRQ(ierr);
152426c55118SMichael Lange   /* Clean up */
152526c55118SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
152626c55118SMichael Lange   ierr = PetscFree(rootIdx);CHKERRQ(ierr);
152726c55118SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
152826c55118SMichael Lange   ierr = PetscSFDestroy(&labelSF);CHKERRQ(ierr);
152926c55118SMichael Lange   PetscFunctionReturn(0);
153026c55118SMichael Lange }
153126c55118SMichael Lange 
153284f0b6dfSMatthew G. Knepley /*@
153384f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
153484f0b6dfSMatthew G. Knepley 
15355b5e7992SMatthew G. Knepley   Collective on sf
15365b5e7992SMatthew G. Knepley 
153784f0b6dfSMatthew G. Knepley   Input Parameters:
153884f0b6dfSMatthew G. Knepley + label - the DMLabel
153984f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
154084f0b6dfSMatthew G. Knepley 
154184f0b6dfSMatthew G. Knepley   Output Parameter:
154284f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
154384f0b6dfSMatthew G. Knepley 
154484f0b6dfSMatthew G. Knepley   Level: intermediate
154584f0b6dfSMatthew G. Knepley 
154684f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
154784f0b6dfSMatthew G. Knepley @*/
1548c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1549c58f1c22SToby Isaac {
1550c58f1c22SToby Isaac   MPI_Comm       comm;
155126c55118SMichael Lange   PetscSection   leafSection;
155226c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
155326c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1554ad8374ffSToby Isaac   PetscInt     **points;
1555d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1556c58f1c22SToby Isaac   char          *name;
1557c58f1c22SToby Isaac   PetscInt       nameSize;
1558e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1559c58f1c22SToby Isaac   size_t         len = 0;
156026c55118SMichael Lange   PetscMPIInt    rank;
1561c58f1c22SToby Isaac   PetscErrorCode ierr;
1562c58f1c22SToby Isaac 
1563c58f1c22SToby Isaac   PetscFunctionBegin;
1564d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1565f018e600SMatthew G. Knepley   if (label) {
1566f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1567f018e600SMatthew G. Knepley     ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1568f018e600SMatthew G. Knepley   }
1569c58f1c22SToby Isaac   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
1570ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1571c58f1c22SToby Isaac   /* Bcast name */
1572d67d17b1SMatthew G. Knepley   if (!rank) {
1573d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1574d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1575d67d17b1SMatthew G. Knepley   }
1576c58f1c22SToby Isaac   nameSize = len;
1577ffc4695bSBarry Smith   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1578c58f1c22SToby Isaac   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1579580bdb30SBarry Smith   if (!rank) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
1580ffc4695bSBarry Smith   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr);
1581d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
1582c58f1c22SToby Isaac   ierr = PetscFree(name);CHKERRQ(ierr);
158377d236dfSMichael Lange   /* Bcast defaultValue */
158477d236dfSMichael Lange   if (!rank) (*labelNew)->defaultValue = label->defaultValue;
1585ffc4695bSBarry Smith   ierr = MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
158626c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
158726c55118SMichael Lange   ierr = DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata);CHKERRQ(ierr);
15885cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
1589e8f14785SLisandro Dalcin   ierr = PetscHSetICreate(&stratumHash);CHKERRQ(ierr);
159026c55118SMichael Lange   ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr);
1591e8f14785SLisandro Dalcin   for (p = 0; p < size; ++p) {ierr = PetscHSetIAdd(stratumHash, leafStrata[p]);CHKERRQ(ierr);}
1592e8f14785SLisandro Dalcin   ierr = PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata);CHKERRQ(ierr);
1593ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS);CHKERRQ(ierr);
1594ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
15955cbdf6fcSMichael Lange   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues);CHKERRQ(ierr);
15965cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
15975cbdf6fcSMichael Lange   offset = 0;
1598e8f14785SLisandro Dalcin   ierr = PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues);CHKERRQ(ierr);
1599a205f1fdSToby Isaac   ierr = PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues);CHKERRQ(ierr);
160090e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
160190e9b2aeSLisandro Dalcin     ierr = PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s);CHKERRQ(ierr);
160290e9b2aeSLisandro Dalcin   }
16035cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1604231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1605231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
16065cbdf6fcSMichael Lange     }
16075cbdf6fcSMichael Lange   }
1608c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
1609c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes);CHKERRQ(ierr);
1610c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1611c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1612c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1613c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1614c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1615c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1616c58f1c22SToby Isaac     }
1617c58f1c22SToby Isaac   }
1618c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht);CHKERRQ(ierr);
1619c58f1c22SToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points);CHKERRQ(ierr);
1620ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&points);CHKERRQ(ierr);
1621c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
1622e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelNew)->ht[s]);CHKERRQ(ierr);
1623ad8374ffSToby Isaac     ierr = PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s]));CHKERRQ(ierr);
1624c58f1c22SToby Isaac   }
1625c58f1c22SToby Isaac   /* Insert points into new strata */
1626c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata, &strataIdx);CHKERRQ(ierr);
1627c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1628c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1629c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1630c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1631c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1632c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1633ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1634c58f1c22SToby Isaac     }
1635c58f1c22SToby Isaac   }
1636ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1637ad8374ffSToby Isaac     ierr = ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s]));CHKERRQ(ierr);
1638ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices");CHKERRQ(ierr);
1639ad8374ffSToby Isaac   }
1640ad8374ffSToby Isaac   ierr = PetscFree(points);CHKERRQ(ierr);
1641e8f14785SLisandro Dalcin   ierr = PetscHSetIDestroy(&stratumHash);CHKERRQ(ierr);
1642c58f1c22SToby Isaac   ierr = PetscFree(leafStrata);CHKERRQ(ierr);
1643c58f1c22SToby Isaac   ierr = PetscFree(strataIdx);CHKERRQ(ierr);
1644c58f1c22SToby Isaac   ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr);
1645c58f1c22SToby Isaac   PetscFunctionReturn(0);
1646c58f1c22SToby Isaac }
1647c58f1c22SToby Isaac 
16487937d9ceSMichael Lange /*@
16497937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
16507937d9ceSMichael Lange 
16515b5e7992SMatthew G. Knepley   Collective on sf
16525b5e7992SMatthew G. Knepley 
16537937d9ceSMichael Lange   Input Parameters:
16547937d9ceSMichael Lange + label - the DMLabel
165584f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
16567937d9ceSMichael Lange 
165784f0b6dfSMatthew G. Knepley   Output Parameters:
165884f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
16597937d9ceSMichael Lange 
16607937d9ceSMichael Lange   Level: developer
16617937d9ceSMichael Lange 
16627937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
16637937d9ceSMichael Lange 
16647937d9ceSMichael Lange .seealso: DMLabelDistribute()
16657937d9ceSMichael Lange @*/
16667937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
16677937d9ceSMichael Lange {
16687937d9ceSMichael Lange   MPI_Comm       comm;
16697937d9ceSMichael Lange   PetscSection   rootSection;
16707937d9ceSMichael Lange   PetscSF        sfLabel;
16717937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
16727937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
16737937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
16747937d9ceSMichael Lange   PetscInt       *rootStrata;
1675d67d17b1SMatthew G. Knepley   const char    *lname;
16767937d9ceSMichael Lange   char          *name;
16777937d9ceSMichael Lange   PetscInt       nameSize;
16787937d9ceSMichael Lange   size_t         len = 0;
16799852e123SBarry Smith   PetscMPIInt    rank, size;
16807937d9ceSMichael Lange   PetscErrorCode ierr;
16817937d9ceSMichael Lange 
16827937d9ceSMichael Lange   PetscFunctionBegin;
1683d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1684d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
16857937d9ceSMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
1686ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1687ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
16887937d9ceSMichael Lange   /* Bcast name */
1689d67d17b1SMatthew G. Knepley   if (!rank) {
1690d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1691d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1692d67d17b1SMatthew G. Knepley   }
16937937d9ceSMichael Lange   nameSize = len;
1694ffc4695bSBarry Smith   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
16957937d9ceSMichael Lange   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1696580bdb30SBarry Smith   if (!rank) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
1697ffc4695bSBarry Smith   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr);
1698d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
16997937d9ceSMichael Lange   ierr = PetscFree(name);CHKERRQ(ierr);
17007937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
17017937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
17027937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
17037937d9ceSMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL);CHKERRQ(ierr);
1704dc53bc9bSMatthew G. Knepley   ierr = PetscMalloc1(nroots, &leafPoints);CHKERRQ(ierr);
1705dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
17067937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
17078212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
17088212dd46SStefano Zampini 
17098212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
17108212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
17117937d9ceSMichael Lange   }
17127937d9ceSMichael Lange   ierr = PetscSFComputeDegreeBegin(sf, &rootDegree);CHKERRQ(ierr);
17137937d9ceSMichael Lange   ierr = PetscSFComputeDegreeEnd(sf, &rootDegree);CHKERRQ(ierr);
17147937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
17157937d9ceSMichael Lange   ierr = PetscMalloc1(nmultiroots, &rootPoints);CHKERRQ(ierr);
17167937d9ceSMichael Lange   ierr = PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
17177937d9ceSMichael Lange   ierr = PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
17187937d9ceSMichael Lange   ierr = PetscSFCreate(comm,& sfLabel);CHKERRQ(ierr);
17197937d9ceSMichael Lange   ierr = PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
17207937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
17217937d9ceSMichael Lange   ierr = DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata);CHKERRQ(ierr);
17227937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
17237937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
17247937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
17257937d9ceSMichael Lange       ierr = PetscSectionGetDof(rootSection, idx+d, &dof);CHKERRQ(ierr);
17267937d9ceSMichael Lange       ierr = PetscSectionGetOffset(rootSection, idx+d, &offset);CHKERRQ(ierr);
17277937d9ceSMichael Lange       for (s = 0; s < dof; s++) {ierr = DMLabelSetValue(*labelNew, p, rootStrata[offset+s]);CHKERRQ(ierr);}
17287937d9ceSMichael Lange     }
17297937d9ceSMichael Lange     idx += rootDegree[p];
17307937d9ceSMichael Lange   }
173177e0c0e7SMichael Lange   ierr = PetscFree(leafPoints);CHKERRQ(ierr);
173277e0c0e7SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
173377e0c0e7SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
173477e0c0e7SMichael Lange   ierr = PetscSFDestroy(&sfLabel);CHKERRQ(ierr);
17357937d9ceSMichael Lange   PetscFunctionReturn(0);
17367937d9ceSMichael Lange }
17377937d9ceSMichael Lange 
173884f0b6dfSMatthew G. Knepley /*@
173984f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
174084f0b6dfSMatthew G. Knepley 
17415b5e7992SMatthew G. Knepley   Not collective
17425b5e7992SMatthew G. Knepley 
174384f0b6dfSMatthew G. Knepley   Input Parameter:
174484f0b6dfSMatthew G. Knepley . label - the DMLabel
174584f0b6dfSMatthew G. Knepley 
174684f0b6dfSMatthew G. Knepley   Output Parameters:
174784f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
174884f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
174984f0b6dfSMatthew G. Knepley 
175084f0b6dfSMatthew G. Knepley   Level: developer
175184f0b6dfSMatthew G. Knepley 
175284f0b6dfSMatthew G. Knepley .seealso: DMLabelDistribute()
175384f0b6dfSMatthew G. Knepley @*/
1754c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
1755c58f1c22SToby Isaac {
1756c58f1c22SToby Isaac   IS              vIS;
1757c58f1c22SToby Isaac   const PetscInt *values;
1758c58f1c22SToby Isaac   PetscInt       *points;
1759c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
1760c58f1c22SToby Isaac   PetscErrorCode  ierr;
1761c58f1c22SToby Isaac 
1762c58f1c22SToby Isaac   PetscFunctionBegin;
1763d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1764c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(label, &nV);CHKERRQ(ierr);
1765c58f1c22SToby Isaac   ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr);
1766c58f1c22SToby Isaac   ierr = ISGetIndices(vIS, &values);CHKERRQ(ierr);
1767c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
1768c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
1769c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
1770c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
1771c58f1c22SToby Isaac   }
1772c58f1c22SToby Isaac   ierr = PetscSectionCreate(PETSC_COMM_SELF, section);CHKERRQ(ierr);
1773c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*section, vS, vE);CHKERRQ(ierr);
1774c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1775c58f1c22SToby Isaac     PetscInt n;
1776c58f1c22SToby Isaac 
1777c58f1c22SToby Isaac     ierr = DMLabelGetStratumSize(label, values[v], &n);CHKERRQ(ierr);
1778c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*section, values[v], n);CHKERRQ(ierr);
1779c58f1c22SToby Isaac   }
1780c58f1c22SToby Isaac   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
1781c58f1c22SToby Isaac   ierr = PetscSectionGetStorageSize(*section, &N);CHKERRQ(ierr);
1782c58f1c22SToby Isaac   ierr = PetscMalloc1(N, &points);CHKERRQ(ierr);
1783c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1784c58f1c22SToby Isaac     IS              is;
1785c58f1c22SToby Isaac     const PetscInt *spoints;
1786c58f1c22SToby Isaac     PetscInt        dof, off, p;
1787c58f1c22SToby Isaac 
1788c58f1c22SToby Isaac     ierr = PetscSectionGetDof(*section, values[v], &dof);CHKERRQ(ierr);
1789c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(*section, values[v], &off);CHKERRQ(ierr);
1790c58f1c22SToby Isaac     ierr = DMLabelGetStratumIS(label, values[v], &is);CHKERRQ(ierr);
1791c58f1c22SToby Isaac     ierr = ISGetIndices(is, &spoints);CHKERRQ(ierr);
1792c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
1793c58f1c22SToby Isaac     ierr = ISRestoreIndices(is, &spoints);CHKERRQ(ierr);
1794c58f1c22SToby Isaac     ierr = ISDestroy(&is);CHKERRQ(ierr);
1795c58f1c22SToby Isaac   }
1796c58f1c22SToby Isaac   ierr = ISRestoreIndices(vIS, &values);CHKERRQ(ierr);
1797c58f1c22SToby Isaac   ierr = ISDestroy(&vIS);CHKERRQ(ierr);
1798c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is);CHKERRQ(ierr);
1799c58f1c22SToby Isaac   PetscFunctionReturn(0);
1800c58f1c22SToby Isaac }
1801c58f1c22SToby Isaac 
180284f0b6dfSMatthew G. Knepley /*@
1803c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
1804c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
1805c58f1c22SToby Isaac 
18065b5e7992SMatthew G. Knepley   Collective on sf
18075b5e7992SMatthew G. Knepley 
1808c58f1c22SToby Isaac   Input Parameters:
1809c58f1c22SToby Isaac   + s - The PetscSection for the local field layout
1810c58f1c22SToby Isaac   . sf - The SF describing parallel layout of the section points
1811c58f1c22SToby Isaac   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1812c58f1c22SToby Isaac   . label - The label specifying the points
1813c58f1c22SToby Isaac   - labelValue - The label stratum specifying the points
1814c58f1c22SToby Isaac 
1815c58f1c22SToby Isaac   Output Parameter:
1816c58f1c22SToby Isaac   . gsection - The PetscSection for the global field layout
1817c58f1c22SToby Isaac 
1818c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
1819c58f1c22SToby Isaac 
1820c58f1c22SToby Isaac   Level: developer
1821c58f1c22SToby Isaac 
1822c58f1c22SToby Isaac .seealso: PetscSectionCreate()
1823c58f1c22SToby Isaac @*/
1824c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
1825c58f1c22SToby Isaac {
1826c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
1827c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
1828c58f1c22SToby Isaac   PetscErrorCode ierr;
1829c58f1c22SToby Isaac 
1830c58f1c22SToby Isaac   PetscFunctionBegin;
1831d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1832d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1833d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
1834c58f1c22SToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
1835c58f1c22SToby Isaac   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1836c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
1837c58f1c22SToby Isaac   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
1838c58f1c22SToby Isaac   if (nroots >= 0) {
1839c58f1c22SToby Isaac     if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
1840c58f1c22SToby Isaac     ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr);
1841c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1842c58f1c22SToby Isaac       ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr);
1843c58f1c22SToby Isaac     } else {
1844c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
1845c58f1c22SToby Isaac     }
1846c58f1c22SToby Isaac   }
1847c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
1848c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
1849c58f1c22SToby Isaac     PetscInt value;
1850c58f1c22SToby Isaac 
1851c58f1c22SToby Isaac     ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr);
1852c58f1c22SToby Isaac     if (value != labelValue) continue;
1853c58f1c22SToby Isaac     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1854c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr);
1855c58f1c22SToby Isaac     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1856c58f1c22SToby Isaac     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);}
1857c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
1858c58f1c22SToby Isaac   }
1859c58f1c22SToby Isaac   ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr);
1860c58f1c22SToby Isaac   if (nroots >= 0) {
1861ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1862ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1863c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1864c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
1865c58f1c22SToby Isaac     }
1866c58f1c22SToby Isaac   }
1867c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
1868c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1869c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
1870c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
1871c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
1872c58f1c22SToby Isaac   }
187355b25c41SPierre Jolivet   ierr       = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRMPI(ierr);
1874c58f1c22SToby Isaac   globalOff -= off;
1875c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1876c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
1877c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
1878c58f1c22SToby Isaac   }
1879c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
1880c58f1c22SToby Isaac   if (nroots >= 0) {
1881ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1882ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1883c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1884c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
1885c58f1c22SToby Isaac     }
1886c58f1c22SToby Isaac   }
1887c58f1c22SToby Isaac   if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);}
1888c58f1c22SToby Isaac   ierr = PetscFree(neg);CHKERRQ(ierr);
1889c58f1c22SToby Isaac   PetscFunctionReturn(0);
1890c58f1c22SToby Isaac }
1891c58f1c22SToby Isaac 
18925fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
18935fdea053SToby Isaac {
18945fdea053SToby Isaac   DMLabel           label;
18955fdea053SToby Isaac   PetscCopyMode     *modes;
18965fdea053SToby Isaac   PetscInt          *sizes;
18975fdea053SToby Isaac   const PetscInt    ***perms;
18985fdea053SToby Isaac   const PetscScalar ***rots;
18995fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
19005fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
19015fdea053SToby Isaac } PetscSectionSym_Label;
19025fdea053SToby Isaac 
19035fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
19045fdea053SToby Isaac {
19055fdea053SToby Isaac   PetscInt              i, j;
19065fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
19075fdea053SToby Isaac   PetscErrorCode        ierr;
19085fdea053SToby Isaac 
19095fdea053SToby Isaac   PetscFunctionBegin;
19105fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
19115fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
19125fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
19135fdea053SToby Isaac         if (sl->perms[i]) {ierr = PetscFree(sl->perms[i][j]);CHKERRQ(ierr);}
19145fdea053SToby Isaac         if (sl->rots[i]) {ierr = PetscFree(sl->rots[i][j]);CHKERRQ(ierr);}
19155fdea053SToby Isaac       }
19165fdea053SToby Isaac       if (sl->perms[i]) {
19175fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
19185fdea053SToby Isaac 
19195fdea053SToby Isaac         ierr = PetscFree(perms);CHKERRQ(ierr);
19205fdea053SToby Isaac       }
19215fdea053SToby Isaac       if (sl->rots[i]) {
19225fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
19235fdea053SToby Isaac 
19245fdea053SToby Isaac         ierr = PetscFree(rots);CHKERRQ(ierr);
19255fdea053SToby Isaac       }
19265fdea053SToby Isaac     }
19275fdea053SToby Isaac   }
19285fdea053SToby Isaac   ierr = PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients);CHKERRQ(ierr);
19295fdea053SToby Isaac   ierr = DMLabelDestroy(&sl->label);CHKERRQ(ierr);
19305fdea053SToby Isaac   sl->numStrata = 0;
19315fdea053SToby Isaac   PetscFunctionReturn(0);
19325fdea053SToby Isaac }
19335fdea053SToby Isaac 
19345fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
19355fdea053SToby Isaac {
19365fdea053SToby Isaac   PetscErrorCode ierr;
19375fdea053SToby Isaac 
19385fdea053SToby Isaac   PetscFunctionBegin;
19395fdea053SToby Isaac   ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);
19405fdea053SToby Isaac   ierr = PetscFree(sym->data);CHKERRQ(ierr);
19415fdea053SToby Isaac   PetscFunctionReturn(0);
19425fdea053SToby Isaac }
19435fdea053SToby Isaac 
19445fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
19455fdea053SToby Isaac {
19465fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
19475fdea053SToby Isaac   PetscBool             isAscii;
19485fdea053SToby Isaac   DMLabel               label = sl->label;
1949d67d17b1SMatthew G. Knepley   const char           *name;
19505fdea053SToby Isaac   PetscErrorCode        ierr;
19515fdea053SToby Isaac 
19525fdea053SToby Isaac   PetscFunctionBegin;
19535fdea053SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii);CHKERRQ(ierr);
19545fdea053SToby Isaac   if (isAscii) {
19555fdea053SToby Isaac     PetscInt          i, j, k;
19565fdea053SToby Isaac     PetscViewerFormat format;
19575fdea053SToby Isaac 
19585fdea053SToby Isaac     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
19595fdea053SToby Isaac     if (label) {
19605fdea053SToby Isaac       ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
19615fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
19625fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19635fdea053SToby Isaac         ierr = DMLabelView(label, viewer);CHKERRQ(ierr);
19645fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19655fdea053SToby Isaac       } else {
1966d67d17b1SMatthew G. Knepley         ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
1967d67d17b1SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name);CHKERRQ(ierr);
19685fdea053SToby Isaac       }
19695fdea053SToby Isaac     } else {
19705fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "No label given\n");CHKERRQ(ierr);
19715fdea053SToby Isaac     }
19725fdea053SToby Isaac     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19735fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
19745fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
19755fdea053SToby Isaac 
19765fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
19775fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point): no symmetries\n", value, sl->sizes[i]);CHKERRQ(ierr);
19785fdea053SToby Isaac       } else {
19795fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point):\n", value, sl->sizes[i]);CHKERRQ(ierr);
19805fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19815fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Orientation range: [%D, %D)\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]);CHKERRQ(ierr);
19825fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
19835fdea053SToby Isaac           ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19845fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
19855fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
19865fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D: identity\n",j);CHKERRQ(ierr);
19875fdea053SToby Isaac             } else {
19885fdea053SToby Isaac               PetscInt tab;
19895fdea053SToby Isaac 
19905fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D:\n",j);CHKERRQ(ierr);
19915fdea053SToby Isaac               ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
19925fdea053SToby Isaac               ierr = PetscViewerASCIIGetTab(viewer,&tab);CHKERRQ(ierr);
19935fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
19945fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Permutation:");CHKERRQ(ierr);
19955fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
19965fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %D",sl->perms[i][j][k]);CHKERRQ(ierr);}
19975fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
19985fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
19995fdea053SToby Isaac               }
20005fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
20015fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Rotations:  ");CHKERRQ(ierr);
20025fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
20035fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
20045fdea053SToby 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);}
20055fdea053SToby Isaac #else
20065fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f",sl->rots[i][j][k]);CHKERRQ(ierr);}
20075fdea053SToby Isaac #endif
20085fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
20095fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
20105fdea053SToby Isaac               }
20115fdea053SToby Isaac               ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20125fdea053SToby Isaac             }
20135fdea053SToby Isaac           }
20145fdea053SToby Isaac           ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20155fdea053SToby Isaac         }
20165fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20175fdea053SToby Isaac       }
20185fdea053SToby Isaac     }
20195fdea053SToby Isaac     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20205fdea053SToby Isaac   }
20215fdea053SToby Isaac   PetscFunctionReturn(0);
20225fdea053SToby Isaac }
20235fdea053SToby Isaac 
20245fdea053SToby Isaac /*@
20255fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
20265fdea053SToby Isaac 
20275fdea053SToby Isaac   Logically collective on sym
20285fdea053SToby Isaac 
20295fdea053SToby Isaac   Input parameters:
20305fdea053SToby Isaac + sym - the section symmetries
20315fdea053SToby Isaac - label - the DMLabel describing the types of points
20325fdea053SToby Isaac 
20335fdea053SToby Isaac   Level: developer:
20345fdea053SToby Isaac 
20355fdea053SToby Isaac .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreateLabel(), PetscSectionGetPointSyms()
20365fdea053SToby Isaac @*/
20375fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
20385fdea053SToby Isaac {
20395fdea053SToby Isaac   PetscSectionSym_Label *sl;
20405fdea053SToby Isaac   PetscErrorCode        ierr;
20415fdea053SToby Isaac 
20425fdea053SToby Isaac   PetscFunctionBegin;
20435fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
20445fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
20455fdea053SToby Isaac   if (sl->label && sl->label != label) {ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);}
20465fdea053SToby Isaac   if (label) {
20475fdea053SToby Isaac     sl->label = label;
2048d67d17b1SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
20495fdea053SToby Isaac     ierr = DMLabelGetNumValues(label,&sl->numStrata);CHKERRQ(ierr);
20501a834cf9SToby 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);
20511a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode));CHKERRQ(ierr);
20521a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt));CHKERRQ(ierr);
20531a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **));CHKERRQ(ierr);
20541a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **));CHKERRQ(ierr);
20551a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2]));CHKERRQ(ierr);
20565fdea053SToby Isaac   }
20575fdea053SToby Isaac   PetscFunctionReturn(0);
20585fdea053SToby Isaac }
20595fdea053SToby Isaac 
20605fdea053SToby Isaac /*@C
20615fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
20625fdea053SToby Isaac 
20635b5e7992SMatthew G. Knepley   Logically collective on sym
20645fdea053SToby Isaac 
20655fdea053SToby Isaac   InputParameters:
20665b5e7992SMatthew G. Knepley + sym       - the section symmetries
20675fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
20685fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
20695fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
20705fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
20715fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
20725fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2073a2b725a8SWilliam 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
20745fdea053SToby Isaac 
20755fdea053SToby Isaac   Level: developer
20765fdea053SToby Isaac 
20775fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
20785fdea053SToby Isaac @*/
20795fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
20805fdea053SToby Isaac {
20815fdea053SToby Isaac   PetscSectionSym_Label *sl;
2082d67d17b1SMatthew G. Knepley   const char            *name;
2083d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
20845fdea053SToby Isaac   PetscErrorCode         ierr;
20855fdea053SToby Isaac 
20865fdea053SToby Isaac   PetscFunctionBegin;
20875fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
20885fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
20895fdea053SToby Isaac   if (!sl->label) SETERRQ(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_WRONGSTATE,"No label set yet");
20905fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
20915fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
20925fdea053SToby Isaac 
20935fdea053SToby Isaac     if (stratum == value) break;
20945fdea053SToby Isaac   }
2095d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
2096d67d17b1SMatthew G. Knepley   if (i > sl->numStrata) SETERRQ2(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_OUTOFRANGE,"Stratum %D not found in label %s\n",stratum,name);
20975fdea053SToby Isaac   sl->sizes[i] = size;
20985fdea053SToby Isaac   sl->modes[i] = mode;
20995fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
21005fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
21015fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
21025fdea053SToby Isaac     if (perms) {
21035fdea053SToby Isaac       PetscInt    **ownPerms;
21045fdea053SToby Isaac 
21055fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownPerms);CHKERRQ(ierr);
21065fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
21075fdea053SToby Isaac         if (perms[j]) {
21085fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownPerms[j]);CHKERRQ(ierr);
21095fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
21105fdea053SToby Isaac         }
21115fdea053SToby Isaac       }
21125fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
21135fdea053SToby Isaac     }
21145fdea053SToby Isaac     if (rots) {
21155fdea053SToby Isaac       PetscScalar **ownRots;
21165fdea053SToby Isaac 
21175fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownRots);CHKERRQ(ierr);
21185fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
21195fdea053SToby Isaac         if (rots[j]) {
21205fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownRots[j]);CHKERRQ(ierr);
21215fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
21225fdea053SToby Isaac         }
21235fdea053SToby Isaac       }
21245fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
21255fdea053SToby Isaac     }
21265fdea053SToby Isaac   } else {
21275fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
21285fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
21295fdea053SToby Isaac   }
21305fdea053SToby Isaac   PetscFunctionReturn(0);
21315fdea053SToby Isaac }
21325fdea053SToby Isaac 
21335fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
21345fdea053SToby Isaac {
21355fdea053SToby Isaac   PetscInt              i, j, numStrata;
21365fdea053SToby Isaac   PetscSectionSym_Label *sl;
21375fdea053SToby Isaac   DMLabel               label;
21385fdea053SToby Isaac   PetscErrorCode        ierr;
21395fdea053SToby Isaac 
21405fdea053SToby Isaac   PetscFunctionBegin;
21415fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
21425fdea053SToby Isaac   numStrata = sl->numStrata;
21435fdea053SToby Isaac   label     = sl->label;
21445fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
21455fdea053SToby Isaac     PetscInt point = points[2*i];
21465fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
21475fdea053SToby Isaac 
21485fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
21495fdea053SToby Isaac       if (label->validIS[j]) {
21505fdea053SToby Isaac         PetscInt k;
21515fdea053SToby Isaac 
21525fdea053SToby Isaac         ierr = ISLocate(label->points[j],point,&k);CHKERRQ(ierr);
21535fdea053SToby Isaac         if (k >= 0) break;
21545fdea053SToby Isaac       } else {
21555fdea053SToby Isaac         PetscBool has;
21565fdea053SToby Isaac 
2157b9907514SLisandro Dalcin         ierr = PetscHSetIHas(label->ht[j], point, &has);CHKERRQ(ierr);
21585fdea053SToby Isaac         if (has) break;
21595fdea053SToby Isaac       }
21605fdea053SToby Isaac     }
21615fdea053SToby 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);
21625fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
21635fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
21645fdea053SToby Isaac   }
21655fdea053SToby Isaac   PetscFunctionReturn(0);
21665fdea053SToby Isaac }
21675fdea053SToby Isaac 
21685fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
21695fdea053SToby Isaac {
21705fdea053SToby Isaac   PetscSectionSym_Label *sl;
21715fdea053SToby Isaac   PetscErrorCode        ierr;
21725fdea053SToby Isaac 
21735fdea053SToby Isaac   PetscFunctionBegin;
21745fdea053SToby Isaac   ierr = PetscNewLog(sym,&sl);CHKERRQ(ierr);
21755fdea053SToby Isaac   sym->ops->getpoints = PetscSectionSymGetPoints_Label;
21765fdea053SToby Isaac   sym->ops->view      = PetscSectionSymView_Label;
21775fdea053SToby Isaac   sym->ops->destroy   = PetscSectionSymDestroy_Label;
21785fdea053SToby Isaac   sym->data           = (void *) sl;
21795fdea053SToby Isaac   PetscFunctionReturn(0);
21805fdea053SToby Isaac }
21815fdea053SToby Isaac 
21825fdea053SToby Isaac /*@
21835fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
21845fdea053SToby Isaac 
21855fdea053SToby Isaac   Collective
21865fdea053SToby Isaac 
21875fdea053SToby Isaac   Input Parameters:
21885fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
21895fdea053SToby Isaac - label - the label defining the strata
21905fdea053SToby Isaac 
21915fdea053SToby Isaac   Output Parameters:
21925fdea053SToby Isaac . sym - the section symmetries
21935fdea053SToby Isaac 
21945fdea053SToby Isaac   Level: developer
21955fdea053SToby Isaac 
21965fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms()
21975fdea053SToby Isaac @*/
21985fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
21995fdea053SToby Isaac {
22005fdea053SToby Isaac   PetscErrorCode        ierr;
22015fdea053SToby Isaac 
22025fdea053SToby Isaac   PetscFunctionBegin;
22035fdea053SToby Isaac   ierr = DMInitializePackage();CHKERRQ(ierr);
22045fdea053SToby Isaac   ierr = PetscSectionSymCreate(comm,sym);CHKERRQ(ierr);
22055fdea053SToby Isaac   ierr = PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL);CHKERRQ(ierr);
22065fdea053SToby Isaac   ierr = PetscSectionSymLabelSetLabel(*sym,label);CHKERRQ(ierr);
22075fdea053SToby Isaac   PetscFunctionReturn(0);
22085fdea053SToby Isaac }
2209