xref: /petsc/src/dm/label/dmlabel.c (revision 5b5e7992d5efec238a29384b748c0a1490060955)
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 
9*5b5e7992SMatthew G. Knepley   Collective
10*5b5e7992SMatthew 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 
50*5b5e7992SMatthew G. Knepley   Not collective
51*5b5e7992SMatthew 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 
95*5b5e7992SMatthew G. Knepley   Not collective
96*5b5e7992SMatthew 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 
122*5b5e7992SMatthew G. Knepley   Not collective
123*5b5e7992SMatthew 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);
2198e1f8cf0SLisandro Dalcin     ierr = PetscMemcpy(tmpV, oldV, v*sizeof(*tmpV));CHKERRQ(ierr);
2208e1f8cf0SLisandro Dalcin     ierr = PetscMemcpy(tmpS, oldS, v*sizeof(*tmpS));CHKERRQ(ierr);
2218e1f8cf0SLisandro Dalcin     ierr = PetscMemcpy(tmpH, oldH, v*sizeof(*tmpH));CHKERRQ(ierr);
2228e1f8cf0SLisandro Dalcin     ierr = PetscMemcpy(tmpP, oldP, v*sizeof(*tmpP));CHKERRQ(ierr);
2238e1f8cf0SLisandro Dalcin     ierr = PetscMemcpy(tmpB, oldB, v*sizeof(*tmpB));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 
283*5b5e7992SMatthew G. Knepley   Not collective
284*5b5e7992SMatthew 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);
303b9907514SLisandro Dalcin   ierr = PetscMemcpy(values, stratumValues, numStrata*sizeof(PetscInt));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 
347*5b5e7992SMatthew G. Knepley   Not collective
348*5b5e7992SMatthew 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 
407*5b5e7992SMatthew G. Knepley   Collective on viewer
408*5b5e7992SMatthew 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 
437*5b5e7992SMatthew G. Knepley   Not collective
438*5b5e7992SMatthew 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 
473*5b5e7992SMatthew G. Knepley   Collective on label
474*5b5e7992SMatthew 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 
499*5b5e7992SMatthew G. Knepley   Collective on label
500*5b5e7992SMatthew 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 
549*5b5e7992SMatthew G. Knepley   Not collective
550*5b5e7992SMatthew 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 
588*5b5e7992SMatthew G. Knepley   Not collective
589*5b5e7992SMatthew 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 
631*5b5e7992SMatthew G. Knepley   Not collective
632*5b5e7992SMatthew 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 
655*5b5e7992SMatthew G. Knepley   Not collective
656*5b5e7992SMatthew 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) {
678c6a43d28SMatthew G. Knepley     PetscValidPointer(pStart, 2);
679c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
680c6a43d28SMatthew G. Knepley   }
681c6a43d28SMatthew G. Knepley   if (pEnd) {
682c6a43d28SMatthew G. Knepley     PetscValidPointer(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 
691*5b5e7992SMatthew G. Knepley   Not collective
692*5b5e7992SMatthew 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);
711c58f1c22SToby Isaac   PetscValidPointer(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 
720*5b5e7992SMatthew G. Knepley   Not collective
721*5b5e7992SMatthew 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);
741c58f1c22SToby Isaac   PetscValidPointer(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 
754*5b5e7992SMatthew G. Knepley   Not collective
755*5b5e7992SMatthew 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);
775c58f1c22SToby Isaac   PetscValidPointer(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 
798*5b5e7992SMatthew G. Knepley   Not collective
799*5b5e7992SMatthew 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 
822*5b5e7992SMatthew G. Knepley   Not collective
823*5b5e7992SMatthew 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 
845*5b5e7992SMatthew G. Knepley   Not collective
846*5b5e7992SMatthew 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 
892*5b5e7992SMatthew G. Knepley   Not collective
893*5b5e7992SMatthew 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 
922*5b5e7992SMatthew G. Knepley   Not collective
923*5b5e7992SMatthew 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 
958*5b5e7992SMatthew G. Knepley   Not collective
959*5b5e7992SMatthew 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 
993*5b5e7992SMatthew G. Knepley   Not collective
994*5b5e7992SMatthew 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 
1017*5b5e7992SMatthew G. Knepley   Not collective
1018*5b5e7992SMatthew 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 
1043*5b5e7992SMatthew G. Knepley   Not collective
1044*5b5e7992SMatthew 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 
1072*5b5e7992SMatthew G. Knepley   Not collective
1073*5b5e7992SMatthew 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 
1104*5b5e7992SMatthew G. Knepley   Not collective
1105*5b5e7992SMatthew 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 
1140*5b5e7992SMatthew G. Knepley   Not collective
1141*5b5e7992SMatthew 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 
1173*5b5e7992SMatthew G. Knepley   Not collective
1174*5b5e7992SMatthew 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 
1219*5b5e7992SMatthew G. Knepley   Not collective
1220*5b5e7992SMatthew 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 
1266*5b5e7992SMatthew G. Knepley   Not collective
1267*5b5e7992SMatthew 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 
1314*5b5e7992SMatthew G. Knepley   Not collective
1315*5b5e7992SMatthew 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 
1441*5b5e7992SMatthew G. Knepley   Collective on sf
1442*5b5e7992SMatthew 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);
1485d67d17b1SMatthew G. Knepley   if (!rank) {ierr = PetscMemcpy(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 
1557*5b5e7992SMatthew G. Knepley   Collective on sf
1558*5b5e7992SMatthew 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);
1602d67d17b1SMatthew G. Knepley   if (!rank) {ierr = PetscMemcpy(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 
1647*5b5e7992SMatthew G. Knepley   Not collective
1648*5b5e7992SMatthew 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 
1712*5b5e7992SMatthew G. Knepley   Collective on sf
1713*5b5e7992SMatthew 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 
1969*5b5e7992SMatthew G. Knepley   Logically collective on sym
19705fdea053SToby Isaac 
19715fdea053SToby Isaac   InputParameters:
1972*5b5e7992SMatthew 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
19795fdea053SToby Isaac + 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