xref: /petsc/src/dm/label/dmlabel.c (revision 534a8f05a7a8aff70dd8cfd53d9cd834400a8dbf)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h>   /*I      "petscdmlabel.h"   I*/
3c58f1c22SToby Isaac #include <petsc/private/isimpl.h>        /*I      "petscis.h"        I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5c58f1c22SToby Isaac 
6c58f1c22SToby Isaac /*@C
7c58f1c22SToby Isaac   DMLabelCreate - Create a DMLabel object, which is a multimap
8c58f1c22SToby Isaac 
95b5e7992SMatthew G. Knepley   Collective
105b5e7992SMatthew G. Knepley 
11d67d17b1SMatthew G. Knepley   Input parameters:
12d67d17b1SMatthew G. Knepley + comm - The communicator, usually PETSC_COMM_SELF
13d67d17b1SMatthew G. Knepley - name - The label name
14c58f1c22SToby Isaac 
15c58f1c22SToby Isaac   Output parameter:
16c58f1c22SToby Isaac . label - The DMLabel
17c58f1c22SToby Isaac 
18c58f1c22SToby Isaac   Level: beginner
19c58f1c22SToby Isaac 
20c58f1c22SToby Isaac .seealso: DMLabelDestroy()
21c58f1c22SToby Isaac @*/
22d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
23c58f1c22SToby Isaac {
24c58f1c22SToby Isaac   PetscErrorCode ierr;
25c58f1c22SToby Isaac 
26c58f1c22SToby Isaac   PetscFunctionBegin;
27d67d17b1SMatthew G. Knepley   PetscValidPointer(label,2);
28d67d17b1SMatthew G. Knepley   ierr = DMInitializePackage();CHKERRQ(ierr);
29c58f1c22SToby Isaac 
30d67d17b1SMatthew G. Knepley   ierr = PetscHeaderCreate(*label,DMLABEL_CLASSID,"DMLabel","DMLabel","DM",comm,DMLabelDestroy,DMLabelView);CHKERRQ(ierr);
31d67d17b1SMatthew G. Knepley 
32c58f1c22SToby Isaac   (*label)->numStrata      = 0;
335aa44df4SToby Isaac   (*label)->defaultValue   = -1;
34c58f1c22SToby Isaac   (*label)->stratumValues  = NULL;
35ad8374ffSToby Isaac   (*label)->validIS        = NULL;
36c58f1c22SToby Isaac   (*label)->stratumSizes   = NULL;
37c58f1c22SToby Isaac   (*label)->points         = NULL;
38c58f1c22SToby Isaac   (*label)->ht             = NULL;
39c58f1c22SToby Isaac   (*label)->pStart         = -1;
40c58f1c22SToby Isaac   (*label)->pEnd           = -1;
41c58f1c22SToby Isaac   (*label)->bt             = NULL;
42b9907514SLisandro Dalcin   ierr = PetscHMapICreate(&(*label)->hmap);CHKERRQ(ierr);
43d67d17b1SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *label, name);CHKERRQ(ierr);
44c58f1c22SToby Isaac   PetscFunctionReturn(0);
45c58f1c22SToby Isaac }
46c58f1c22SToby Isaac 
47c58f1c22SToby Isaac /*
48c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
49c58f1c22SToby Isaac 
505b5e7992SMatthew G. Knepley   Not collective
515b5e7992SMatthew G. Knepley 
52c58f1c22SToby Isaac   Input parameter:
53c58f1c22SToby Isaac + label - The DMLabel
54c58f1c22SToby Isaac - v - The stratum value
55c58f1c22SToby Isaac 
56c58f1c22SToby Isaac   Output parameter:
57c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
58c58f1c22SToby Isaac 
59c58f1c22SToby Isaac   Level: developer
60c58f1c22SToby Isaac 
61c58f1c22SToby Isaac .seealso: DMLabelCreate()
62c58f1c22SToby Isaac */
63c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
64c58f1c22SToby Isaac {
65277ea44aSLisandro Dalcin   IS             is;
66b9907514SLisandro Dalcin   PetscInt       off = 0, *pointArray, p;
67c58f1c22SToby Isaac   PetscErrorCode ierr;
68c58f1c22SToby Isaac 
69b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
70c58f1c22SToby Isaac   PetscFunctionBegin;
710c3c4a36SLisandro 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);
72e8f14785SLisandro Dalcin   ierr = PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]);CHKERRQ(ierr);
73ad8374ffSToby Isaac   ierr = PetscMalloc1(label->stratumSizes[v], &pointArray);CHKERRQ(ierr);
74e8f14785SLisandro Dalcin   ierr = PetscHSetIGetElems(label->ht[v], &off, pointArray);CHKERRQ(ierr);
75b9907514SLisandro Dalcin   ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr);
76ad8374ffSToby Isaac   ierr = PetscSortInt(label->stratumSizes[v], pointArray);CHKERRQ(ierr);
77c58f1c22SToby Isaac   if (label->bt) {
78c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
79ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
80c58f1c22SToby 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);
81c58f1c22SToby Isaac       ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr);
82c58f1c22SToby Isaac     }
83c58f1c22SToby Isaac   }
84277ea44aSLisandro Dalcin   ierr = ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is);CHKERRQ(ierr);
85277ea44aSLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) is, "indices");CHKERRQ(ierr);
86277ea44aSLisandro Dalcin   label->points[v]  = is;
87ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
88d67d17b1SMatthew G. Knepley   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
89c58f1c22SToby Isaac   PetscFunctionReturn(0);
90c58f1c22SToby Isaac }
91c58f1c22SToby Isaac 
92c58f1c22SToby Isaac /*
93c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
94c58f1c22SToby Isaac 
955b5e7992SMatthew G. Knepley   Not collective
965b5e7992SMatthew G. Knepley 
97c58f1c22SToby Isaac   Input parameter:
98c58f1c22SToby Isaac . label - The DMLabel
99c58f1c22SToby Isaac 
100c58f1c22SToby Isaac   Output parameter:
101c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
102c58f1c22SToby Isaac 
103c58f1c22SToby Isaac   Level: developer
104c58f1c22SToby Isaac 
105c58f1c22SToby Isaac .seealso: DMLabelCreate()
106c58f1c22SToby Isaac */
107c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
108c58f1c22SToby Isaac {
109c58f1c22SToby Isaac   PetscInt       v;
110c58f1c22SToby Isaac   PetscErrorCode ierr;
111c58f1c22SToby Isaac 
112c58f1c22SToby Isaac   PetscFunctionBegin;
113c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; v++){
114c58f1c22SToby Isaac     ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
115c58f1c22SToby Isaac   }
116c58f1c22SToby Isaac   PetscFunctionReturn(0);
117c58f1c22SToby Isaac }
118c58f1c22SToby Isaac 
119c58f1c22SToby Isaac /*
120c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
121c58f1c22SToby Isaac 
1225b5e7992SMatthew G. Knepley   Not collective
1235b5e7992SMatthew G. Knepley 
124c58f1c22SToby Isaac   Input parameter:
125c58f1c22SToby Isaac + label - The DMLabel
126c58f1c22SToby Isaac - v - The stratum value
127c58f1c22SToby Isaac 
128c58f1c22SToby Isaac   Output parameter:
129c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
130c58f1c22SToby Isaac 
131c58f1c22SToby Isaac   Level: developer
132c58f1c22SToby Isaac 
133c58f1c22SToby Isaac .seealso: DMLabelCreate()
134c58f1c22SToby Isaac */
135c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
136c58f1c22SToby Isaac {
137c58f1c22SToby Isaac   PetscInt       p;
138ad8374ffSToby Isaac   const PetscInt *points;
139c58f1c22SToby Isaac   PetscErrorCode ierr;
140c58f1c22SToby Isaac 
141b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
142c58f1c22SToby Isaac   PetscFunctionBegin;
1430c3c4a36SLisandro 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);
144ad8374ffSToby Isaac   if (label->points[v]) {
145ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
146e8f14785SLisandro Dalcin     for (p = 0; p < label->stratumSizes[v]; ++p) {
147e8f14785SLisandro Dalcin       ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);
148e8f14785SLisandro Dalcin     }
149ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr);
150ad8374ffSToby Isaac     ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr);
151ad8374ffSToby Isaac   }
152ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
153c58f1c22SToby Isaac   PetscFunctionReturn(0);
154c58f1c22SToby Isaac }
155c58f1c22SToby Isaac 
156b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
157b9907514SLisandro Dalcin #define DMLABEL_LOOKUP_THRESHOLD 16
158b9907514SLisandro Dalcin #endif
159b9907514SLisandro Dalcin 
1600c3c4a36SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
1610c3c4a36SLisandro Dalcin {
1620c3c4a36SLisandro Dalcin   PetscInt       v;
163b9907514SLisandro Dalcin   PetscErrorCode ierr;
1640e79e033SBarry Smith 
1650c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1660e79e033SBarry Smith   *index = -1;
167b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
168b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
169b9907514SLisandro Dalcin       if (label->stratumValues[v] == value) {*index = v; break;}
170b9907514SLisandro Dalcin   } else {
171b9907514SLisandro Dalcin     ierr = PetscHMapIGet(label->hmap, value, index);CHKERRQ(ierr);
1720e79e033SBarry Smith   }
17390e9b2aeSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
17490e9b2aeSLisandro Dalcin   { /* Check strata hash map consistency */
17590e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
17690e9b2aeSLisandro Dalcin     ierr = PetscHMapIGetSize(label->hmap, &len);CHKERRQ(ierr);
17790e9b2aeSLisandro Dalcin     if (len != label->numStrata) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
17890e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
17990e9b2aeSLisandro Dalcin       ierr = PetscHMapIGet(label->hmap, value, &loc);CHKERRQ(ierr);
18090e9b2aeSLisandro Dalcin     } else {
18190e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
18290e9b2aeSLisandro Dalcin         if (label->stratumValues[v] == value) {loc = v; break;}
18390e9b2aeSLisandro Dalcin     }
18490e9b2aeSLisandro Dalcin     if (loc != *index) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
18590e9b2aeSLisandro Dalcin   }
18690e9b2aeSLisandro Dalcin #endif
1870c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
1880c3c4a36SLisandro Dalcin }
1890c3c4a36SLisandro Dalcin 
190b9907514SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
191c58f1c22SToby Isaac {
192b9907514SLisandro Dalcin   PetscInt       v;
193b9907514SLisandro Dalcin   PetscInt      *tmpV;
194b9907514SLisandro Dalcin   PetscInt      *tmpS;
195b9907514SLisandro Dalcin   PetscHSetI    *tmpH, ht;
196b9907514SLisandro Dalcin   IS            *tmpP, is;
197c58f1c22SToby Isaac   PetscBool     *tmpB;
198b9907514SLisandro Dalcin   PetscHMapI     hmap = label->hmap;
199c58f1c22SToby Isaac   PetscErrorCode ierr;
200c58f1c22SToby Isaac 
201c58f1c22SToby Isaac   PetscFunctionBegin;
202b9907514SLisandro Dalcin   v    = label->numStrata;
203b9907514SLisandro Dalcin   tmpV = label->stratumValues;
204b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
205b9907514SLisandro Dalcin   tmpH = label->ht;
206b9907514SLisandro Dalcin   tmpP = label->points;
207b9907514SLisandro Dalcin   tmpB = label->validIS;
2088e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2098e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2108e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2118e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2128e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2138e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2148e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpV), &tmpV);CHKERRQ(ierr);
2158e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpS), &tmpS);CHKERRQ(ierr);
2168e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpH), &tmpH);CHKERRQ(ierr);
2178e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpP), &tmpP);CHKERRQ(ierr);
2188e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpB), &tmpB);CHKERRQ(ierr);
219580bdb30SBarry Smith     ierr = PetscArraycpy(tmpV, oldV, v);CHKERRQ(ierr);
220580bdb30SBarry Smith     ierr = PetscArraycpy(tmpS, oldS, v);CHKERRQ(ierr);
221580bdb30SBarry Smith     ierr = PetscArraycpy(tmpH, oldH, v);CHKERRQ(ierr);
222580bdb30SBarry Smith     ierr = PetscArraycpy(tmpP, oldP, v);CHKERRQ(ierr);
223580bdb30SBarry Smith     ierr = PetscArraycpy(tmpB, oldB, v);CHKERRQ(ierr);
2248e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldV);CHKERRQ(ierr);
2258e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldS);CHKERRQ(ierr);
2268e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldH);CHKERRQ(ierr);
2278e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldP);CHKERRQ(ierr);
2288e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldB);CHKERRQ(ierr);
2298e1f8cf0SLisandro Dalcin   }
230b9907514SLisandro Dalcin   label->numStrata     = v+1;
231c58f1c22SToby Isaac   label->stratumValues = tmpV;
232c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
233c58f1c22SToby Isaac   label->ht            = tmpH;
234c58f1c22SToby Isaac   label->points        = tmpP;
235ad8374ffSToby Isaac   label->validIS       = tmpB;
236b9907514SLisandro Dalcin   ierr = PetscHSetICreate(&ht);CHKERRQ(ierr);
237b9907514SLisandro Dalcin   ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr);
238b9907514SLisandro Dalcin   ierr = PetscHMapISet(hmap, value, v);CHKERRQ(ierr);
239b9907514SLisandro Dalcin   tmpV[v] = value;
240b9907514SLisandro Dalcin   tmpS[v] = 0;
241b9907514SLisandro Dalcin   tmpH[v] = ht;
242b9907514SLisandro Dalcin   tmpP[v] = is;
243b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
244277ea44aSLisandro Dalcin   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
2450c3c4a36SLisandro Dalcin   *index = v;
2460c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2470c3c4a36SLisandro Dalcin }
2480c3c4a36SLisandro Dalcin 
249b9907514SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
250b9907514SLisandro Dalcin {
251b9907514SLisandro Dalcin   PetscErrorCode ierr;
252b9907514SLisandro Dalcin   PetscFunctionBegin;
253b9907514SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, index);CHKERRQ(ierr);
254b9907514SLisandro Dalcin   if (*index < 0) {ierr = DMLabelNewStratum(label, value, index);CHKERRQ(ierr);}
255b9907514SLisandro Dalcin   PetscFunctionReturn(0);
256b9907514SLisandro Dalcin }
257b9907514SLisandro Dalcin 
258b9907514SLisandro Dalcin /*@
259b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
260b9907514SLisandro Dalcin 
261b9907514SLisandro Dalcin   Input Parameter:
262b9907514SLisandro Dalcin + label - The DMLabel
263b9907514SLisandro Dalcin - value - The stratum value
264b9907514SLisandro Dalcin 
265b9907514SLisandro Dalcin   Level: beginner
266b9907514SLisandro Dalcin 
267b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
268b9907514SLisandro Dalcin @*/
2690c3c4a36SLisandro Dalcin PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
2700c3c4a36SLisandro Dalcin {
2710c3c4a36SLisandro Dalcin   PetscInt       v;
2720c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
2730c3c4a36SLisandro Dalcin 
2740c3c4a36SLisandro Dalcin   PetscFunctionBegin;
275d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
276b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
277b9907514SLisandro Dalcin   PetscFunctionReturn(0);
278b9907514SLisandro Dalcin }
279b9907514SLisandro Dalcin 
280b9907514SLisandro Dalcin /*@
281b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
282b9907514SLisandro Dalcin 
2835b5e7992SMatthew G. Knepley   Not collective
2845b5e7992SMatthew G. Knepley 
285b9907514SLisandro Dalcin   Input Parameter:
286b9907514SLisandro Dalcin + label - The DMLabel
287b9907514SLisandro Dalcin . numStrata - The number of stratum values
288b9907514SLisandro Dalcin - stratumValues - The stratum values
289b9907514SLisandro Dalcin 
290b9907514SLisandro Dalcin   Level: beginner
291b9907514SLisandro Dalcin 
292b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
293b9907514SLisandro Dalcin @*/
294b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
295b9907514SLisandro Dalcin {
296b9907514SLisandro Dalcin   PetscInt       *values, v;
297b9907514SLisandro Dalcin   PetscErrorCode ierr;
298b9907514SLisandro Dalcin 
299b9907514SLisandro Dalcin   PetscFunctionBegin;
300b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
301b9907514SLisandro Dalcin   if (numStrata) PetscValidIntPointer(stratumValues, 3);
302b9907514SLisandro Dalcin   ierr = PetscMalloc1(numStrata, &values);CHKERRQ(ierr);
303580bdb30SBarry Smith   ierr = PetscArraycpy(values, stratumValues, numStrata);CHKERRQ(ierr);
304b9907514SLisandro Dalcin   ierr = PetscSortRemoveDupsInt(&numStrata, values);CHKERRQ(ierr);
305b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
306b9907514SLisandro Dalcin     PetscInt   *tmpV;
307b9907514SLisandro Dalcin     PetscInt   *tmpS;
308b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
309b9907514SLisandro Dalcin     IS         *tmpP, is;
310b9907514SLisandro Dalcin     PetscBool  *tmpB;
311b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
312b9907514SLisandro Dalcin 
313b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpV);CHKERRQ(ierr);
314b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpS);CHKERRQ(ierr);
315b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpH);CHKERRQ(ierr);
316b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpP);CHKERRQ(ierr);
317b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpB);CHKERRQ(ierr);
318b9907514SLisandro Dalcin     label->numStrata     = numStrata;
319b9907514SLisandro Dalcin     label->stratumValues = tmpV;
320b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
321b9907514SLisandro Dalcin     label->ht            = tmpH;
322b9907514SLisandro Dalcin     label->points        = tmpP;
323b9907514SLisandro Dalcin     label->validIS       = tmpB;
324b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
325b9907514SLisandro Dalcin       ierr = PetscHSetICreate(&ht);CHKERRQ(ierr);
326b9907514SLisandro Dalcin       ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr);
327b9907514SLisandro Dalcin       ierr = PetscHMapISet(hmap, values[v], v);CHKERRQ(ierr);
328b9907514SLisandro Dalcin       tmpV[v] = values[v];
329b9907514SLisandro Dalcin       tmpS[v] = 0;
330b9907514SLisandro Dalcin       tmpH[v] = ht;
331b9907514SLisandro Dalcin       tmpP[v] = is;
332b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
333b9907514SLisandro Dalcin     }
334277ea44aSLisandro Dalcin     ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
335b9907514SLisandro Dalcin   } else {
336b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
337b9907514SLisandro Dalcin       ierr = DMLabelAddStratum(label, values[v]);CHKERRQ(ierr);
338b9907514SLisandro Dalcin     }
339b9907514SLisandro Dalcin   }
340b9907514SLisandro Dalcin   ierr = PetscFree(values);CHKERRQ(ierr);
341b9907514SLisandro Dalcin   PetscFunctionReturn(0);
342b9907514SLisandro Dalcin }
343b9907514SLisandro Dalcin 
344b9907514SLisandro Dalcin /*@
345b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
346b9907514SLisandro Dalcin 
3475b5e7992SMatthew G. Knepley   Not collective
3485b5e7992SMatthew G. Knepley 
349b9907514SLisandro Dalcin   Input Parameter:
350b9907514SLisandro Dalcin + label - The DMLabel
351b9907514SLisandro Dalcin - valueIS - Index set with stratum values
352b9907514SLisandro Dalcin 
353b9907514SLisandro Dalcin   Level: beginner
354b9907514SLisandro Dalcin 
355b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
356b9907514SLisandro Dalcin @*/
357b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
358b9907514SLisandro Dalcin {
359b9907514SLisandro Dalcin   PetscInt       numStrata;
360b9907514SLisandro Dalcin   const PetscInt *stratumValues;
361b9907514SLisandro Dalcin   PetscErrorCode ierr;
362b9907514SLisandro Dalcin 
363b9907514SLisandro Dalcin   PetscFunctionBegin;
364b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
365b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
366b9907514SLisandro Dalcin   ierr = ISGetLocalSize(valueIS, &numStrata);CHKERRQ(ierr);
367b9907514SLisandro Dalcin   ierr = ISGetIndices(valueIS, &stratumValues);CHKERRQ(ierr);
368b9907514SLisandro Dalcin   ierr = DMLabelAddStrata(label, numStrata, stratumValues);CHKERRQ(ierr);
369c58f1c22SToby Isaac   PetscFunctionReturn(0);
370c58f1c22SToby Isaac }
371c58f1c22SToby Isaac 
372c58f1c22SToby Isaac static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer)
373c58f1c22SToby Isaac {
374c58f1c22SToby Isaac   PetscInt       v;
375c58f1c22SToby Isaac   PetscMPIInt    rank;
376c58f1c22SToby Isaac   PetscErrorCode ierr;
377c58f1c22SToby Isaac 
378c58f1c22SToby Isaac   PetscFunctionBegin;
379c58f1c22SToby Isaac   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr);
380c58f1c22SToby Isaac   ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
381c58f1c22SToby Isaac   if (label) {
382d67d17b1SMatthew G. Knepley     const char *name;
383d67d17b1SMatthew G. Knepley 
384d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
385d67d17b1SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name);CHKERRQ(ierr);
386c58f1c22SToby Isaac     if (label->bt) {ierr = PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%D, %D)\n", label->pStart, label->pEnd);CHKERRQ(ierr);}
387c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
388c58f1c22SToby Isaac       const PetscInt value = label->stratumValues[v];
389ad8374ffSToby Isaac       const PetscInt *points;
390c58f1c22SToby Isaac       PetscInt       p;
391c58f1c22SToby Isaac 
392ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
393c58f1c22SToby Isaac       for (p = 0; p < label->stratumSizes[v]; ++p) {
394ad8374ffSToby Isaac         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D (%D)\n", rank, points[p], value);CHKERRQ(ierr);
395c58f1c22SToby Isaac       }
396ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr);
397c58f1c22SToby Isaac     }
398c58f1c22SToby Isaac   }
399c58f1c22SToby Isaac   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
400c58f1c22SToby Isaac   ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
401c58f1c22SToby Isaac   PetscFunctionReturn(0);
402c58f1c22SToby Isaac }
403c58f1c22SToby Isaac 
404c58f1c22SToby Isaac /*@C
405c58f1c22SToby Isaac   DMLabelView - View the label
406c58f1c22SToby Isaac 
4075b5e7992SMatthew G. Knepley   Collective on viewer
4085b5e7992SMatthew G. Knepley 
409c58f1c22SToby Isaac   Input Parameters:
410c58f1c22SToby Isaac + label - The DMLabel
411c58f1c22SToby Isaac - viewer - The PetscViewer
412c58f1c22SToby Isaac 
413c58f1c22SToby Isaac   Level: intermediate
414c58f1c22SToby Isaac 
415c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelDestroy()
416c58f1c22SToby Isaac @*/
417c58f1c22SToby Isaac PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
418c58f1c22SToby Isaac {
419c58f1c22SToby Isaac   PetscBool      iascii;
420c58f1c22SToby Isaac   PetscErrorCode ierr;
421c58f1c22SToby Isaac 
422c58f1c22SToby Isaac   PetscFunctionBegin;
423d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
424b9907514SLisandro Dalcin   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer);CHKERRQ(ierr);}
425c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
426c58f1c22SToby Isaac   if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);}
427c58f1c22SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
428c58f1c22SToby Isaac   if (iascii) {
429c58f1c22SToby Isaac     ierr = DMLabelView_Ascii(label, viewer);CHKERRQ(ierr);
430c58f1c22SToby Isaac   }
431c58f1c22SToby Isaac   PetscFunctionReturn(0);
432c58f1c22SToby Isaac }
433c58f1c22SToby Isaac 
43484f0b6dfSMatthew G. Knepley /*@
435d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
436d67d17b1SMatthew G. Knepley 
4375b5e7992SMatthew G. Knepley   Not collective
4385b5e7992SMatthew G. Knepley 
439d67d17b1SMatthew G. Knepley   Input Parameter:
440d67d17b1SMatthew G. Knepley . label - The DMLabel
441d67d17b1SMatthew G. Knepley 
442d67d17b1SMatthew G. Knepley   Level: beginner
443d67d17b1SMatthew G. Knepley 
444d67d17b1SMatthew G. Knepley .seealso: DMLabelDestroy(), DMLabelCreate()
445d67d17b1SMatthew G. Knepley @*/
446d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelReset(DMLabel label)
447d67d17b1SMatthew G. Knepley {
448d67d17b1SMatthew G. Knepley   PetscInt       v;
449d67d17b1SMatthew G. Knepley   PetscErrorCode ierr;
450d67d17b1SMatthew G. Knepley 
451d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
452d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
453d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
454d67d17b1SMatthew G. Knepley     ierr = PetscHSetIDestroy(&label->ht[v]);CHKERRQ(ierr);
455d67d17b1SMatthew G. Knepley     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
456d67d17b1SMatthew G. Knepley   }
457b9907514SLisandro Dalcin   label->numStrata = 0;
458b9907514SLisandro Dalcin   ierr = PetscFree(label->stratumValues);CHKERRQ(ierr);
459b9907514SLisandro Dalcin   ierr = PetscFree(label->stratumSizes);CHKERRQ(ierr);
460d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->ht);CHKERRQ(ierr);
461d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->points);CHKERRQ(ierr);
462d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->validIS);CHKERRQ(ierr);
463b9907514SLisandro Dalcin   ierr = PetscHMapIReset(label->hmap);CHKERRQ(ierr);
464b9907514SLisandro Dalcin   label->pStart = -1;
465b9907514SLisandro Dalcin   label->pEnd   = -1;
466d67d17b1SMatthew G. Knepley   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
467d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
468d67d17b1SMatthew G. Knepley }
469d67d17b1SMatthew G. Knepley 
470d67d17b1SMatthew G. Knepley /*@
47184f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
47284f0b6dfSMatthew G. Knepley 
4735b5e7992SMatthew G. Knepley   Collective on label
4745b5e7992SMatthew G. Knepley 
47584f0b6dfSMatthew G. Knepley   Input Parameter:
47684f0b6dfSMatthew G. Knepley . label - The DMLabel
47784f0b6dfSMatthew G. Knepley 
47884f0b6dfSMatthew G. Knepley   Level: beginner
47984f0b6dfSMatthew G. Knepley 
480d67d17b1SMatthew G. Knepley .seealso: DMLabelReset(), DMLabelCreate()
48184f0b6dfSMatthew G. Knepley @*/
482c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
483c58f1c22SToby Isaac {
484c58f1c22SToby Isaac   PetscErrorCode ierr;
485c58f1c22SToby Isaac 
486c58f1c22SToby Isaac   PetscFunctionBegin;
487d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
488d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1);
489b9907514SLisandro Dalcin   if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);}
490d67d17b1SMatthew G. Knepley   ierr = DMLabelReset(*label);CHKERRQ(ierr);
491b9907514SLisandro Dalcin   ierr = PetscHMapIDestroy(&(*label)->hmap);CHKERRQ(ierr);
492d67d17b1SMatthew G. Knepley   ierr = PetscHeaderDestroy(label);CHKERRQ(ierr);
493c58f1c22SToby Isaac   PetscFunctionReturn(0);
494c58f1c22SToby Isaac }
495c58f1c22SToby Isaac 
49684f0b6dfSMatthew G. Knepley /*@
49784f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
49884f0b6dfSMatthew G. Knepley 
4995b5e7992SMatthew G. Knepley   Collective on label
5005b5e7992SMatthew G. Knepley 
50184f0b6dfSMatthew G. Knepley   Input Parameter:
50284f0b6dfSMatthew G. Knepley . label - The DMLabel
50384f0b6dfSMatthew G. Knepley 
50484f0b6dfSMatthew G. Knepley   Output Parameter:
50584f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
50684f0b6dfSMatthew G. Knepley 
50784f0b6dfSMatthew G. Knepley   Level: intermediate
50884f0b6dfSMatthew G. Knepley 
50984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelDestroy()
51084f0b6dfSMatthew G. Knepley @*/
511c58f1c22SToby Isaac PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
512c58f1c22SToby Isaac {
513d67d17b1SMatthew G. Knepley   const char    *name;
514ad8374ffSToby Isaac   PetscInt       v;
515c58f1c22SToby Isaac   PetscErrorCode ierr;
516c58f1c22SToby Isaac 
517c58f1c22SToby Isaac   PetscFunctionBegin;
518d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
519c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
520d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
521d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew);CHKERRQ(ierr);
522c58f1c22SToby Isaac 
523c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5245aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
525c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues);CHKERRQ(ierr);
526c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes);CHKERRQ(ierr);
527c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->ht);CHKERRQ(ierr);
528c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->points);CHKERRQ(ierr);
529ad8374ffSToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->validIS);CHKERRQ(ierr);
530c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
531e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelnew)->ht[v]);CHKERRQ(ierr);
532c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
533c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
534ad8374ffSToby Isaac     ierr = PetscObjectReference((PetscObject) (label->points[v]));CHKERRQ(ierr);
535ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
536b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
537c58f1c22SToby Isaac   }
538f14fe40dSLisandro Dalcin   ierr = PetscHMapIDestroy(&(*labelnew)->hmap);CHKERRQ(ierr);
539b9907514SLisandro Dalcin   ierr = PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap);CHKERRQ(ierr);
540c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
541c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
542c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
543c58f1c22SToby Isaac   PetscFunctionReturn(0);
544c58f1c22SToby Isaac }
545c58f1c22SToby Isaac 
546c6a43d28SMatthew G. Knepley /*@
547c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
548c6a43d28SMatthew G. Knepley 
5495b5e7992SMatthew G. Knepley   Not collective
5505b5e7992SMatthew G. Knepley 
551c6a43d28SMatthew G. Knepley   Input Parameter:
552c6a43d28SMatthew G. Knepley . label  - The DMLabel
553c6a43d28SMatthew G. Knepley 
554c6a43d28SMatthew G. Knepley   Level: intermediate
555c6a43d28SMatthew G. Knepley 
556c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
557c6a43d28SMatthew G. Knepley @*/
558c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
559c6a43d28SMatthew G. Knepley {
560c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
561c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
562c6a43d28SMatthew G. Knepley 
563c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
564c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
565c6a43d28SMatthew G. Knepley   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
566c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
567c6a43d28SMatthew G. Knepley     const PetscInt *points;
568c6a43d28SMatthew G. Knepley     PetscInt       i;
569c6a43d28SMatthew G. Knepley 
570c6a43d28SMatthew G. Knepley     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
571c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
572c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
573c6a43d28SMatthew G. Knepley 
574c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
575c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
576c6a43d28SMatthew G. Knepley     }
577c6a43d28SMatthew G. Knepley     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
578c6a43d28SMatthew G. Knepley   }
579c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
580c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
581c6a43d28SMatthew G. Knepley   ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
582c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
583c6a43d28SMatthew G. Knepley }
584c6a43d28SMatthew G. Knepley 
585c6a43d28SMatthew G. Knepley /*@
586c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
587c6a43d28SMatthew G. Knepley 
5885b5e7992SMatthew G. Knepley   Not collective
5895b5e7992SMatthew G. Knepley 
590c6a43d28SMatthew G. Knepley   Input Parameters:
591c6a43d28SMatthew G. Knepley + label  - The DMLabel
592c6a43d28SMatthew G. Knepley . pStart - The smallest point
593c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
594c6a43d28SMatthew G. Knepley 
595c6a43d28SMatthew G. Knepley   Level: intermediate
596c6a43d28SMatthew G. Knepley 
597c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelComputeIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
598c6a43d28SMatthew G. Knepley @*/
599c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
600c58f1c22SToby Isaac {
601c58f1c22SToby Isaac   PetscInt       v;
602c58f1c22SToby Isaac   PetscErrorCode ierr;
603c58f1c22SToby Isaac 
604c58f1c22SToby Isaac   PetscFunctionBegin;
605d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6060c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
607c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
608c58f1c22SToby Isaac   label->pStart = pStart;
609c58f1c22SToby Isaac   label->pEnd   = pEnd;
610c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
611c58f1c22SToby Isaac   ierr = PetscBTCreate(pEnd - pStart, &label->bt);CHKERRQ(ierr);
612c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
613ad8374ffSToby Isaac     const PetscInt *points;
614c58f1c22SToby Isaac     PetscInt       i;
615c58f1c22SToby Isaac 
616ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
617c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
618ad8374ffSToby Isaac       const PetscInt point = points[i];
619c58f1c22SToby Isaac 
620c58f1c22SToby 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);
621c58f1c22SToby Isaac       ierr = PetscBTSet(label->bt, point - pStart);CHKERRQ(ierr);
622c58f1c22SToby Isaac     }
623ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
624c58f1c22SToby Isaac   }
625c58f1c22SToby Isaac   PetscFunctionReturn(0);
626c58f1c22SToby Isaac }
627c58f1c22SToby Isaac 
628c6a43d28SMatthew G. Knepley /*@
629c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
630c6a43d28SMatthew G. Knepley 
6315b5e7992SMatthew G. Knepley   Not collective
6325b5e7992SMatthew G. Knepley 
633c6a43d28SMatthew G. Knepley   Input Parameter:
634c6a43d28SMatthew G. Knepley . label - the DMLabel
635c6a43d28SMatthew G. Knepley 
636c6a43d28SMatthew G. Knepley   Level: intermediate
637c6a43d28SMatthew G. Knepley 
638c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
639c6a43d28SMatthew G. Knepley @*/
640c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
641c58f1c22SToby Isaac {
642c58f1c22SToby Isaac   PetscErrorCode ierr;
643c58f1c22SToby Isaac 
644c58f1c22SToby Isaac   PetscFunctionBegin;
645d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
646c58f1c22SToby Isaac   label->pStart = -1;
647c58f1c22SToby Isaac   label->pEnd   = -1;
6480c3c4a36SLisandro Dalcin   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
649c58f1c22SToby Isaac   PetscFunctionReturn(0);
650c58f1c22SToby Isaac }
651c58f1c22SToby Isaac 
652c58f1c22SToby Isaac /*@
653c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
654c6a43d28SMatthew G. Knepley 
6555b5e7992SMatthew G. Knepley   Not collective
6565b5e7992SMatthew G. Knepley 
657c6a43d28SMatthew G. Knepley   Input Parameter:
658c6a43d28SMatthew G. Knepley . label - the DMLabel
659c6a43d28SMatthew G. Knepley 
660c6a43d28SMatthew G. Knepley   Output Parameters:
661c6a43d28SMatthew G. Knepley + pStart - The smallest point
662c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
663c6a43d28SMatthew G. Knepley 
664c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
665c6a43d28SMatthew G. Knepley 
666c6a43d28SMatthew G. Knepley   Level: intermediate
667c6a43d28SMatthew G. Knepley 
668c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
669c6a43d28SMatthew G. Knepley @*/
670c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
671c6a43d28SMatthew G. Knepley {
672c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
673c6a43d28SMatthew G. Knepley 
674c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
675c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
676c6a43d28SMatthew G. Knepley   if ((label->pStart == -1) && (label->pEnd == -1)) {ierr = DMLabelComputeIndex(label);CHKERRQ(ierr);}
677c6a43d28SMatthew G. Knepley   if (pStart) {
678*534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
679c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
680c6a43d28SMatthew G. Knepley   }
681c6a43d28SMatthew G. Knepley   if (pEnd) {
682*534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
683c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
684c6a43d28SMatthew G. Knepley   }
685c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
686c6a43d28SMatthew G. Knepley }
687c6a43d28SMatthew G. Knepley 
688c6a43d28SMatthew G. Knepley /*@
689c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
690c58f1c22SToby Isaac 
6915b5e7992SMatthew G. Knepley   Not collective
6925b5e7992SMatthew G. Knepley 
693c58f1c22SToby Isaac   Input Parameters:
694c58f1c22SToby Isaac + label - the DMLabel
695c58f1c22SToby Isaac - value - the value
696c58f1c22SToby Isaac 
697c58f1c22SToby Isaac   Output Parameter:
698c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
699c58f1c22SToby Isaac 
700c58f1c22SToby Isaac   Level: developer
701c58f1c22SToby Isaac 
702c58f1c22SToby Isaac .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue()
703c58f1c22SToby Isaac @*/
704c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
705c58f1c22SToby Isaac {
706c58f1c22SToby Isaac   PetscInt v;
7070c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
708c58f1c22SToby Isaac 
709c58f1c22SToby Isaac   PetscFunctionBegin;
710d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
711*534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
7120c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
7130c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
714c58f1c22SToby Isaac   PetscFunctionReturn(0);
715c58f1c22SToby Isaac }
716c58f1c22SToby Isaac 
717c58f1c22SToby Isaac /*@
718c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
719c58f1c22SToby Isaac 
7205b5e7992SMatthew G. Knepley   Not collective
7215b5e7992SMatthew G. Knepley 
722c58f1c22SToby Isaac   Input Parameters:
723c58f1c22SToby Isaac + label - the DMLabel
724c58f1c22SToby Isaac - point - the point
725c58f1c22SToby Isaac 
726c58f1c22SToby Isaac   Output Parameter:
727c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
728c58f1c22SToby Isaac 
729c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
730c58f1c22SToby Isaac 
731c58f1c22SToby Isaac   Level: developer
732c58f1c22SToby Isaac 
733c58f1c22SToby Isaac .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
734c58f1c22SToby Isaac @*/
735c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
736c58f1c22SToby Isaac {
737c58f1c22SToby Isaac   PetscErrorCode ierr;
738c58f1c22SToby Isaac 
739c58f1c22SToby Isaac   PetscFunctionBeginHot;
740d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
741*534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
742c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
743c58f1c22SToby Isaac #if defined(PETSC_USE_DEBUG)
744c58f1c22SToby Isaac   if (!label->bt) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
745c58f1c22SToby 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);
746c58f1c22SToby Isaac #endif
747c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
748c58f1c22SToby Isaac   PetscFunctionReturn(0);
749c58f1c22SToby Isaac }
750c58f1c22SToby Isaac 
751c58f1c22SToby Isaac /*@
752c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
753c58f1c22SToby Isaac 
7545b5e7992SMatthew G. Knepley   Not collective
7555b5e7992SMatthew G. Knepley 
756c58f1c22SToby Isaac   Input Parameters:
757c58f1c22SToby Isaac + label - the DMLabel
758c58f1c22SToby Isaac . value - the stratum value
759c58f1c22SToby Isaac - point - the point
760c58f1c22SToby Isaac 
761c58f1c22SToby Isaac   Output Parameter:
762c58f1c22SToby Isaac . contains - true if the stratum contains the point
763c58f1c22SToby Isaac 
764c58f1c22SToby Isaac   Level: intermediate
765c58f1c22SToby Isaac 
766c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue()
767c58f1c22SToby Isaac @*/
768c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
769c58f1c22SToby Isaac {
770c58f1c22SToby Isaac   PetscInt       v;
771c58f1c22SToby Isaac   PetscErrorCode ierr;
772c58f1c22SToby Isaac 
7730c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
774d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
775*534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
776c58f1c22SToby Isaac   *contains = PETSC_FALSE;
7770c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
7780c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
7790c3c4a36SLisandro Dalcin 
780ad8374ffSToby Isaac   if (label->validIS[v]) {
781c58f1c22SToby Isaac     PetscInt i;
782c58f1c22SToby Isaac 
783a2d74346SToby Isaac     ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
7840c3c4a36SLisandro Dalcin     if (i >= 0) *contains = PETSC_TRUE;
785c58f1c22SToby Isaac   } else {
786c58f1c22SToby Isaac     PetscBool has;
787c58f1c22SToby Isaac 
788b9907514SLisandro Dalcin     ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
7890c3c4a36SLisandro Dalcin     if (has) *contains = PETSC_TRUE;
790c58f1c22SToby Isaac   }
791c58f1c22SToby Isaac   PetscFunctionReturn(0);
792c58f1c22SToby Isaac }
793c58f1c22SToby Isaac 
79484f0b6dfSMatthew G. Knepley /*@
7955aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
7965aa44df4SToby Isaac   When a label is created, it is initialized to -1.
7975aa44df4SToby Isaac 
7985b5e7992SMatthew G. Knepley   Not collective
7995b5e7992SMatthew G. Knepley 
8005aa44df4SToby Isaac   Input parameter:
8015aa44df4SToby Isaac . label - a DMLabel object
8025aa44df4SToby Isaac 
8035aa44df4SToby Isaac   Output parameter:
8045aa44df4SToby Isaac . defaultValue - the default value
8055aa44df4SToby Isaac 
8065aa44df4SToby Isaac   Level: beginner
8075aa44df4SToby Isaac 
8085aa44df4SToby Isaac .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
80984f0b6dfSMatthew G. Knepley @*/
8105aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
8115aa44df4SToby Isaac {
8125aa44df4SToby Isaac   PetscFunctionBegin;
813d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8145aa44df4SToby Isaac   *defaultValue = label->defaultValue;
8155aa44df4SToby Isaac   PetscFunctionReturn(0);
8165aa44df4SToby Isaac }
8175aa44df4SToby Isaac 
81884f0b6dfSMatthew G. Knepley /*@
8195aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8205aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8215aa44df4SToby Isaac 
8225b5e7992SMatthew G. Knepley   Not collective
8235b5e7992SMatthew G. Knepley 
8245aa44df4SToby Isaac   Input parameter:
8255aa44df4SToby Isaac . label - a DMLabel object
8265aa44df4SToby Isaac 
8275aa44df4SToby Isaac   Output parameter:
8285aa44df4SToby Isaac . defaultValue - the default value
8295aa44df4SToby Isaac 
8305aa44df4SToby Isaac   Level: beginner
8315aa44df4SToby Isaac 
8325aa44df4SToby Isaac .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
83384f0b6dfSMatthew G. Knepley @*/
8345aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
8355aa44df4SToby Isaac {
8365aa44df4SToby Isaac   PetscFunctionBegin;
837d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8385aa44df4SToby Isaac   label->defaultValue = defaultValue;
8395aa44df4SToby Isaac   PetscFunctionReturn(0);
8405aa44df4SToby Isaac }
8415aa44df4SToby Isaac 
842c58f1c22SToby Isaac /*@
8435aa44df4SToby 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())
844c58f1c22SToby Isaac 
8455b5e7992SMatthew G. Knepley   Not collective
8465b5e7992SMatthew G. Knepley 
847c58f1c22SToby Isaac   Input Parameters:
848c58f1c22SToby Isaac + label - the DMLabel
849c58f1c22SToby Isaac - point - the point
850c58f1c22SToby Isaac 
851c58f1c22SToby Isaac   Output Parameter:
8528e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
853c58f1c22SToby Isaac 
854c58f1c22SToby Isaac   Level: intermediate
855c58f1c22SToby Isaac 
8565aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
857c58f1c22SToby Isaac @*/
858c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
859c58f1c22SToby Isaac {
860c58f1c22SToby Isaac   PetscInt       v;
861c58f1c22SToby Isaac   PetscErrorCode ierr;
862c58f1c22SToby Isaac 
8630c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
864d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
865c58f1c22SToby Isaac   PetscValidPointer(value, 3);
8665aa44df4SToby Isaac   *value = label->defaultValue;
867c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
868ad8374ffSToby Isaac     if (label->validIS[v]) {
869c58f1c22SToby Isaac       PetscInt i;
870c58f1c22SToby Isaac 
871a2d74346SToby Isaac       ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
872c58f1c22SToby Isaac       if (i >= 0) {
873c58f1c22SToby Isaac         *value = label->stratumValues[v];
874c58f1c22SToby Isaac         break;
875c58f1c22SToby Isaac       }
876c58f1c22SToby Isaac     } else {
877c58f1c22SToby Isaac       PetscBool has;
878c58f1c22SToby Isaac 
879b9907514SLisandro Dalcin       ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
880c58f1c22SToby Isaac       if (has) {
881c58f1c22SToby Isaac         *value = label->stratumValues[v];
882c58f1c22SToby Isaac         break;
883c58f1c22SToby Isaac       }
884c58f1c22SToby Isaac     }
885c58f1c22SToby Isaac   }
886c58f1c22SToby Isaac   PetscFunctionReturn(0);
887c58f1c22SToby Isaac }
888c58f1c22SToby Isaac 
889c58f1c22SToby Isaac /*@
890367003a6SStefano 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.
891c58f1c22SToby Isaac 
8925b5e7992SMatthew G. Knepley   Not collective
8935b5e7992SMatthew G. Knepley 
894c58f1c22SToby Isaac   Input Parameters:
895c58f1c22SToby Isaac + label - the DMLabel
896c58f1c22SToby Isaac . point - the point
897c58f1c22SToby Isaac - value - The point value
898c58f1c22SToby Isaac 
899c58f1c22SToby Isaac   Level: intermediate
900c58f1c22SToby Isaac 
9015aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
902c58f1c22SToby Isaac @*/
903c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
904c58f1c22SToby Isaac {
905c58f1c22SToby Isaac   PetscInt       v;
906c58f1c22SToby Isaac   PetscErrorCode ierr;
907c58f1c22SToby Isaac 
908c58f1c22SToby Isaac   PetscFunctionBegin;
909d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9100c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
9115aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
912b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
913c58f1c22SToby Isaac   /* Set key */
9140c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
915e8f14785SLisandro Dalcin   ierr = PetscHSetIAdd(label->ht[v], point);CHKERRQ(ierr);
916c58f1c22SToby Isaac   PetscFunctionReturn(0);
917c58f1c22SToby Isaac }
918c58f1c22SToby Isaac 
919c58f1c22SToby Isaac /*@
920c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
921c58f1c22SToby Isaac 
9225b5e7992SMatthew G. Knepley   Not collective
9235b5e7992SMatthew G. Knepley 
924c58f1c22SToby Isaac   Input Parameters:
925c58f1c22SToby Isaac + label - the DMLabel
926c58f1c22SToby Isaac . point - the point
927c58f1c22SToby Isaac - value - The point value
928c58f1c22SToby Isaac 
929c58f1c22SToby Isaac   Level: intermediate
930c58f1c22SToby Isaac 
931c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue()
932c58f1c22SToby Isaac @*/
933c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
934c58f1c22SToby Isaac {
935ad8374ffSToby Isaac   PetscInt       v;
936c58f1c22SToby Isaac   PetscErrorCode ierr;
937c58f1c22SToby Isaac 
938c58f1c22SToby Isaac   PetscFunctionBegin;
939d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
940c58f1c22SToby Isaac   /* Find label value */
9410c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
9420c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
9430c3c4a36SLisandro Dalcin 
944eeed21e7SToby Isaac   if (label->bt) {
945eeed21e7SToby 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);
946eeed21e7SToby Isaac     ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
947eeed21e7SToby Isaac   }
9480c3c4a36SLisandro Dalcin 
9490c3c4a36SLisandro Dalcin   /* Delete key */
9500c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
951e8f14785SLisandro Dalcin   ierr = PetscHSetIDel(label->ht[v], point);CHKERRQ(ierr);
952c58f1c22SToby Isaac   PetscFunctionReturn(0);
953c58f1c22SToby Isaac }
954c58f1c22SToby Isaac 
955c58f1c22SToby Isaac /*@
956c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
957c58f1c22SToby Isaac 
9585b5e7992SMatthew G. Knepley   Not collective
9595b5e7992SMatthew G. Knepley 
960c58f1c22SToby Isaac   Input Parameters:
961c58f1c22SToby Isaac + label - the DMLabel
962c58f1c22SToby Isaac . is    - the point IS
963c58f1c22SToby Isaac - value - The point value
964c58f1c22SToby Isaac 
965c58f1c22SToby Isaac   Level: intermediate
966c58f1c22SToby Isaac 
967c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
968c58f1c22SToby Isaac @*/
969c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
970c58f1c22SToby Isaac {
9710c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
972c58f1c22SToby Isaac   const PetscInt *points;
973c58f1c22SToby Isaac   PetscErrorCode  ierr;
974c58f1c22SToby Isaac 
975c58f1c22SToby Isaac   PetscFunctionBegin;
976d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
977c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9780c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
9790c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
980b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
9810c3c4a36SLisandro Dalcin   /* Set keys */
9820c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
983c58f1c22SToby Isaac   ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr);
984c58f1c22SToby Isaac   ierr = ISGetIndices(is, &points);CHKERRQ(ierr);
985e8f14785SLisandro Dalcin   for (p = 0; p < n; ++p) {ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);}
986c58f1c22SToby Isaac   ierr = ISRestoreIndices(is, &points);CHKERRQ(ierr);
987c58f1c22SToby Isaac   PetscFunctionReturn(0);
988c58f1c22SToby Isaac }
989c58f1c22SToby Isaac 
99084f0b6dfSMatthew G. Knepley /*@
99184f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
99284f0b6dfSMatthew G. Knepley 
9935b5e7992SMatthew G. Knepley   Not collective
9945b5e7992SMatthew G. Knepley 
99584f0b6dfSMatthew G. Knepley   Input Parameter:
99684f0b6dfSMatthew G. Knepley . label - the DMLabel
99784f0b6dfSMatthew G. Knepley 
99884f0b6dfSMatthew G. Knepley   Output Paramater:
99984f0b6dfSMatthew G. Knepley . numValues - the number of values
100084f0b6dfSMatthew G. Knepley 
100184f0b6dfSMatthew G. Knepley   Level: intermediate
100284f0b6dfSMatthew G. Knepley 
100384f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
100484f0b6dfSMatthew G. Knepley @*/
1005c58f1c22SToby Isaac PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1006c58f1c22SToby Isaac {
1007c58f1c22SToby Isaac   PetscFunctionBegin;
1008d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1009c58f1c22SToby Isaac   PetscValidPointer(numValues, 2);
1010c58f1c22SToby Isaac   *numValues = label->numStrata;
1011c58f1c22SToby Isaac   PetscFunctionReturn(0);
1012c58f1c22SToby Isaac }
1013c58f1c22SToby Isaac 
101484f0b6dfSMatthew G. Knepley /*@
101584f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
101684f0b6dfSMatthew G. Knepley 
10175b5e7992SMatthew G. Knepley   Not collective
10185b5e7992SMatthew G. Knepley 
101984f0b6dfSMatthew G. Knepley   Input Parameter:
102084f0b6dfSMatthew G. Knepley . label - the DMLabel
102184f0b6dfSMatthew G. Knepley 
102284f0b6dfSMatthew G. Knepley   Output Paramater:
102384f0b6dfSMatthew G. Knepley . is    - the value IS
102484f0b6dfSMatthew G. Knepley 
102584f0b6dfSMatthew G. Knepley   Level: intermediate
102684f0b6dfSMatthew G. Knepley 
102784f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
102884f0b6dfSMatthew G. Knepley @*/
1029c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1030c58f1c22SToby Isaac {
1031c58f1c22SToby Isaac   PetscErrorCode ierr;
1032c58f1c22SToby Isaac 
1033c58f1c22SToby Isaac   PetscFunctionBegin;
1034d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1035c58f1c22SToby Isaac   PetscValidPointer(values, 2);
1036c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values);CHKERRQ(ierr);
1037c58f1c22SToby Isaac   PetscFunctionReturn(0);
1038c58f1c22SToby Isaac }
1039c58f1c22SToby Isaac 
104084f0b6dfSMatthew G. Knepley /*@
104184f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
104284f0b6dfSMatthew G. Knepley 
10435b5e7992SMatthew G. Knepley   Not collective
10445b5e7992SMatthew G. Knepley 
104584f0b6dfSMatthew G. Knepley   Input Parameters:
104684f0b6dfSMatthew G. Knepley + label - the DMLabel
104784f0b6dfSMatthew G. Knepley - value - the stratum value
104884f0b6dfSMatthew G. Knepley 
104984f0b6dfSMatthew G. Knepley   Output Paramater:
105084f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
105184f0b6dfSMatthew G. Knepley 
105284f0b6dfSMatthew G. Knepley   Level: intermediate
105384f0b6dfSMatthew G. Knepley 
105484f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
105584f0b6dfSMatthew G. Knepley @*/
1056fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1057fada774cSMatthew G. Knepley {
1058fada774cSMatthew G. Knepley   PetscInt       v;
10590c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
1060fada774cSMatthew G. Knepley 
1061fada774cSMatthew G. Knepley   PetscFunctionBegin;
1062d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1063fada774cSMatthew G. Knepley   PetscValidPointer(exists, 3);
10640c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
10650c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1066fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1067fada774cSMatthew G. Knepley }
1068fada774cSMatthew G. Knepley 
106984f0b6dfSMatthew G. Knepley /*@
107084f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
107184f0b6dfSMatthew G. Knepley 
10725b5e7992SMatthew G. Knepley   Not collective
10735b5e7992SMatthew G. Knepley 
107484f0b6dfSMatthew G. Knepley   Input Parameters:
107584f0b6dfSMatthew G. Knepley + label - the DMLabel
107684f0b6dfSMatthew G. Knepley - value - the stratum value
107784f0b6dfSMatthew G. Knepley 
107884f0b6dfSMatthew G. Knepley   Output Paramater:
107984f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
108084f0b6dfSMatthew G. Knepley 
108184f0b6dfSMatthew G. Knepley   Level: intermediate
108284f0b6dfSMatthew G. Knepley 
108384f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
108484f0b6dfSMatthew G. Knepley @*/
1085c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1086c58f1c22SToby Isaac {
1087c58f1c22SToby Isaac   PetscInt       v;
1088c58f1c22SToby Isaac   PetscErrorCode ierr;
1089c58f1c22SToby Isaac 
1090c58f1c22SToby Isaac   PetscFunctionBegin;
1091d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1092c58f1c22SToby Isaac   PetscValidPointer(size, 3);
1093c58f1c22SToby Isaac   *size = 0;
10940c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
10950c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1096c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1097c58f1c22SToby Isaac   *size = label->stratumSizes[v];
1098c58f1c22SToby Isaac   PetscFunctionReturn(0);
1099c58f1c22SToby Isaac }
1100c58f1c22SToby Isaac 
110184f0b6dfSMatthew G. Knepley /*@
110284f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
110384f0b6dfSMatthew G. Knepley 
11045b5e7992SMatthew G. Knepley   Not collective
11055b5e7992SMatthew G. Knepley 
110684f0b6dfSMatthew G. Knepley   Input Parameters:
110784f0b6dfSMatthew G. Knepley + label - the DMLabel
110884f0b6dfSMatthew G. Knepley - value - the stratum value
110984f0b6dfSMatthew G. Knepley 
111084f0b6dfSMatthew G. Knepley   Output Paramaters:
111184f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
111284f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
111384f0b6dfSMatthew G. Knepley 
111484f0b6dfSMatthew G. Knepley   Level: intermediate
111584f0b6dfSMatthew G. Knepley 
111684f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
111784f0b6dfSMatthew G. Knepley @*/
1118c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1119c58f1c22SToby Isaac {
11200c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1121c58f1c22SToby Isaac   PetscErrorCode ierr;
1122c58f1c22SToby Isaac 
1123c58f1c22SToby Isaac   PetscFunctionBegin;
1124d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1125c58f1c22SToby Isaac   if (start) {PetscValidPointer(start, 3); *start = 0;}
1126c58f1c22SToby Isaac   if (end)   {PetscValidPointer(end,   4); *end   = 0;}
11270c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11280c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1129c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
11300c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
1131d6cb179aSToby Isaac   ierr = ISGetMinMax(label->points[v], &min, &max);CHKERRQ(ierr);
1132d6cb179aSToby Isaac   if (start) *start = min;
1133d6cb179aSToby Isaac   if (end)   *end   = max+1;
1134c58f1c22SToby Isaac   PetscFunctionReturn(0);
1135c58f1c22SToby Isaac }
1136c58f1c22SToby Isaac 
113784f0b6dfSMatthew G. Knepley /*@
113884f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
113984f0b6dfSMatthew G. Knepley 
11405b5e7992SMatthew G. Knepley   Not collective
11415b5e7992SMatthew G. Knepley 
114284f0b6dfSMatthew G. Knepley   Input Parameters:
114384f0b6dfSMatthew G. Knepley + label - the DMLabel
114484f0b6dfSMatthew G. Knepley - value - the stratum value
114584f0b6dfSMatthew G. Knepley 
114684f0b6dfSMatthew G. Knepley   Output Paramater:
114784f0b6dfSMatthew G. Knepley . points - The stratum points
114884f0b6dfSMatthew G. Knepley 
114984f0b6dfSMatthew G. Knepley   Level: intermediate
115084f0b6dfSMatthew G. Knepley 
115184f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
115284f0b6dfSMatthew G. Knepley @*/
1153c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1154c58f1c22SToby Isaac {
1155c58f1c22SToby Isaac   PetscInt       v;
1156c58f1c22SToby Isaac   PetscErrorCode ierr;
1157c58f1c22SToby Isaac 
1158c58f1c22SToby Isaac   PetscFunctionBegin;
1159d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1160c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1161c58f1c22SToby Isaac   *points = NULL;
11620c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11630c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1164c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1165ad8374ffSToby Isaac   ierr = PetscObjectReference((PetscObject) label->points[v]);CHKERRQ(ierr);
1166ad8374ffSToby Isaac   *points = label->points[v];
1167c58f1c22SToby Isaac   PetscFunctionReturn(0);
1168c58f1c22SToby Isaac }
1169c58f1c22SToby Isaac 
117084f0b6dfSMatthew G. Knepley /*@
117184f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
117284f0b6dfSMatthew G. Knepley 
11735b5e7992SMatthew G. Knepley   Not collective
11745b5e7992SMatthew G. Knepley 
117584f0b6dfSMatthew G. Knepley   Input Parameters:
117684f0b6dfSMatthew G. Knepley + label - the DMLabel
117784f0b6dfSMatthew G. Knepley . value - the stratum value
117884f0b6dfSMatthew G. Knepley - points - The stratum points
117984f0b6dfSMatthew G. Knepley 
118084f0b6dfSMatthew G. Knepley   Level: intermediate
118184f0b6dfSMatthew G. Knepley 
118284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
118384f0b6dfSMatthew G. Knepley @*/
11844de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
11854de306b1SToby Isaac {
11860c3c4a36SLisandro Dalcin   PetscInt       v;
11874de306b1SToby Isaac   PetscErrorCode ierr;
11884de306b1SToby Isaac 
11894de306b1SToby Isaac   PetscFunctionBegin;
1190d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1191d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
1192b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
11934de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
11944de306b1SToby Isaac   ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr);
11954de306b1SToby Isaac   ierr = ISGetLocalSize(is, &(label->stratumSizes[v]));CHKERRQ(ierr);
11964de306b1SToby Isaac   ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
11974de306b1SToby Isaac   ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr);
11980c3c4a36SLisandro Dalcin   label->points[v]  = is;
11990c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
1200277ea44aSLisandro Dalcin   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
12014de306b1SToby Isaac   if (label->bt) {
12024de306b1SToby Isaac     const PetscInt *points;
12034de306b1SToby Isaac     PetscInt p;
12044de306b1SToby Isaac 
12054de306b1SToby Isaac     ierr = ISGetIndices(is,&points);CHKERRQ(ierr);
12064de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
12074de306b1SToby Isaac       const PetscInt point = points[p];
12084de306b1SToby Isaac 
12094de306b1SToby 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);
12104de306b1SToby Isaac       ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr);
12114de306b1SToby Isaac     }
12124de306b1SToby Isaac   }
12134de306b1SToby Isaac   PetscFunctionReturn(0);
12144de306b1SToby Isaac }
12154de306b1SToby Isaac 
121684f0b6dfSMatthew G. Knepley /*@
121784f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
12184de306b1SToby Isaac 
12195b5e7992SMatthew G. Knepley   Not collective
12205b5e7992SMatthew G. Knepley 
122184f0b6dfSMatthew G. Knepley   Input Parameters:
122284f0b6dfSMatthew G. Knepley + label - the DMLabel
122384f0b6dfSMatthew G. Knepley - value - the stratum value
122484f0b6dfSMatthew G. Knepley 
122584f0b6dfSMatthew G. Knepley   Level: intermediate
122684f0b6dfSMatthew G. Knepley 
122784f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
122884f0b6dfSMatthew G. Knepley @*/
1229c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1230c58f1c22SToby Isaac {
1231c58f1c22SToby Isaac   PetscInt       v;
1232c58f1c22SToby Isaac   PetscErrorCode ierr;
1233c58f1c22SToby Isaac 
1234c58f1c22SToby Isaac   PetscFunctionBegin;
1235d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12360c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
12370c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
12384de306b1SToby Isaac   if (label->validIS[v]) {
12394de306b1SToby Isaac     if (label->bt) {
1240c58f1c22SToby Isaac       PetscInt       i;
1241ad8374ffSToby Isaac       const PetscInt *points;
1242c58f1c22SToby Isaac 
1243ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
1244c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1245ad8374ffSToby Isaac         const PetscInt point = points[i];
1246c58f1c22SToby Isaac 
1247c58f1c22SToby 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);
1248c58f1c22SToby Isaac         ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
1249c58f1c22SToby Isaac       }
1250ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
1251c58f1c22SToby Isaac     }
1252c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
12530c3c4a36SLisandro Dalcin     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
1254277ea44aSLisandro Dalcin     ierr = ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]);CHKERRQ(ierr);
12550c3c4a36SLisandro Dalcin     ierr = PetscObjectSetName((PetscObject) label->points[v], "indices");CHKERRQ(ierr);
1256277ea44aSLisandro Dalcin     ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
1257c58f1c22SToby Isaac   } else {
1258b9907514SLisandro Dalcin     ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr);
1259c58f1c22SToby Isaac   }
1260c58f1c22SToby Isaac   PetscFunctionReturn(0);
1261c58f1c22SToby Isaac }
1262c58f1c22SToby Isaac 
126384f0b6dfSMatthew G. Knepley /*@
126484f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
126584f0b6dfSMatthew G. Knepley 
12665b5e7992SMatthew G. Knepley   Not collective
12675b5e7992SMatthew G. Knepley 
126884f0b6dfSMatthew G. Knepley   Input Parameters:
126984f0b6dfSMatthew G. Knepley + label - the DMLabel
127084f0b6dfSMatthew G. Knepley . start - the first point
127184f0b6dfSMatthew G. Knepley - end - the last point
127284f0b6dfSMatthew G. Knepley 
127384f0b6dfSMatthew G. Knepley   Level: intermediate
127484f0b6dfSMatthew G. Knepley 
127584f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
127684f0b6dfSMatthew G. Knepley @*/
1277c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1278c58f1c22SToby Isaac {
1279c58f1c22SToby Isaac   PetscInt       v;
1280c58f1c22SToby Isaac   PetscErrorCode ierr;
1281c58f1c22SToby Isaac 
1282c58f1c22SToby Isaac   PetscFunctionBegin;
1283d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
12840c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
1285c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1286c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
1287c58f1c22SToby Isaac     PetscInt off, q;
1288ad8374ffSToby Isaac     const PetscInt *points;
1289033405d5SLisandro Dalcin     PetscInt numPointsNew = 0, *pointsNew = NULL;
1290c58f1c22SToby Isaac 
1291ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
1292033405d5SLisandro Dalcin     for (q = 0; q < label->stratumSizes[v]; ++q)
1293033405d5SLisandro Dalcin       if (points[q] >= start && points[q] < end)
1294033405d5SLisandro Dalcin         numPointsNew++;
1295033405d5SLisandro Dalcin     ierr = PetscMalloc1(numPointsNew, &pointsNew);CHKERRQ(ierr);
1296c58f1c22SToby Isaac     for (off = 0, q = 0; q < label->stratumSizes[v]; ++q) {
1297033405d5SLisandro Dalcin       if (points[q] >= start && points[q] < end)
1298033405d5SLisandro Dalcin         pointsNew[off++] = points[q];
1299ad8374ffSToby Isaac     }
1300ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr);
1301033405d5SLisandro Dalcin 
1302033405d5SLisandro Dalcin     label->stratumSizes[v] = numPointsNew;
1303033405d5SLisandro Dalcin     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
1304033405d5SLisandro Dalcin     ierr = ISCreateGeneral(PETSC_COMM_SELF,numPointsNew, pointsNew, PETSC_OWN_POINTER, &label->points[v]);CHKERRQ(ierr);
1305033405d5SLisandro Dalcin     ierr = PetscObjectSetName((PetscObject) label->points[v], "indices");CHKERRQ(ierr);
1306c58f1c22SToby Isaac   }
1307c58f1c22SToby Isaac   ierr = DMLabelCreateIndex(label, start, end);CHKERRQ(ierr);
1308c58f1c22SToby Isaac   PetscFunctionReturn(0);
1309c58f1c22SToby Isaac }
1310c58f1c22SToby Isaac 
131184f0b6dfSMatthew G. Knepley /*@
131284f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
131384f0b6dfSMatthew G. Knepley 
13145b5e7992SMatthew G. Knepley   Not collective
13155b5e7992SMatthew G. Knepley 
131684f0b6dfSMatthew G. Knepley   Input Parameters:
131784f0b6dfSMatthew G. Knepley + label - the DMLabel
131884f0b6dfSMatthew G. Knepley - permutation - the point permutation
131984f0b6dfSMatthew G. Knepley 
132084f0b6dfSMatthew G. Knepley   Output Parameter:
132184f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
132284f0b6dfSMatthew G. Knepley 
132384f0b6dfSMatthew G. Knepley   Level: intermediate
132484f0b6dfSMatthew G. Knepley 
132584f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
132684f0b6dfSMatthew G. Knepley @*/
1327c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1328c58f1c22SToby Isaac {
1329c58f1c22SToby Isaac   const PetscInt *perm;
1330c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1331c58f1c22SToby Isaac   PetscErrorCode  ierr;
1332c58f1c22SToby Isaac 
1333c58f1c22SToby Isaac   PetscFunctionBegin;
1334d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1335d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
1336c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1337c58f1c22SToby Isaac   ierr = DMLabelDuplicate(label, labelNew);CHKERRQ(ierr);
1338c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(*labelNew, &numValues);CHKERRQ(ierr);
1339c58f1c22SToby Isaac   ierr = ISGetLocalSize(permutation, &numPoints);CHKERRQ(ierr);
1340c58f1c22SToby Isaac   ierr = ISGetIndices(permutation, &perm);CHKERRQ(ierr);
1341c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1342c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1343ad8374ffSToby Isaac     const PetscInt *points;
1344ad8374ffSToby Isaac     PetscInt *pointsNew;
1345c58f1c22SToby Isaac 
1346ad8374ffSToby Isaac     ierr = ISGetIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1347ad8374ffSToby Isaac     ierr = PetscMalloc1(size,&pointsNew);CHKERRQ(ierr);
1348c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1349ad8374ffSToby Isaac       const PetscInt point = points[q];
1350c58f1c22SToby Isaac 
1351c58f1c22SToby 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);
1352ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1353c58f1c22SToby Isaac     }
1354ad8374ffSToby Isaac     ierr = ISRestoreIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1355ad8374ffSToby Isaac     ierr = PetscSortInt(size, pointsNew);CHKERRQ(ierr);
1356ad8374ffSToby Isaac     ierr = ISDestroy(&((*labelNew)->points[v]));CHKERRQ(ierr);
1357fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
1358fa8e8ae5SToby Isaac       ierr = ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v]));CHKERRQ(ierr);
1359fa8e8ae5SToby Isaac       ierr = PetscFree(pointsNew);CHKERRQ(ierr);
1360fa8e8ae5SToby Isaac     } else {
1361ad8374ffSToby Isaac       ierr = ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v]));CHKERRQ(ierr);
1362fa8e8ae5SToby Isaac     }
1363ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices");CHKERRQ(ierr);
1364c58f1c22SToby Isaac   }
1365c58f1c22SToby Isaac   ierr = ISRestoreIndices(permutation, &perm);CHKERRQ(ierr);
1366c58f1c22SToby Isaac   if (label->bt) {
1367c58f1c22SToby Isaac     ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
1368c58f1c22SToby Isaac     ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
1369c58f1c22SToby Isaac   }
1370c58f1c22SToby Isaac   PetscFunctionReturn(0);
1371c58f1c22SToby Isaac }
1372c58f1c22SToby Isaac 
137326c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
137426c55118SMichael Lange {
137526c55118SMichael Lange   MPI_Comm       comm;
137626c55118SMichael Lange   PetscInt       s, l, nroots, nleaves, dof, offset, size;
137726c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
137826c55118SMichael Lange   PetscSection   rootSection;
137926c55118SMichael Lange   PetscSF        labelSF;
138026c55118SMichael Lange   PetscErrorCode ierr;
138126c55118SMichael Lange 
138226c55118SMichael Lange   PetscFunctionBegin;
138326c55118SMichael Lange   if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);}
138426c55118SMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
138526c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
138626c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
138726c55118SMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL);CHKERRQ(ierr);
138826c55118SMichael Lange   ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr);
138926c55118SMichael Lange   ierr = PetscSectionSetChart(rootSection, 0, nroots);CHKERRQ(ierr);
139026c55118SMichael Lange   if (label) {
139126c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1392ad8374ffSToby Isaac       const PetscInt *points;
1393ad8374ffSToby Isaac 
1394ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
139526c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1396ad8374ffSToby Isaac         ierr = PetscSectionGetDof(rootSection, points[l], &dof);CHKERRQ(ierr);
1397ad8374ffSToby Isaac         ierr = PetscSectionSetDof(rootSection, points[l], dof+1);CHKERRQ(ierr);
139826c55118SMichael Lange       }
1399ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
140026c55118SMichael Lange     }
140126c55118SMichael Lange   }
140226c55118SMichael Lange   ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr);
140326c55118SMichael Lange   /* Create a point-wise array of stratum values */
140426c55118SMichael Lange   ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr);
140526c55118SMichael Lange   ierr = PetscMalloc1(size, &rootStrata);CHKERRQ(ierr);
140626c55118SMichael Lange   ierr = PetscCalloc1(nroots, &rootIdx);CHKERRQ(ierr);
140726c55118SMichael Lange   if (label) {
140826c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1409ad8374ffSToby Isaac       const PetscInt *points;
1410ad8374ffSToby Isaac 
1411ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
141226c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1413ad8374ffSToby Isaac         const PetscInt p = points[l];
141426c55118SMichael Lange         ierr = PetscSectionGetOffset(rootSection, p, &offset);CHKERRQ(ierr);
141526c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
141626c55118SMichael Lange       }
1417ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
141826c55118SMichael Lange     }
141926c55118SMichael Lange   }
142026c55118SMichael Lange   /* Build SF that maps label points to remote processes */
142126c55118SMichael Lange   ierr = PetscSectionCreate(comm, leafSection);CHKERRQ(ierr);
142226c55118SMichael Lange   ierr = PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection);CHKERRQ(ierr);
142326c55118SMichael Lange   ierr = PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF);CHKERRQ(ierr);
142426c55118SMichael Lange   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
142526c55118SMichael Lange   /* Send the strata for each point over the derived SF */
142626c55118SMichael Lange   ierr = PetscSectionGetStorageSize(*leafSection, &size);CHKERRQ(ierr);
142726c55118SMichael Lange   ierr = PetscMalloc1(size, leafStrata);CHKERRQ(ierr);
142826c55118SMichael Lange   ierr = PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata);CHKERRQ(ierr);
142926c55118SMichael Lange   ierr = PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata);CHKERRQ(ierr);
143026c55118SMichael Lange   /* Clean up */
143126c55118SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
143226c55118SMichael Lange   ierr = PetscFree(rootIdx);CHKERRQ(ierr);
143326c55118SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
143426c55118SMichael Lange   ierr = PetscSFDestroy(&labelSF);CHKERRQ(ierr);
143526c55118SMichael Lange   PetscFunctionReturn(0);
143626c55118SMichael Lange }
143726c55118SMichael Lange 
143884f0b6dfSMatthew G. Knepley /*@
143984f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
144084f0b6dfSMatthew G. Knepley 
14415b5e7992SMatthew G. Knepley   Collective on sf
14425b5e7992SMatthew G. Knepley 
144384f0b6dfSMatthew G. Knepley   Input Parameters:
144484f0b6dfSMatthew G. Knepley + label - the DMLabel
144584f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
144684f0b6dfSMatthew G. Knepley 
144784f0b6dfSMatthew G. Knepley   Output Parameter:
144884f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
144984f0b6dfSMatthew G. Knepley 
145084f0b6dfSMatthew G. Knepley   Level: intermediate
145184f0b6dfSMatthew G. Knepley 
145284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
145384f0b6dfSMatthew G. Knepley @*/
1454c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1455c58f1c22SToby Isaac {
1456c58f1c22SToby Isaac   MPI_Comm       comm;
145726c55118SMichael Lange   PetscSection   leafSection;
145826c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
145926c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1460ad8374ffSToby Isaac   PetscInt     **points;
1461d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1462c58f1c22SToby Isaac   char          *name;
1463c58f1c22SToby Isaac   PetscInt       nameSize;
1464e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1465c58f1c22SToby Isaac   size_t         len = 0;
146626c55118SMichael Lange   PetscMPIInt    rank;
1467c58f1c22SToby Isaac   PetscErrorCode ierr;
1468c58f1c22SToby Isaac 
1469c58f1c22SToby Isaac   PetscFunctionBegin;
1470d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1471f018e600SMatthew G. Knepley   if (label) {
1472f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1473f018e600SMatthew G. Knepley     ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1474f018e600SMatthew G. Knepley   }
1475c58f1c22SToby Isaac   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
1476c58f1c22SToby Isaac   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1477c58f1c22SToby Isaac   /* Bcast name */
1478d67d17b1SMatthew G. Knepley   if (!rank) {
1479d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1480d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1481d67d17b1SMatthew G. Knepley   }
1482c58f1c22SToby Isaac   nameSize = len;
1483c58f1c22SToby Isaac   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
1484c58f1c22SToby Isaac   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1485580bdb30SBarry Smith   if (!rank) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
1486c58f1c22SToby Isaac   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr);
1487d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
1488c58f1c22SToby Isaac   ierr = PetscFree(name);CHKERRQ(ierr);
148977d236dfSMichael Lange   /* Bcast defaultValue */
149077d236dfSMichael Lange   if (!rank) (*labelNew)->defaultValue = label->defaultValue;
149177d236dfSMichael Lange   ierr = MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
149226c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
149326c55118SMichael Lange   ierr = DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata);CHKERRQ(ierr);
14945cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
1495e8f14785SLisandro Dalcin   ierr = PetscHSetICreate(&stratumHash);CHKERRQ(ierr);
149626c55118SMichael Lange   ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr);
1497e8f14785SLisandro Dalcin   for (p = 0; p < size; ++p) {ierr = PetscHSetIAdd(stratumHash, leafStrata[p]);CHKERRQ(ierr);}
1498e8f14785SLisandro Dalcin   ierr = PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata);CHKERRQ(ierr);
1499ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS);CHKERRQ(ierr);
1500ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
15015cbdf6fcSMichael Lange   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues);CHKERRQ(ierr);
15025cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
15035cbdf6fcSMichael Lange   offset = 0;
1504e8f14785SLisandro Dalcin   ierr = PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues);CHKERRQ(ierr);
1505a205f1fdSToby Isaac   ierr = PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues);CHKERRQ(ierr);
150690e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
150790e9b2aeSLisandro Dalcin     ierr = PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s);CHKERRQ(ierr);
150890e9b2aeSLisandro Dalcin   }
15095cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1510231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1511231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
15125cbdf6fcSMichael Lange     }
15135cbdf6fcSMichael Lange   }
1514c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
1515c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes);CHKERRQ(ierr);
1516c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1517c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1518c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1519c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1520c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1521c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1522c58f1c22SToby Isaac     }
1523c58f1c22SToby Isaac   }
1524c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht);CHKERRQ(ierr);
1525c58f1c22SToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points);CHKERRQ(ierr);
1526ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&points);CHKERRQ(ierr);
1527c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
1528e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelNew)->ht[s]);CHKERRQ(ierr);
1529ad8374ffSToby Isaac     ierr = PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s]));CHKERRQ(ierr);
1530c58f1c22SToby Isaac   }
1531c58f1c22SToby Isaac   /* Insert points into new strata */
1532c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata, &strataIdx);CHKERRQ(ierr);
1533c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1534c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1535c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1536c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1537c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1538c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1539ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1540c58f1c22SToby Isaac     }
1541c58f1c22SToby Isaac   }
1542ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1543ad8374ffSToby Isaac     ierr = ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s]));CHKERRQ(ierr);
1544ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices");CHKERRQ(ierr);
1545ad8374ffSToby Isaac   }
1546ad8374ffSToby Isaac   ierr = PetscFree(points);CHKERRQ(ierr);
1547e8f14785SLisandro Dalcin   ierr = PetscHSetIDestroy(&stratumHash);CHKERRQ(ierr);
1548c58f1c22SToby Isaac   ierr = PetscFree(leafStrata);CHKERRQ(ierr);
1549c58f1c22SToby Isaac   ierr = PetscFree(strataIdx);CHKERRQ(ierr);
1550c58f1c22SToby Isaac   ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr);
1551c58f1c22SToby Isaac   PetscFunctionReturn(0);
1552c58f1c22SToby Isaac }
1553c58f1c22SToby Isaac 
15547937d9ceSMichael Lange /*@
15557937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
15567937d9ceSMichael Lange 
15575b5e7992SMatthew G. Knepley   Collective on sf
15585b5e7992SMatthew G. Knepley 
15597937d9ceSMichael Lange   Input Parameters:
15607937d9ceSMichael Lange + label - the DMLabel
156184f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
15627937d9ceSMichael Lange 
156384f0b6dfSMatthew G. Knepley   Output Parameters:
156484f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
15657937d9ceSMichael Lange 
15667937d9ceSMichael Lange   Level: developer
15677937d9ceSMichael Lange 
15687937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
15697937d9ceSMichael Lange 
15707937d9ceSMichael Lange .seealso: DMLabelDistribute()
15717937d9ceSMichael Lange @*/
15727937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
15737937d9ceSMichael Lange {
15747937d9ceSMichael Lange   MPI_Comm       comm;
15757937d9ceSMichael Lange   PetscSection   rootSection;
15767937d9ceSMichael Lange   PetscSF        sfLabel;
15777937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
15787937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
15797937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
15807937d9ceSMichael Lange   PetscInt       *rootStrata;
1581d67d17b1SMatthew G. Knepley   const char    *lname;
15827937d9ceSMichael Lange   char          *name;
15837937d9ceSMichael Lange   PetscInt       nameSize;
15847937d9ceSMichael Lange   size_t         len = 0;
15859852e123SBarry Smith   PetscMPIInt    rank, size;
15867937d9ceSMichael Lange   PetscErrorCode ierr;
15877937d9ceSMichael Lange 
15887937d9ceSMichael Lange   PetscFunctionBegin;
1589d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1590d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
15917937d9ceSMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
15927937d9ceSMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
15939852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
15947937d9ceSMichael Lange   /* Bcast name */
1595d67d17b1SMatthew G. Knepley   if (!rank) {
1596d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1597d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1598d67d17b1SMatthew G. Knepley   }
15997937d9ceSMichael Lange   nameSize = len;
16007937d9ceSMichael Lange   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
16017937d9ceSMichael Lange   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1602580bdb30SBarry Smith   if (!rank) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
16037937d9ceSMichael Lange   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr);
1604d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
16057937d9ceSMichael Lange   ierr = PetscFree(name);CHKERRQ(ierr);
16067937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
16077937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
16087937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
16097937d9ceSMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL);CHKERRQ(ierr);
1610dc53bc9bSMatthew G. Knepley   ierr = PetscMalloc1(nroots, &leafPoints);CHKERRQ(ierr);
1611dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
16127937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
16138212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
16148212dd46SStefano Zampini 
16158212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
16168212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
16177937d9ceSMichael Lange   }
16187937d9ceSMichael Lange   ierr = PetscSFComputeDegreeBegin(sf, &rootDegree);CHKERRQ(ierr);
16197937d9ceSMichael Lange   ierr = PetscSFComputeDegreeEnd(sf, &rootDegree);CHKERRQ(ierr);
16207937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
16217937d9ceSMichael Lange   ierr = PetscMalloc1(nmultiroots, &rootPoints);CHKERRQ(ierr);
16227937d9ceSMichael Lange   ierr = PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
16237937d9ceSMichael Lange   ierr = PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
16247937d9ceSMichael Lange   ierr = PetscSFCreate(comm,& sfLabel);CHKERRQ(ierr);
16257937d9ceSMichael Lange   ierr = PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
16267937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
16277937d9ceSMichael Lange   ierr = DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata);CHKERRQ(ierr);
16287937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
16297937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
16307937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
16317937d9ceSMichael Lange       ierr = PetscSectionGetDof(rootSection, idx+d, &dof);CHKERRQ(ierr);
16327937d9ceSMichael Lange       ierr = PetscSectionGetOffset(rootSection, idx+d, &offset);CHKERRQ(ierr);
16337937d9ceSMichael Lange       for (s = 0; s < dof; s++) {ierr = DMLabelSetValue(*labelNew, p, rootStrata[offset+s]);CHKERRQ(ierr);}
16347937d9ceSMichael Lange     }
16357937d9ceSMichael Lange     idx += rootDegree[p];
16367937d9ceSMichael Lange   }
163777e0c0e7SMichael Lange   ierr = PetscFree(leafPoints);CHKERRQ(ierr);
163877e0c0e7SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
163977e0c0e7SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
164077e0c0e7SMichael Lange   ierr = PetscSFDestroy(&sfLabel);CHKERRQ(ierr);
16417937d9ceSMichael Lange   PetscFunctionReturn(0);
16427937d9ceSMichael Lange }
16437937d9ceSMichael Lange 
164484f0b6dfSMatthew G. Knepley /*@
164584f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
164684f0b6dfSMatthew G. Knepley 
16475b5e7992SMatthew G. Knepley   Not collective
16485b5e7992SMatthew G. Knepley 
164984f0b6dfSMatthew G. Knepley   Input Parameter:
165084f0b6dfSMatthew G. Knepley . label - the DMLabel
165184f0b6dfSMatthew G. Knepley 
165284f0b6dfSMatthew G. Knepley   Output Parameters:
165384f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
165484f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
165584f0b6dfSMatthew G. Knepley 
165684f0b6dfSMatthew G. Knepley   Level: developer
165784f0b6dfSMatthew G. Knepley 
165884f0b6dfSMatthew G. Knepley .seealso: DMLabelDistribute()
165984f0b6dfSMatthew G. Knepley @*/
1660c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
1661c58f1c22SToby Isaac {
1662c58f1c22SToby Isaac   IS              vIS;
1663c58f1c22SToby Isaac   const PetscInt *values;
1664c58f1c22SToby Isaac   PetscInt       *points;
1665c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
1666c58f1c22SToby Isaac   PetscErrorCode  ierr;
1667c58f1c22SToby Isaac 
1668c58f1c22SToby Isaac   PetscFunctionBegin;
1669d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1670c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(label, &nV);CHKERRQ(ierr);
1671c58f1c22SToby Isaac   ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr);
1672c58f1c22SToby Isaac   ierr = ISGetIndices(vIS, &values);CHKERRQ(ierr);
1673c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
1674c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
1675c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
1676c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
1677c58f1c22SToby Isaac   }
1678c58f1c22SToby Isaac   ierr = PetscSectionCreate(PETSC_COMM_SELF, section);CHKERRQ(ierr);
1679c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*section, vS, vE);CHKERRQ(ierr);
1680c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1681c58f1c22SToby Isaac     PetscInt n;
1682c58f1c22SToby Isaac 
1683c58f1c22SToby Isaac     ierr = DMLabelGetStratumSize(label, values[v], &n);CHKERRQ(ierr);
1684c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*section, values[v], n);CHKERRQ(ierr);
1685c58f1c22SToby Isaac   }
1686c58f1c22SToby Isaac   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
1687c58f1c22SToby Isaac   ierr = PetscSectionGetStorageSize(*section, &N);CHKERRQ(ierr);
1688c58f1c22SToby Isaac   ierr = PetscMalloc1(N, &points);CHKERRQ(ierr);
1689c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1690c58f1c22SToby Isaac     IS              is;
1691c58f1c22SToby Isaac     const PetscInt *spoints;
1692c58f1c22SToby Isaac     PetscInt        dof, off, p;
1693c58f1c22SToby Isaac 
1694c58f1c22SToby Isaac     ierr = PetscSectionGetDof(*section, values[v], &dof);CHKERRQ(ierr);
1695c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(*section, values[v], &off);CHKERRQ(ierr);
1696c58f1c22SToby Isaac     ierr = DMLabelGetStratumIS(label, values[v], &is);CHKERRQ(ierr);
1697c58f1c22SToby Isaac     ierr = ISGetIndices(is, &spoints);CHKERRQ(ierr);
1698c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
1699c58f1c22SToby Isaac     ierr = ISRestoreIndices(is, &spoints);CHKERRQ(ierr);
1700c58f1c22SToby Isaac     ierr = ISDestroy(&is);CHKERRQ(ierr);
1701c58f1c22SToby Isaac   }
1702c58f1c22SToby Isaac   ierr = ISRestoreIndices(vIS, &values);CHKERRQ(ierr);
1703c58f1c22SToby Isaac   ierr = ISDestroy(&vIS);CHKERRQ(ierr);
1704c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is);CHKERRQ(ierr);
1705c58f1c22SToby Isaac   PetscFunctionReturn(0);
1706c58f1c22SToby Isaac }
1707c58f1c22SToby Isaac 
170884f0b6dfSMatthew G. Knepley /*@
1709c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
1710c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
1711c58f1c22SToby Isaac 
17125b5e7992SMatthew G. Knepley   Collective on sf
17135b5e7992SMatthew G. Knepley 
1714c58f1c22SToby Isaac   Input Parameters:
1715c58f1c22SToby Isaac   + s - The PetscSection for the local field layout
1716c58f1c22SToby Isaac   . sf - The SF describing parallel layout of the section points
1717c58f1c22SToby Isaac   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1718c58f1c22SToby Isaac   . label - The label specifying the points
1719c58f1c22SToby Isaac   - labelValue - The label stratum specifying the points
1720c58f1c22SToby Isaac 
1721c58f1c22SToby Isaac   Output Parameter:
1722c58f1c22SToby Isaac   . gsection - The PetscSection for the global field layout
1723c58f1c22SToby Isaac 
1724c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
1725c58f1c22SToby Isaac 
1726c58f1c22SToby Isaac   Level: developer
1727c58f1c22SToby Isaac 
1728c58f1c22SToby Isaac .seealso: PetscSectionCreate()
1729c58f1c22SToby Isaac @*/
1730c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
1731c58f1c22SToby Isaac {
1732c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
1733c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
1734c58f1c22SToby Isaac   PetscErrorCode ierr;
1735c58f1c22SToby Isaac 
1736c58f1c22SToby Isaac   PetscFunctionBegin;
1737d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1738d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1739d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
1740c58f1c22SToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
1741c58f1c22SToby Isaac   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1742c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
1743c58f1c22SToby Isaac   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
1744c58f1c22SToby Isaac   if (nroots >= 0) {
1745c58f1c22SToby Isaac     if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
1746c58f1c22SToby Isaac     ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr);
1747c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1748c58f1c22SToby Isaac       ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr);
1749c58f1c22SToby Isaac     } else {
1750c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
1751c58f1c22SToby Isaac     }
1752c58f1c22SToby Isaac   }
1753c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
1754c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
1755c58f1c22SToby Isaac     PetscInt value;
1756c58f1c22SToby Isaac 
1757c58f1c22SToby Isaac     ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr);
1758c58f1c22SToby Isaac     if (value != labelValue) continue;
1759c58f1c22SToby Isaac     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1760c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr);
1761c58f1c22SToby Isaac     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1762c58f1c22SToby Isaac     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);}
1763c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
1764c58f1c22SToby Isaac   }
1765c58f1c22SToby Isaac   ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr);
1766c58f1c22SToby Isaac   if (nroots >= 0) {
1767c58f1c22SToby Isaac     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1768c58f1c22SToby Isaac     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1769c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1770c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
1771c58f1c22SToby Isaac     }
1772c58f1c22SToby Isaac   }
1773c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
1774c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1775c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
1776c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
1777c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
1778c58f1c22SToby Isaac   }
1779c58f1c22SToby Isaac   ierr       = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr);
1780c58f1c22SToby Isaac   globalOff -= off;
1781c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1782c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
1783c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
1784c58f1c22SToby Isaac   }
1785c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
1786c58f1c22SToby Isaac   if (nroots >= 0) {
1787c58f1c22SToby Isaac     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1788c58f1c22SToby Isaac     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1789c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1790c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
1791c58f1c22SToby Isaac     }
1792c58f1c22SToby Isaac   }
1793c58f1c22SToby Isaac   if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);}
1794c58f1c22SToby Isaac   ierr = PetscFree(neg);CHKERRQ(ierr);
1795c58f1c22SToby Isaac   PetscFunctionReturn(0);
1796c58f1c22SToby Isaac }
1797c58f1c22SToby Isaac 
17985fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
17995fdea053SToby Isaac {
18005fdea053SToby Isaac   DMLabel           label;
18015fdea053SToby Isaac   PetscCopyMode     *modes;
18025fdea053SToby Isaac   PetscInt          *sizes;
18035fdea053SToby Isaac   const PetscInt    ***perms;
18045fdea053SToby Isaac   const PetscScalar ***rots;
18055fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
18065fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
18075fdea053SToby Isaac } PetscSectionSym_Label;
18085fdea053SToby Isaac 
18095fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
18105fdea053SToby Isaac {
18115fdea053SToby Isaac   PetscInt              i, j;
18125fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
18135fdea053SToby Isaac   PetscErrorCode        ierr;
18145fdea053SToby Isaac 
18155fdea053SToby Isaac   PetscFunctionBegin;
18165fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
18175fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
18185fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
18195fdea053SToby Isaac         if (sl->perms[i]) {ierr = PetscFree(sl->perms[i][j]);CHKERRQ(ierr);}
18205fdea053SToby Isaac         if (sl->rots[i]) {ierr = PetscFree(sl->rots[i][j]);CHKERRQ(ierr);}
18215fdea053SToby Isaac       }
18225fdea053SToby Isaac       if (sl->perms[i]) {
18235fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
18245fdea053SToby Isaac 
18255fdea053SToby Isaac         ierr = PetscFree(perms);CHKERRQ(ierr);
18265fdea053SToby Isaac       }
18275fdea053SToby Isaac       if (sl->rots[i]) {
18285fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
18295fdea053SToby Isaac 
18305fdea053SToby Isaac         ierr = PetscFree(rots);CHKERRQ(ierr);
18315fdea053SToby Isaac       }
18325fdea053SToby Isaac     }
18335fdea053SToby Isaac   }
18345fdea053SToby Isaac   ierr = PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients);CHKERRQ(ierr);
18355fdea053SToby Isaac   ierr = DMLabelDestroy(&sl->label);CHKERRQ(ierr);
18365fdea053SToby Isaac   sl->numStrata = 0;
18375fdea053SToby Isaac   PetscFunctionReturn(0);
18385fdea053SToby Isaac }
18395fdea053SToby Isaac 
18405fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
18415fdea053SToby Isaac {
18425fdea053SToby Isaac   PetscErrorCode ierr;
18435fdea053SToby Isaac 
18445fdea053SToby Isaac   PetscFunctionBegin;
18455fdea053SToby Isaac   ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);
18465fdea053SToby Isaac   ierr = PetscFree(sym->data);CHKERRQ(ierr);
18475fdea053SToby Isaac   PetscFunctionReturn(0);
18485fdea053SToby Isaac }
18495fdea053SToby Isaac 
18505fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
18515fdea053SToby Isaac {
18525fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
18535fdea053SToby Isaac   PetscBool             isAscii;
18545fdea053SToby Isaac   DMLabel               label = sl->label;
1855d67d17b1SMatthew G. Knepley   const char           *name;
18565fdea053SToby Isaac   PetscErrorCode        ierr;
18575fdea053SToby Isaac 
18585fdea053SToby Isaac   PetscFunctionBegin;
18595fdea053SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii);CHKERRQ(ierr);
18605fdea053SToby Isaac   if (isAscii) {
18615fdea053SToby Isaac     PetscInt          i, j, k;
18625fdea053SToby Isaac     PetscViewerFormat format;
18635fdea053SToby Isaac 
18645fdea053SToby Isaac     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
18655fdea053SToby Isaac     if (label) {
18665fdea053SToby Isaac       ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
18675fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
18685fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
18695fdea053SToby Isaac         ierr = DMLabelView(label, viewer);CHKERRQ(ierr);
18705fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
18715fdea053SToby Isaac       } else {
1872d67d17b1SMatthew G. Knepley         ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
1873d67d17b1SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name);CHKERRQ(ierr);
18745fdea053SToby Isaac       }
18755fdea053SToby Isaac     } else {
18765fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "No label given\n");CHKERRQ(ierr);
18775fdea053SToby Isaac     }
18785fdea053SToby Isaac     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
18795fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
18805fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
18815fdea053SToby Isaac 
18825fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
18835fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point): no symmetries\n", value, sl->sizes[i]);CHKERRQ(ierr);
18845fdea053SToby Isaac       } else {
18855fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point):\n", value, sl->sizes[i]);CHKERRQ(ierr);
18865fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
18875fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Orientation range: [%D, %D)\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]);CHKERRQ(ierr);
18885fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
18895fdea053SToby Isaac           ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
18905fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
18915fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
18925fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D: identity\n",j);CHKERRQ(ierr);
18935fdea053SToby Isaac             } else {
18945fdea053SToby Isaac               PetscInt tab;
18955fdea053SToby Isaac 
18965fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D:\n",j);CHKERRQ(ierr);
18975fdea053SToby Isaac               ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
18985fdea053SToby Isaac               ierr = PetscViewerASCIIGetTab(viewer,&tab);CHKERRQ(ierr);
18995fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
19005fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Permutation:");CHKERRQ(ierr);
19015fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
19025fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %D",sl->perms[i][j][k]);CHKERRQ(ierr);}
19035fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
19045fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
19055fdea053SToby Isaac               }
19065fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
19075fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Rotations:  ");CHKERRQ(ierr);
19085fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
19095fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
19105fdea053SToby 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);}
19115fdea053SToby Isaac #else
19125fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f",sl->rots[i][j][k]);CHKERRQ(ierr);}
19135fdea053SToby Isaac #endif
19145fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
19155fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
19165fdea053SToby Isaac               }
19175fdea053SToby Isaac               ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19185fdea053SToby Isaac             }
19195fdea053SToby Isaac           }
19205fdea053SToby Isaac           ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19215fdea053SToby Isaac         }
19225fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19235fdea053SToby Isaac       }
19245fdea053SToby Isaac     }
19255fdea053SToby Isaac     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
19265fdea053SToby Isaac   }
19275fdea053SToby Isaac   PetscFunctionReturn(0);
19285fdea053SToby Isaac }
19295fdea053SToby Isaac 
19305fdea053SToby Isaac /*@
19315fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
19325fdea053SToby Isaac 
19335fdea053SToby Isaac   Logically collective on sym
19345fdea053SToby Isaac 
19355fdea053SToby Isaac   Input parameters:
19365fdea053SToby Isaac + sym - the section symmetries
19375fdea053SToby Isaac - label - the DMLabel describing the types of points
19385fdea053SToby Isaac 
19395fdea053SToby Isaac   Level: developer:
19405fdea053SToby Isaac 
19415fdea053SToby Isaac .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreateLabel(), PetscSectionGetPointSyms()
19425fdea053SToby Isaac @*/
19435fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
19445fdea053SToby Isaac {
19455fdea053SToby Isaac   PetscSectionSym_Label *sl;
19465fdea053SToby Isaac   PetscErrorCode        ierr;
19475fdea053SToby Isaac 
19485fdea053SToby Isaac   PetscFunctionBegin;
19495fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
19505fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
19515fdea053SToby Isaac   if (sl->label && sl->label != label) {ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);}
19525fdea053SToby Isaac   if (label) {
19535fdea053SToby Isaac     sl->label = label;
1954d67d17b1SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
19555fdea053SToby Isaac     ierr = DMLabelGetNumValues(label,&sl->numStrata);CHKERRQ(ierr);
19561a834cf9SToby 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);
19571a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode));CHKERRQ(ierr);
19581a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt));CHKERRQ(ierr);
19591a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **));CHKERRQ(ierr);
19601a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **));CHKERRQ(ierr);
19611a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2]));CHKERRQ(ierr);
19625fdea053SToby Isaac   }
19635fdea053SToby Isaac   PetscFunctionReturn(0);
19645fdea053SToby Isaac }
19655fdea053SToby Isaac 
19665fdea053SToby Isaac /*@C
19675fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
19685fdea053SToby Isaac 
19695b5e7992SMatthew G. Knepley   Logically collective on sym
19705fdea053SToby Isaac 
19715fdea053SToby Isaac   InputParameters:
19725b5e7992SMatthew G. Knepley + sym       - the section symmetries
19735fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
19745fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
19755fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
19765fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
19775fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
19785fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
1979a2b725a8SWilliam 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
19805fdea053SToby Isaac 
19815fdea053SToby Isaac   Level: developer
19825fdea053SToby Isaac 
19835fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
19845fdea053SToby Isaac @*/
19855fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
19865fdea053SToby Isaac {
19875fdea053SToby Isaac   PetscSectionSym_Label *sl;
1988d67d17b1SMatthew G. Knepley   const char            *name;
1989d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
19905fdea053SToby Isaac   PetscErrorCode         ierr;
19915fdea053SToby Isaac 
19925fdea053SToby Isaac   PetscFunctionBegin;
19935fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
19945fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
19955fdea053SToby Isaac   if (!sl->label) SETERRQ(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_WRONGSTATE,"No label set yet");
19965fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
19975fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
19985fdea053SToby Isaac 
19995fdea053SToby Isaac     if (stratum == value) break;
20005fdea053SToby Isaac   }
2001d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
2002d67d17b1SMatthew G. Knepley   if (i > sl->numStrata) SETERRQ2(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_OUTOFRANGE,"Stratum %D not found in label %s\n",stratum,name);
20035fdea053SToby Isaac   sl->sizes[i] = size;
20045fdea053SToby Isaac   sl->modes[i] = mode;
20055fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
20065fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
20075fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
20085fdea053SToby Isaac     if (perms) {
20095fdea053SToby Isaac       PetscInt    **ownPerms;
20105fdea053SToby Isaac 
20115fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownPerms);CHKERRQ(ierr);
20125fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
20135fdea053SToby Isaac         if (perms[j]) {
20145fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownPerms[j]);CHKERRQ(ierr);
20155fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
20165fdea053SToby Isaac         }
20175fdea053SToby Isaac       }
20185fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
20195fdea053SToby Isaac     }
20205fdea053SToby Isaac     if (rots) {
20215fdea053SToby Isaac       PetscScalar **ownRots;
20225fdea053SToby Isaac 
20235fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownRots);CHKERRQ(ierr);
20245fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
20255fdea053SToby Isaac         if (rots[j]) {
20265fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownRots[j]);CHKERRQ(ierr);
20275fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
20285fdea053SToby Isaac         }
20295fdea053SToby Isaac       }
20305fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
20315fdea053SToby Isaac     }
20325fdea053SToby Isaac   } else {
20335fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
20345fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
20355fdea053SToby Isaac   }
20365fdea053SToby Isaac   PetscFunctionReturn(0);
20375fdea053SToby Isaac }
20385fdea053SToby Isaac 
20395fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
20405fdea053SToby Isaac {
20415fdea053SToby Isaac   PetscInt              i, j, numStrata;
20425fdea053SToby Isaac   PetscSectionSym_Label *sl;
20435fdea053SToby Isaac   DMLabel               label;
20445fdea053SToby Isaac   PetscErrorCode        ierr;
20455fdea053SToby Isaac 
20465fdea053SToby Isaac   PetscFunctionBegin;
20475fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
20485fdea053SToby Isaac   numStrata = sl->numStrata;
20495fdea053SToby Isaac   label     = sl->label;
20505fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
20515fdea053SToby Isaac     PetscInt point = points[2*i];
20525fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
20535fdea053SToby Isaac 
20545fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
20555fdea053SToby Isaac       if (label->validIS[j]) {
20565fdea053SToby Isaac         PetscInt k;
20575fdea053SToby Isaac 
20585fdea053SToby Isaac         ierr = ISLocate(label->points[j],point,&k);CHKERRQ(ierr);
20595fdea053SToby Isaac         if (k >= 0) break;
20605fdea053SToby Isaac       } else {
20615fdea053SToby Isaac         PetscBool has;
20625fdea053SToby Isaac 
2063b9907514SLisandro Dalcin         ierr = PetscHSetIHas(label->ht[j], point, &has);CHKERRQ(ierr);
20645fdea053SToby Isaac         if (has) break;
20655fdea053SToby Isaac       }
20665fdea053SToby Isaac     }
20675fdea053SToby 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);
20685fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
20695fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
20705fdea053SToby Isaac   }
20715fdea053SToby Isaac   PetscFunctionReturn(0);
20725fdea053SToby Isaac }
20735fdea053SToby Isaac 
20745fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
20755fdea053SToby Isaac {
20765fdea053SToby Isaac   PetscSectionSym_Label *sl;
20775fdea053SToby Isaac   PetscErrorCode        ierr;
20785fdea053SToby Isaac 
20795fdea053SToby Isaac   PetscFunctionBegin;
20805fdea053SToby Isaac   ierr = PetscNewLog(sym,&sl);CHKERRQ(ierr);
20815fdea053SToby Isaac   sym->ops->getpoints = PetscSectionSymGetPoints_Label;
20825fdea053SToby Isaac   sym->ops->view      = PetscSectionSymView_Label;
20835fdea053SToby Isaac   sym->ops->destroy   = PetscSectionSymDestroy_Label;
20845fdea053SToby Isaac   sym->data           = (void *) sl;
20855fdea053SToby Isaac   PetscFunctionReturn(0);
20865fdea053SToby Isaac }
20875fdea053SToby Isaac 
20885fdea053SToby Isaac /*@
20895fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
20905fdea053SToby Isaac 
20915fdea053SToby Isaac   Collective
20925fdea053SToby Isaac 
20935fdea053SToby Isaac   Input Parameters:
20945fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
20955fdea053SToby Isaac - label - the label defining the strata
20965fdea053SToby Isaac 
20975fdea053SToby Isaac   Output Parameters:
20985fdea053SToby Isaac . sym - the section symmetries
20995fdea053SToby Isaac 
21005fdea053SToby Isaac   Level: developer
21015fdea053SToby Isaac 
21025fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms()
21035fdea053SToby Isaac @*/
21045fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
21055fdea053SToby Isaac {
21065fdea053SToby Isaac   PetscErrorCode        ierr;
21075fdea053SToby Isaac 
21085fdea053SToby Isaac   PetscFunctionBegin;
21095fdea053SToby Isaac   ierr = DMInitializePackage();CHKERRQ(ierr);
21105fdea053SToby Isaac   ierr = PetscSectionSymCreate(comm,sym);CHKERRQ(ierr);
21115fdea053SToby Isaac   ierr = PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL);CHKERRQ(ierr);
21125fdea053SToby Isaac   ierr = PetscSectionSymLabelSetLabel(*sym,label);CHKERRQ(ierr);
21135fdea053SToby Isaac   PetscFunctionReturn(0);
21145fdea053SToby Isaac }
2115