xref: /petsc/src/dm/label/dmlabel.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h>   /*I      "petscdmlabel.h"   I*/
3ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h>   /*I      "petscsection.h"   I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5ea844a1aSMatthew Knepley #include <petscsection.h>
6c58f1c22SToby Isaac 
7c58f1c22SToby Isaac /*@C
8c58f1c22SToby Isaac   DMLabelCreate - Create a DMLabel object, which is a multimap
9c58f1c22SToby Isaac 
105b5e7992SMatthew G. Knepley   Collective
115b5e7992SMatthew G. Knepley 
12d67d17b1SMatthew G. Knepley   Input parameters:
13d67d17b1SMatthew G. Knepley + comm - The communicator, usually PETSC_COMM_SELF
14d67d17b1SMatthew G. Knepley - name - The label name
15c58f1c22SToby Isaac 
16c58f1c22SToby Isaac   Output parameter:
17c58f1c22SToby Isaac . label - The DMLabel
18c58f1c22SToby Isaac 
19c58f1c22SToby Isaac   Level: beginner
20c58f1c22SToby Isaac 
2105ab7a9fSVaclav Hapla   Notes:
2205ab7a9fSVaclav Hapla   The label name is actually usual PetscObject name.
2305ab7a9fSVaclav Hapla   One can get/set it with PetscObjectGetName()/PetscObjectSetName().
2405ab7a9fSVaclav Hapla 
25c58f1c22SToby Isaac .seealso: DMLabelDestroy()
26c58f1c22SToby Isaac @*/
27d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
28c58f1c22SToby Isaac {
29c58f1c22SToby Isaac   PetscFunctionBegin;
30064a246eSJacob Faibussowitsch   PetscValidPointer(label,3);
315f80ce2aSJacob Faibussowitsch   CHKERRQ(DMInitializePackage());
32c58f1c22SToby Isaac 
335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHeaderCreate(*label,DMLABEL_CLASSID,"DMLabel","DMLabel","DM",comm,DMLabelDestroy,DMLabelView));
34d67d17b1SMatthew G. Knepley 
35c58f1c22SToby Isaac   (*label)->numStrata      = 0;
365aa44df4SToby Isaac   (*label)->defaultValue   = -1;
37c58f1c22SToby Isaac   (*label)->stratumValues  = NULL;
38ad8374ffSToby Isaac   (*label)->validIS        = NULL;
39c58f1c22SToby Isaac   (*label)->stratumSizes   = NULL;
40c58f1c22SToby Isaac   (*label)->points         = NULL;
41c58f1c22SToby Isaac   (*label)->ht             = NULL;
42c58f1c22SToby Isaac   (*label)->pStart         = -1;
43c58f1c22SToby Isaac   (*label)->pEnd           = -1;
44c58f1c22SToby Isaac   (*label)->bt             = NULL;
455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapICreate(&(*label)->hmap));
465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *label, name));
47c58f1c22SToby Isaac   PetscFunctionReturn(0);
48c58f1c22SToby Isaac }
49c58f1c22SToby Isaac 
50c58f1c22SToby Isaac /*
51c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
52c58f1c22SToby Isaac 
535b5e7992SMatthew G. Knepley   Not collective
545b5e7992SMatthew G. Knepley 
55c58f1c22SToby Isaac   Input parameter:
56c58f1c22SToby Isaac + label - The DMLabel
57c58f1c22SToby Isaac - v - The stratum value
58c58f1c22SToby Isaac 
59c58f1c22SToby Isaac   Output parameter:
60c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
61c58f1c22SToby Isaac 
62c58f1c22SToby Isaac   Level: developer
63c58f1c22SToby Isaac 
64c58f1c22SToby Isaac .seealso: DMLabelCreate()
65c58f1c22SToby Isaac */
66c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
67c58f1c22SToby Isaac {
68277ea44aSLisandro Dalcin   IS             is;
69b9907514SLisandro Dalcin   PetscInt       off = 0, *pointArray, p;
70c58f1c22SToby Isaac 
71b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
72c58f1c22SToby Isaac   PetscFunctionBegin;
732c71b3e2SJacob Faibussowitsch   PetscCheckFalse(v < 0 || v >= label->numStrata,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeValid_Private", v);
745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]));
755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(label->stratumSizes[v], &pointArray));
765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIGetElems(label->ht[v], &off, pointArray));
775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIClear(label->ht[v]));
785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortInt(label->stratumSizes[v], pointArray));
79c58f1c22SToby Isaac   if (label->bt) {
80c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
81ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
822c71b3e2SJacob Faibussowitsch       PetscCheckFalse((point < label->pStart) || (point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
835f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscBTSet(label->bt, point - label->pStart));
84c58f1c22SToby Isaac     }
85c58f1c22SToby Isaac   }
86ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v]-1] == pointArray[0] + label->stratumSizes[v]-1) {
875f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is));
885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(pointArray));
89ba2698f1SMatthew G. Knepley   } else {
905f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is));
91ba2698f1SMatthew G. Knepley   }
925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) is, "indices"));
93277ea44aSLisandro Dalcin   label->points[v]  = is;
94ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateIncrease((PetscObject) label));
96c58f1c22SToby Isaac   PetscFunctionReturn(0);
97c58f1c22SToby Isaac }
98c58f1c22SToby Isaac 
99c58f1c22SToby Isaac /*
100c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
101c58f1c22SToby Isaac 
1025b5e7992SMatthew G. Knepley   Not collective
1035b5e7992SMatthew G. Knepley 
104c58f1c22SToby Isaac   Input parameter:
105c58f1c22SToby Isaac . label - The DMLabel
106c58f1c22SToby Isaac 
107c58f1c22SToby Isaac   Output parameter:
108c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
109c58f1c22SToby Isaac 
110c58f1c22SToby Isaac   Level: developer
111c58f1c22SToby Isaac 
112c58f1c22SToby Isaac .seealso: DMLabelCreate()
113c58f1c22SToby Isaac */
114c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
115c58f1c22SToby Isaac {
116c58f1c22SToby Isaac   PetscInt       v;
117c58f1c22SToby Isaac 
118c58f1c22SToby Isaac   PetscFunctionBegin;
119c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; v++) {
1205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelMakeValid_Private(label, v));
121c58f1c22SToby Isaac   }
122c58f1c22SToby Isaac   PetscFunctionReturn(0);
123c58f1c22SToby Isaac }
124c58f1c22SToby Isaac 
125c58f1c22SToby Isaac /*
126c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
127c58f1c22SToby Isaac 
1285b5e7992SMatthew G. Knepley   Not collective
1295b5e7992SMatthew G. Knepley 
130c58f1c22SToby Isaac   Input parameter:
131c58f1c22SToby Isaac + label - The DMLabel
132c58f1c22SToby Isaac - v - The stratum value
133c58f1c22SToby Isaac 
134c58f1c22SToby Isaac   Output parameter:
135c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
136c58f1c22SToby Isaac 
137c58f1c22SToby Isaac   Level: developer
138c58f1c22SToby Isaac 
139c58f1c22SToby Isaac .seealso: DMLabelCreate()
140c58f1c22SToby Isaac */
141c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
142c58f1c22SToby Isaac {
143c58f1c22SToby Isaac   PetscInt       p;
144ad8374ffSToby Isaac   const PetscInt *points;
145c58f1c22SToby Isaac 
146b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
147c58f1c22SToby Isaac   PetscFunctionBegin;
1482c71b3e2SJacob Faibussowitsch   PetscCheckFalse(v < 0 || v >= label->numStrata,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeInvalid_Private", v);
149ad8374ffSToby Isaac   if (label->points[v]) {
1505f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(label->points[v], &points));
151e8f14785SLisandro Dalcin     for (p = 0; p < label->stratumSizes[v]; ++p) {
1525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHSetIAdd(label->ht[v], points[p]));
153e8f14785SLisandro Dalcin     }
1545f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(label->points[v],&points));
1555f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&(label->points[v])));
156ad8374ffSToby Isaac   }
157ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
158c58f1c22SToby Isaac   PetscFunctionReturn(0);
159c58f1c22SToby Isaac }
160c58f1c22SToby Isaac 
161b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
162b9907514SLisandro Dalcin #define DMLABEL_LOOKUP_THRESHOLD 16
163b9907514SLisandro Dalcin #endif
164b9907514SLisandro Dalcin 
1659fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
1660c3c4a36SLisandro Dalcin {
1670c3c4a36SLisandro Dalcin   PetscInt       v;
1680e79e033SBarry Smith 
1690c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1700e79e033SBarry Smith   *index = -1;
171b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
172b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
173b9907514SLisandro Dalcin       if (label->stratumValues[v] == value) {*index = v; break;}
174b9907514SLisandro Dalcin   } else {
1755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIGet(label->hmap, value, index));
1760e79e033SBarry Smith   }
17776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */
17890e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
1795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapIGetSize(label->hmap, &len));
1802c71b3e2SJacob Faibussowitsch     PetscCheckFalse(len != label->numStrata,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
18190e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
1825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHMapIGet(label->hmap, value, &loc));
18390e9b2aeSLisandro Dalcin     } else {
18490e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
18590e9b2aeSLisandro Dalcin         if (label->stratumValues[v] == value) {loc = v; break;}
18690e9b2aeSLisandro Dalcin     }
1872c71b3e2SJacob Faibussowitsch     PetscCheckFalse(loc != *index,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
18890e9b2aeSLisandro Dalcin   }
1890c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
1900c3c4a36SLisandro Dalcin }
1910c3c4a36SLisandro Dalcin 
1929fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
193c58f1c22SToby Isaac {
194b9907514SLisandro Dalcin   PetscInt       v;
195b9907514SLisandro Dalcin   PetscInt      *tmpV;
196b9907514SLisandro Dalcin   PetscInt      *tmpS;
197b9907514SLisandro Dalcin   PetscHSetI    *tmpH, ht;
198b9907514SLisandro Dalcin   IS            *tmpP, is;
199c58f1c22SToby Isaac   PetscBool     *tmpB;
200b9907514SLisandro Dalcin   PetscHMapI     hmap = label->hmap;
201c58f1c22SToby Isaac 
202c58f1c22SToby Isaac   PetscFunctionBegin;
203b9907514SLisandro Dalcin   v    = label->numStrata;
204b9907514SLisandro Dalcin   tmpV = label->stratumValues;
205b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
206b9907514SLisandro Dalcin   tmpH = label->ht;
207b9907514SLisandro Dalcin   tmpP = label->points;
208b9907514SLisandro Dalcin   tmpB = label->validIS;
2098e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2108e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2118e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2128e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2138e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2148e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc((v+1)*sizeof(*tmpV), &tmpV));
2165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc((v+1)*sizeof(*tmpS), &tmpS));
2175f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc((v+1)*sizeof(*tmpH), &tmpH));
2185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc((v+1)*sizeof(*tmpP), &tmpP));
2195f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc((v+1)*sizeof(*tmpB), &tmpB));
2205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(tmpV, oldV, v));
2215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(tmpS, oldS, v));
2225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(tmpH, oldH, v));
2235f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(tmpP, oldP, v));
2245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(tmpB, oldB, v));
2255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(oldV));
2265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(oldS));
2275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(oldH));
2285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(oldP));
2295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(oldB));
2308e1f8cf0SLisandro Dalcin   }
231b9907514SLisandro Dalcin   label->numStrata     = v+1;
232c58f1c22SToby Isaac   label->stratumValues = tmpV;
233c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
234c58f1c22SToby Isaac   label->ht            = tmpH;
235c58f1c22SToby Isaac   label->points        = tmpP;
236ad8374ffSToby Isaac   label->validIS       = tmpB;
2375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetICreate(&ht));
2385f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateStride(PETSC_COMM_SELF,0,0,1,&is));
2395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapISet(hmap, value, v));
240b9907514SLisandro Dalcin   tmpV[v] = value;
241b9907514SLisandro Dalcin   tmpS[v] = 0;
242b9907514SLisandro Dalcin   tmpH[v] = ht;
243b9907514SLisandro Dalcin   tmpP[v] = is;
244b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
2455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateIncrease((PetscObject) label));
2460c3c4a36SLisandro Dalcin   *index = v;
2470c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2480c3c4a36SLisandro Dalcin }
2490c3c4a36SLisandro Dalcin 
2509fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
251b9907514SLisandro Dalcin {
252b9907514SLisandro Dalcin   PetscFunctionBegin;
2535f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, index));
2545f80ce2aSJacob Faibussowitsch   if (*index < 0) CHKERRQ(DMLabelNewStratum(label, value, index));
255b9907514SLisandro Dalcin   PetscFunctionReturn(0);
256b9907514SLisandro Dalcin }
257b9907514SLisandro Dalcin 
2589fbee547SJacob Faibussowitsch static inline PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
2599e63cc69SVaclav Hapla {
2609e63cc69SVaclav Hapla   PetscFunctionBegin;
2619e63cc69SVaclav Hapla   *size = 0;
2629e63cc69SVaclav Hapla   if (v < 0) PetscFunctionReturn(0);
2639e63cc69SVaclav Hapla   if (label->validIS[v]) {
2649e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
2659e63cc69SVaclav Hapla   } else {
2665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIGetSize(label->ht[v], size));
2679e63cc69SVaclav Hapla   }
2689e63cc69SVaclav Hapla   PetscFunctionReturn(0);
2699e63cc69SVaclav Hapla }
2709e63cc69SVaclav Hapla 
271b9907514SLisandro Dalcin /*@
272b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
273b9907514SLisandro Dalcin 
274d8d19677SJose E. Roman   Input Parameters:
275b9907514SLisandro Dalcin + label - The DMLabel
276b9907514SLisandro Dalcin - value - The stratum value
277b9907514SLisandro Dalcin 
278b9907514SLisandro Dalcin   Level: beginner
279b9907514SLisandro Dalcin 
280b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
281b9907514SLisandro Dalcin @*/
2820c3c4a36SLisandro Dalcin PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
2830c3c4a36SLisandro Dalcin {
2840c3c4a36SLisandro Dalcin   PetscInt       v;
2850c3c4a36SLisandro Dalcin 
2860c3c4a36SLisandro Dalcin   PetscFunctionBegin;
287d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
2885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupAddStratum(label, value, &v));
289b9907514SLisandro Dalcin   PetscFunctionReturn(0);
290b9907514SLisandro Dalcin }
291b9907514SLisandro Dalcin 
292b9907514SLisandro Dalcin /*@
293b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
294b9907514SLisandro Dalcin 
2955b5e7992SMatthew G. Knepley   Not collective
2965b5e7992SMatthew G. Knepley 
297d8d19677SJose E. Roman   Input Parameters:
298b9907514SLisandro Dalcin + label - The DMLabel
299b9907514SLisandro Dalcin . numStrata - The number of stratum values
300b9907514SLisandro Dalcin - stratumValues - The stratum values
301b9907514SLisandro Dalcin 
302b9907514SLisandro Dalcin   Level: beginner
303b9907514SLisandro Dalcin 
304b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
305b9907514SLisandro Dalcin @*/
306b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
307b9907514SLisandro Dalcin {
308b9907514SLisandro Dalcin   PetscInt       *values, v;
309b9907514SLisandro Dalcin 
310b9907514SLisandro Dalcin   PetscFunctionBegin;
311b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
312b9907514SLisandro Dalcin   if (numStrata) PetscValidIntPointer(stratumValues, 3);
3135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(numStrata, &values));
3145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(values, stratumValues, numStrata));
3155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortRemoveDupsInt(&numStrata, values));
316b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
317b9907514SLisandro Dalcin     PetscInt   *tmpV;
318b9907514SLisandro Dalcin     PetscInt   *tmpS;
319b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
320b9907514SLisandro Dalcin     IS         *tmpP, is;
321b9907514SLisandro Dalcin     PetscBool  *tmpB;
322b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
323b9907514SLisandro Dalcin 
3245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numStrata, &tmpV));
3255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numStrata, &tmpS));
3265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numStrata, &tmpH));
3275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numStrata, &tmpP));
3285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numStrata, &tmpB));
329b9907514SLisandro Dalcin     label->numStrata     = numStrata;
330b9907514SLisandro Dalcin     label->stratumValues = tmpV;
331b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
332b9907514SLisandro Dalcin     label->ht            = tmpH;
333b9907514SLisandro Dalcin     label->points        = tmpP;
334b9907514SLisandro Dalcin     label->validIS       = tmpB;
335b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3365f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHSetICreate(&ht));
3375f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(PETSC_COMM_SELF,0,0,1,&is));
3385f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHMapISet(hmap, values[v], v));
339b9907514SLisandro Dalcin       tmpV[v] = values[v];
340b9907514SLisandro Dalcin       tmpS[v] = 0;
341b9907514SLisandro Dalcin       tmpH[v] = ht;
342b9907514SLisandro Dalcin       tmpP[v] = is;
343b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
344b9907514SLisandro Dalcin     }
3455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectStateIncrease((PetscObject) label));
346b9907514SLisandro Dalcin   } else {
347b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
3485f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelAddStratum(label, values[v]));
349b9907514SLisandro Dalcin     }
350b9907514SLisandro Dalcin   }
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(values));
352b9907514SLisandro Dalcin   PetscFunctionReturn(0);
353b9907514SLisandro Dalcin }
354b9907514SLisandro Dalcin 
355b9907514SLisandro Dalcin /*@
356b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
357b9907514SLisandro Dalcin 
3585b5e7992SMatthew G. Knepley   Not collective
3595b5e7992SMatthew G. Knepley 
360d8d19677SJose E. Roman   Input Parameters:
361b9907514SLisandro Dalcin + label - The DMLabel
362b9907514SLisandro Dalcin - valueIS - Index set with stratum values
363b9907514SLisandro Dalcin 
364b9907514SLisandro Dalcin   Level: beginner
365b9907514SLisandro Dalcin 
366b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
367b9907514SLisandro Dalcin @*/
368b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
369b9907514SLisandro Dalcin {
370b9907514SLisandro Dalcin   PetscInt       numStrata;
371b9907514SLisandro Dalcin   const PetscInt *stratumValues;
372b9907514SLisandro Dalcin 
373b9907514SLisandro Dalcin   PetscFunctionBegin;
374b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
375b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
3765f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(valueIS, &numStrata));
3775f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(valueIS, &stratumValues));
3785f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelAddStrata(label, numStrata, stratumValues));
379c58f1c22SToby Isaac   PetscFunctionReturn(0);
380c58f1c22SToby Isaac }
381c58f1c22SToby Isaac 
382c58f1c22SToby Isaac static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer)
383c58f1c22SToby Isaac {
384c58f1c22SToby Isaac   PetscInt       v;
385c58f1c22SToby Isaac   PetscMPIInt    rank;
386c58f1c22SToby Isaac 
387c58f1c22SToby Isaac   PetscFunctionBegin;
3885f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPushSynchronized(viewer));
390c58f1c22SToby Isaac   if (label) {
391d67d17b1SMatthew G. Knepley     const char *name;
392d67d17b1SMatthew G. Knepley 
3935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) label, &name));
3945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name));
3955f80ce2aSJacob Faibussowitsch     if (label->bt) CHKERRQ(PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%D, %D)\n", label->pStart, label->pEnd));
396c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
397c58f1c22SToby Isaac       const PetscInt value = label->stratumValues[v];
398ad8374ffSToby Isaac       const PetscInt *points;
399c58f1c22SToby Isaac       PetscInt       p;
400c58f1c22SToby Isaac 
4015f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(label->points[v], &points));
402c58f1c22SToby Isaac       for (p = 0; p < label->stratumSizes[v]; ++p) {
4035f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D (%D)\n", rank, points[p], value));
404c58f1c22SToby Isaac       }
4055f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(label->points[v],&points));
406c58f1c22SToby Isaac     }
407c58f1c22SToby Isaac   }
4085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFlush(viewer));
4095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
410c58f1c22SToby Isaac   PetscFunctionReturn(0);
411c58f1c22SToby Isaac }
412c58f1c22SToby Isaac 
413c58f1c22SToby Isaac /*@C
414c58f1c22SToby Isaac   DMLabelView - View the label
415c58f1c22SToby Isaac 
4165b5e7992SMatthew G. Knepley   Collective on viewer
4175b5e7992SMatthew G. Knepley 
418c58f1c22SToby Isaac   Input Parameters:
419c58f1c22SToby Isaac + label - The DMLabel
420c58f1c22SToby Isaac - viewer - The PetscViewer
421c58f1c22SToby Isaac 
422c58f1c22SToby Isaac   Level: intermediate
423c58f1c22SToby Isaac 
424c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelDestroy()
425c58f1c22SToby Isaac @*/
426c58f1c22SToby Isaac PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
427c58f1c22SToby Isaac {
428c58f1c22SToby Isaac   PetscBool      iascii;
429c58f1c22SToby Isaac 
430c58f1c22SToby Isaac   PetscFunctionBegin;
431d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
4325f80ce2aSJacob Faibussowitsch   if (!viewer) CHKERRQ(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer));
433c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4345f80ce2aSJacob Faibussowitsch   if (label) CHKERRQ(DMLabelMakeAllValid_Private(label));
4355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
436c58f1c22SToby Isaac   if (iascii) {
4375f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelView_Ascii(label, viewer));
438c58f1c22SToby Isaac   }
439c58f1c22SToby Isaac   PetscFunctionReturn(0);
440c58f1c22SToby Isaac }
441c58f1c22SToby Isaac 
44284f0b6dfSMatthew G. Knepley /*@
443d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
444d67d17b1SMatthew G. Knepley 
4455b5e7992SMatthew G. Knepley   Not collective
4465b5e7992SMatthew G. Knepley 
447d67d17b1SMatthew G. Knepley   Input Parameter:
448d67d17b1SMatthew G. Knepley . label - The DMLabel
449d67d17b1SMatthew G. Knepley 
450d67d17b1SMatthew G. Knepley   Level: beginner
451d67d17b1SMatthew G. Knepley 
452d67d17b1SMatthew G. Knepley .seealso: DMLabelDestroy(), DMLabelCreate()
453d67d17b1SMatthew G. Knepley @*/
454d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelReset(DMLabel label)
455d67d17b1SMatthew G. Knepley {
456d67d17b1SMatthew G. Knepley   PetscInt       v;
457d67d17b1SMatthew G. Knepley 
458d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
459d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
460d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
4615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIDestroy(&label->ht[v]));
4625f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&label->points[v]));
463d67d17b1SMatthew G. Knepley   }
464b9907514SLisandro Dalcin   label->numStrata = 0;
4655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(label->stratumValues));
4665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(label->stratumSizes));
4675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(label->ht));
4685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(label->points));
4695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(label->validIS));
470f9244615SMatthew G. Knepley   label->stratumValues = NULL;
471f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
472f9244615SMatthew G. Knepley   label->ht            = NULL;
473f9244615SMatthew G. Knepley   label->points        = NULL;
474f9244615SMatthew G. Knepley   label->validIS       = NULL;
4755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapIReset(label->hmap));
476b9907514SLisandro Dalcin   label->pStart = -1;
477b9907514SLisandro Dalcin   label->pEnd   = -1;
4785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTDestroy(&label->bt));
479d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
480d67d17b1SMatthew G. Knepley }
481d67d17b1SMatthew G. Knepley 
482d67d17b1SMatthew G. Knepley /*@
48384f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
48484f0b6dfSMatthew G. Knepley 
4855b5e7992SMatthew G. Knepley   Collective on label
4865b5e7992SMatthew G. Knepley 
48784f0b6dfSMatthew G. Knepley   Input Parameter:
48884f0b6dfSMatthew G. Knepley . label - The DMLabel
48984f0b6dfSMatthew G. Knepley 
49084f0b6dfSMatthew G. Knepley   Level: beginner
49184f0b6dfSMatthew G. Knepley 
492d67d17b1SMatthew G. Knepley .seealso: DMLabelReset(), DMLabelCreate()
49384f0b6dfSMatthew G. Knepley @*/
494c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
495c58f1c22SToby Isaac {
496c58f1c22SToby Isaac   PetscFunctionBegin;
497d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
498d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1);
499b9907514SLisandro Dalcin   if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);}
5005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelReset(*label));
5015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapIDestroy(&(*label)->hmap));
5025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHeaderDestroy(label));
503c58f1c22SToby Isaac   PetscFunctionReturn(0);
504c58f1c22SToby Isaac }
505c58f1c22SToby Isaac 
50684f0b6dfSMatthew G. Knepley /*@
50784f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
50884f0b6dfSMatthew G. Knepley 
5095b5e7992SMatthew G. Knepley   Collective on label
5105b5e7992SMatthew G. Knepley 
51184f0b6dfSMatthew G. Knepley   Input Parameter:
51284f0b6dfSMatthew G. Knepley . label - The DMLabel
51384f0b6dfSMatthew G. Knepley 
51484f0b6dfSMatthew G. Knepley   Output Parameter:
51584f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
51684f0b6dfSMatthew G. Knepley 
51784f0b6dfSMatthew G. Knepley   Level: intermediate
51884f0b6dfSMatthew G. Knepley 
51984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelDestroy()
52084f0b6dfSMatthew G. Knepley @*/
521c58f1c22SToby Isaac PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
522c58f1c22SToby Isaac {
523d67d17b1SMatthew G. Knepley   const char    *name;
524ad8374ffSToby Isaac   PetscInt       v;
525c58f1c22SToby Isaac 
526c58f1c22SToby Isaac   PetscFunctionBegin;
527d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
5285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeAllValid_Private(label));
5295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) label, &name));
5305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew));
531c58f1c22SToby Isaac 
532c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5335aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
5345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues));
5355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes));
5365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(label->numStrata, &(*labelnew)->ht));
5375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(label->numStrata, &(*labelnew)->points));
5385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(label->numStrata, &(*labelnew)->validIS));
539c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
5405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetICreate(&(*labelnew)->ht[v]));
541c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
542c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
5435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject) (label->points[v])));
544ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
545b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
546c58f1c22SToby Isaac   }
5475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapIDestroy(&(*labelnew)->hmap));
5485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap));
549c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
550c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
551c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
552c58f1c22SToby Isaac   PetscFunctionReturn(0);
553c58f1c22SToby Isaac }
554c58f1c22SToby Isaac 
555609dae6eSVaclav Hapla /*@C
556609dae6eSVaclav Hapla   DMLabelCompare - Compare two DMLabel objects
557609dae6eSVaclav Hapla 
5585efe38ccSVaclav Hapla   Collective on comm
559609dae6eSVaclav Hapla 
560609dae6eSVaclav Hapla   Input Parameters:
561f1a722f8SMatthew G. Knepley + comm - Comm over which to compare labels
562f1a722f8SMatthew G. Knepley . l0 - First DMLabel
563609dae6eSVaclav Hapla - l1 - Second DMLabel
564609dae6eSVaclav Hapla 
565609dae6eSVaclav Hapla   Output Parameters
5665efe38ccSVaclav Hapla + equal   - (Optional) Flag whether the two labels are equal
5675efe38ccSVaclav Hapla - message - (Optional) Message describing the difference
568609dae6eSVaclav Hapla 
569609dae6eSVaclav Hapla   Level: intermediate
570609dae6eSVaclav Hapla 
571609dae6eSVaclav Hapla   Notes:
5725efe38ccSVaclav Hapla   The output flag equal is the same on all processes.
5735efe38ccSVaclav Hapla   If it is passed as NULL and difference is found, an error is thrown on all processes.
5745efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
575609dae6eSVaclav Hapla 
5765efe38ccSVaclav Hapla   The output message is set independently on each rank.
5775efe38ccSVaclav Hapla   It is set to NULL if no difference was found on the current rank. It must be freed by user.
5785efe38ccSVaclav Hapla   If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner.
5795efe38ccSVaclav Hapla   Make sure to pass NULL on all processes.
580609dae6eSVaclav Hapla 
581609dae6eSVaclav Hapla   For the comparison, we ignore the order of stratum values, and strata with no points.
582609dae6eSVaclav Hapla 
5835efe38ccSVaclav Hapla   The communicator needs to be specified because currently DMLabel can live on PETSC_COMM_SELF even if the underlying DM is parallel.
5845efe38ccSVaclav Hapla 
585609dae6eSVaclav Hapla   Fortran Notes:
586609dae6eSVaclav Hapla   This function is currently not available from Fortran.
587609dae6eSVaclav Hapla 
588609dae6eSVaclav Hapla .seealso: DMCompareLabels(), DMLabelGetNumValues(), DMLabelGetDefaultValue(), DMLabelGetNonEmptyStratumValuesIS(), DMLabelGetStratumIS()
589609dae6eSVaclav Hapla @*/
5905efe38ccSVaclav Hapla PetscErrorCode DMLabelCompare(MPI_Comm comm, DMLabel l0, DMLabel l1, PetscBool *equal, char **message)
591609dae6eSVaclav Hapla {
592609dae6eSVaclav Hapla   const char     *name0, *name1;
593609dae6eSVaclav Hapla   char            msg[PETSC_MAX_PATH_LEN] = "";
5945efe38ccSVaclav Hapla   PetscBool       eq;
5955efe38ccSVaclav Hapla   PetscMPIInt     rank;
596609dae6eSVaclav Hapla 
597609dae6eSVaclav Hapla   PetscFunctionBegin;
5985efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l0, DMLABEL_CLASSID, 2);
5995efe38ccSVaclav Hapla   PetscValidHeaderSpecific(l1, DMLABEL_CLASSID, 3);
6005efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 4);
6015efe38ccSVaclav Hapla   if (message) PetscValidPointer(message, 5);
6025f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
6035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject)l0, &name0));
6045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject)l1, &name1));
605609dae6eSVaclav Hapla   {
606609dae6eSVaclav Hapla     PetscInt v0, v1;
607609dae6eSVaclav Hapla 
6085f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetDefaultValue(l0, &v0));
6095f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetDefaultValue(l1, &v1));
6105efe38ccSVaclav Hapla     eq = (PetscBool) (v0 == v1);
6115efe38ccSVaclav Hapla     if (!eq) {
6125f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintf(msg, sizeof(msg), "Default value of DMLabel l0 \"%s\" = %D != %D = Default value of DMLabel l1 \"%s\"", name0, v0, v1, name1));
613609dae6eSVaclav Hapla     }
6145f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6155efe38ccSVaclav Hapla     if (!eq) goto finish;
616609dae6eSVaclav Hapla   }
617609dae6eSVaclav Hapla   {
618609dae6eSVaclav Hapla     IS              is0, is1;
619609dae6eSVaclav Hapla 
6205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetNonEmptyStratumValuesIS(l0, &is0));
6215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetNonEmptyStratumValuesIS(l1, &is1));
6225f80ce2aSJacob Faibussowitsch     CHKERRQ(ISEqual(is0, is1, &eq));
6235f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is0));
6245f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is1));
6255efe38ccSVaclav Hapla     if (!eq) {
6265f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSNPrintf(msg, sizeof(msg), "Stratum values in DMLabel l0 \"%s\" are different than in DMLabel l1 \"%s\"", name0, name1));
627609dae6eSVaclav Hapla     }
6285f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
6295efe38ccSVaclav Hapla     if (!eq) goto finish;
630609dae6eSVaclav Hapla   }
631609dae6eSVaclav Hapla   {
632609dae6eSVaclav Hapla     PetscInt i, nValues;
633609dae6eSVaclav Hapla 
6345f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetNumValues(l0, &nValues));
635609dae6eSVaclav Hapla     for (i=0; i<nValues; i++) {
636609dae6eSVaclav Hapla       const PetscInt  v = l0->stratumValues[i];
637609dae6eSVaclav Hapla       PetscInt        n;
638609dae6eSVaclav Hapla       IS              is0, is1;
639609dae6eSVaclav Hapla 
6405f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumSize_Private(l0, i, &n));
641609dae6eSVaclav Hapla       if (!n) continue;
6425f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumIS(l0, v, &is0));
6435f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumIS(l1, v, &is1));
6445f80ce2aSJacob Faibussowitsch       CHKERRQ(ISEqualUnsorted(is0, is1, &eq));
6455f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is0));
6465f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is1));
6475efe38ccSVaclav Hapla       if (!eq) {
6485f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSNPrintf(msg, sizeof(msg), "Stratum #%D with value %D contains different points in DMLabel l0 \"%s\" and DMLabel l1 \"%s\"", i, v, name0, name1));
6495efe38ccSVaclav Hapla         break;
650609dae6eSVaclav Hapla       }
651609dae6eSVaclav Hapla     }
6525f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
653609dae6eSVaclav Hapla   }
654609dae6eSVaclav Hapla finish:
6555efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
656609dae6eSVaclav Hapla   if (message) {
657609dae6eSVaclav Hapla     *message = NULL;
658609dae6eSVaclav Hapla     if (msg[0]) {
6595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrallocpy(msg, message));
660609dae6eSVaclav Hapla     }
6615efe38ccSVaclav Hapla   } else {
6625efe38ccSVaclav Hapla     if (msg[0]) {
6635f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
664609dae6eSVaclav Hapla     }
6655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedFlush(comm, PETSC_STDERR));
6665efe38ccSVaclav Hapla   }
6675efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
6685efe38ccSVaclav Hapla   if (equal) *equal = eq;
669*28b400f6SJacob Faibussowitsch   else PetscCheck(eq,comm, PETSC_ERR_ARG_INCOMP, "DMLabels l0 \"%s\" and l1 \"%s\" are not equal");
670609dae6eSVaclav Hapla   PetscFunctionReturn(0);
671609dae6eSVaclav Hapla }
672609dae6eSVaclav Hapla 
673c6a43d28SMatthew G. Knepley /*@
674c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
675c6a43d28SMatthew G. Knepley 
6765b5e7992SMatthew G. Knepley   Not collective
6775b5e7992SMatthew G. Knepley 
678c6a43d28SMatthew G. Knepley   Input Parameter:
679c6a43d28SMatthew G. Knepley . label  - The DMLabel
680c6a43d28SMatthew G. Knepley 
681c6a43d28SMatthew G. Knepley   Level: intermediate
682c6a43d28SMatthew G. Knepley 
683c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
684c6a43d28SMatthew G. Knepley @*/
685c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
686c6a43d28SMatthew G. Knepley {
687c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
688c6a43d28SMatthew G. Knepley 
689c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
690c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6915f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeAllValid_Private(label));
692c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
693c6a43d28SMatthew G. Knepley     const PetscInt *points;
694c6a43d28SMatthew G. Knepley     PetscInt       i;
695c6a43d28SMatthew G. Knepley 
6965f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(label->points[v], &points));
697c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
698c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
699c6a43d28SMatthew G. Knepley 
700c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
701c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
702c6a43d28SMatthew G. Knepley     }
7035f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(label->points[v], &points));
704c6a43d28SMatthew G. Knepley   }
705c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
706c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
7075f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreateIndex(label, label->pStart, label->pEnd));
708c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
709c6a43d28SMatthew G. Knepley }
710c6a43d28SMatthew G. Knepley 
711c6a43d28SMatthew G. Knepley /*@
712c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
713c6a43d28SMatthew G. Knepley 
7145b5e7992SMatthew G. Knepley   Not collective
7155b5e7992SMatthew G. Knepley 
716c6a43d28SMatthew G. Knepley   Input Parameters:
717c6a43d28SMatthew G. Knepley + label  - The DMLabel
718c6a43d28SMatthew G. Knepley . pStart - The smallest point
719c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
720c6a43d28SMatthew G. Knepley 
721c6a43d28SMatthew G. Knepley   Level: intermediate
722c6a43d28SMatthew G. Knepley 
723c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelComputeIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
724c6a43d28SMatthew G. Knepley @*/
725c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
726c58f1c22SToby Isaac {
727c58f1c22SToby Isaac   PetscInt       v;
728c58f1c22SToby Isaac 
729c58f1c22SToby Isaac   PetscFunctionBegin;
730d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7315f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroyIndex(label));
7325f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeAllValid_Private(label));
733c58f1c22SToby Isaac   label->pStart = pStart;
734c58f1c22SToby Isaac   label->pEnd   = pEnd;
735c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
7365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTCreate(pEnd - pStart, &label->bt));
737c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
738ad8374ffSToby Isaac     const PetscInt *points;
739c58f1c22SToby Isaac     PetscInt       i;
740c58f1c22SToby Isaac 
7415f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(label->points[v], &points));
742c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
743ad8374ffSToby Isaac       const PetscInt point = points[i];
744c58f1c22SToby Isaac 
7452c71b3e2SJacob Faibussowitsch       PetscCheckFalse((point < pStart) || (point >= pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, pStart, pEnd);
7465f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscBTSet(label->bt, point - pStart));
747c58f1c22SToby Isaac     }
7485f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(label->points[v], &points));
749c58f1c22SToby Isaac   }
750c58f1c22SToby Isaac   PetscFunctionReturn(0);
751c58f1c22SToby Isaac }
752c58f1c22SToby Isaac 
753c6a43d28SMatthew G. Knepley /*@
754c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
755c6a43d28SMatthew G. Knepley 
7565b5e7992SMatthew G. Knepley   Not collective
7575b5e7992SMatthew G. Knepley 
758c6a43d28SMatthew G. Knepley   Input Parameter:
759c6a43d28SMatthew G. Knepley . label - the DMLabel
760c6a43d28SMatthew G. Knepley 
761c6a43d28SMatthew G. Knepley   Level: intermediate
762c6a43d28SMatthew G. Knepley 
763c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
764c6a43d28SMatthew G. Knepley @*/
765c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
766c58f1c22SToby Isaac {
767c58f1c22SToby Isaac   PetscFunctionBegin;
768d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
769c58f1c22SToby Isaac   label->pStart = -1;
770c58f1c22SToby Isaac   label->pEnd   = -1;
7715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTDestroy(&label->bt));
772c58f1c22SToby Isaac   PetscFunctionReturn(0);
773c58f1c22SToby Isaac }
774c58f1c22SToby Isaac 
775c58f1c22SToby Isaac /*@
776c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
777c6a43d28SMatthew G. Knepley 
7785b5e7992SMatthew G. Knepley   Not collective
7795b5e7992SMatthew G. Knepley 
780c6a43d28SMatthew G. Knepley   Input Parameter:
781c6a43d28SMatthew G. Knepley . label - the DMLabel
782c6a43d28SMatthew G. Knepley 
783c6a43d28SMatthew G. Knepley   Output Parameters:
784c6a43d28SMatthew G. Knepley + pStart - The smallest point
785c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
786c6a43d28SMatthew G. Knepley 
787c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
788c6a43d28SMatthew G. Knepley 
789c6a43d28SMatthew G. Knepley   Level: intermediate
790c6a43d28SMatthew G. Knepley 
791c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
792c6a43d28SMatthew G. Knepley @*/
793c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
794c6a43d28SMatthew G. Knepley {
795c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
796c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
7975f80ce2aSJacob Faibussowitsch   if ((label->pStart == -1) && (label->pEnd == -1)) CHKERRQ(DMLabelComputeIndex(label));
798c6a43d28SMatthew G. Knepley   if (pStart) {
799534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
800c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
801c6a43d28SMatthew G. Knepley   }
802c6a43d28SMatthew G. Knepley   if (pEnd) {
803534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
804c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
805c6a43d28SMatthew G. Knepley   }
806c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
807c6a43d28SMatthew G. Knepley }
808c6a43d28SMatthew G. Knepley 
809c6a43d28SMatthew G. Knepley /*@
810c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
811c58f1c22SToby Isaac 
8125b5e7992SMatthew G. Knepley   Not collective
8135b5e7992SMatthew G. Knepley 
814c58f1c22SToby Isaac   Input Parameters:
815c58f1c22SToby Isaac + label - the DMLabel
816c58f1c22SToby Isaac - value - the value
817c58f1c22SToby Isaac 
818c58f1c22SToby Isaac   Output Parameter:
819c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
820c58f1c22SToby Isaac 
821c58f1c22SToby Isaac   Level: developer
822c58f1c22SToby Isaac 
823c58f1c22SToby Isaac .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue()
824c58f1c22SToby Isaac @*/
825c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
826c58f1c22SToby Isaac {
827c58f1c22SToby Isaac   PetscInt v;
828c58f1c22SToby Isaac 
829c58f1c22SToby Isaac   PetscFunctionBegin;
830d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
831534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8325f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
8330c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
834c58f1c22SToby Isaac   PetscFunctionReturn(0);
835c58f1c22SToby Isaac }
836c58f1c22SToby Isaac 
837c58f1c22SToby Isaac /*@
838c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
839c58f1c22SToby Isaac 
8405b5e7992SMatthew G. Knepley   Not collective
8415b5e7992SMatthew G. Knepley 
842c58f1c22SToby Isaac   Input Parameters:
843c58f1c22SToby Isaac + label - the DMLabel
844c58f1c22SToby Isaac - point - the point
845c58f1c22SToby Isaac 
846c58f1c22SToby Isaac   Output Parameter:
847c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
848c58f1c22SToby Isaac 
849c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
850c58f1c22SToby Isaac 
851c58f1c22SToby Isaac   Level: developer
852c58f1c22SToby Isaac 
853c58f1c22SToby Isaac .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
854c58f1c22SToby Isaac @*/
855c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
856c58f1c22SToby Isaac {
857c58f1c22SToby Isaac   PetscFunctionBeginHot;
858d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
859534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
8605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeAllValid_Private(label));
86176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
862*28b400f6SJacob Faibussowitsch     PetscCheck(label->bt,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
8632c71b3e2SJacob Faibussowitsch     PetscCheckFalse((point < label->pStart) || (point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
86476bd3646SJed Brown   }
865c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
866c58f1c22SToby Isaac   PetscFunctionReturn(0);
867c58f1c22SToby Isaac }
868c58f1c22SToby Isaac 
869c58f1c22SToby Isaac /*@
870c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
871c58f1c22SToby Isaac 
8725b5e7992SMatthew G. Knepley   Not collective
8735b5e7992SMatthew G. Knepley 
874c58f1c22SToby Isaac   Input Parameters:
875c58f1c22SToby Isaac + label - the DMLabel
876c58f1c22SToby Isaac . value - the stratum value
877c58f1c22SToby Isaac - point - the point
878c58f1c22SToby Isaac 
879c58f1c22SToby Isaac   Output Parameter:
880c58f1c22SToby Isaac . contains - true if the stratum contains the point
881c58f1c22SToby Isaac 
882c58f1c22SToby Isaac   Level: intermediate
883c58f1c22SToby Isaac 
884c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue()
885c58f1c22SToby Isaac @*/
886c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
887c58f1c22SToby Isaac {
888c58f1c22SToby Isaac   PetscInt       v;
889c58f1c22SToby Isaac 
8900c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
891d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
892534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
893c58f1c22SToby Isaac   *contains = PETSC_FALSE;
8945f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
8950c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
8960c3c4a36SLisandro Dalcin 
897ad8374ffSToby Isaac   if (label->validIS[v]) {
898c58f1c22SToby Isaac     PetscInt i;
899c58f1c22SToby Isaac 
9005f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocate(label->points[v], point, &i));
9010c3c4a36SLisandro Dalcin     if (i >= 0) *contains = PETSC_TRUE;
902c58f1c22SToby Isaac   } else {
903c58f1c22SToby Isaac     PetscBool has;
904c58f1c22SToby Isaac 
9055f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIHas(label->ht[v], point, &has));
9060c3c4a36SLisandro Dalcin     if (has) *contains = PETSC_TRUE;
907c58f1c22SToby Isaac   }
908c58f1c22SToby Isaac   PetscFunctionReturn(0);
909c58f1c22SToby Isaac }
910c58f1c22SToby Isaac 
91184f0b6dfSMatthew G. Knepley /*@
9125aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9135aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9145aa44df4SToby Isaac 
9155b5e7992SMatthew G. Knepley   Not collective
9165b5e7992SMatthew G. Knepley 
9175aa44df4SToby Isaac   Input parameter:
9185aa44df4SToby Isaac . label - a DMLabel object
9195aa44df4SToby Isaac 
9205aa44df4SToby Isaac   Output parameter:
9215aa44df4SToby Isaac . defaultValue - the default value
9225aa44df4SToby Isaac 
9235aa44df4SToby Isaac   Level: beginner
9245aa44df4SToby Isaac 
9255aa44df4SToby Isaac .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
92684f0b6dfSMatthew G. Knepley @*/
9275aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
9285aa44df4SToby Isaac {
9295aa44df4SToby Isaac   PetscFunctionBegin;
930d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9315aa44df4SToby Isaac   *defaultValue = label->defaultValue;
9325aa44df4SToby Isaac   PetscFunctionReturn(0);
9335aa44df4SToby Isaac }
9345aa44df4SToby Isaac 
93584f0b6dfSMatthew G. Knepley /*@
9365aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
9375aa44df4SToby Isaac   When a label is created, it is initialized to -1.
9385aa44df4SToby Isaac 
9395b5e7992SMatthew G. Knepley   Not collective
9405b5e7992SMatthew G. Knepley 
9415aa44df4SToby Isaac   Input parameter:
9425aa44df4SToby Isaac . label - a DMLabel object
9435aa44df4SToby Isaac 
9445aa44df4SToby Isaac   Output parameter:
9455aa44df4SToby Isaac . defaultValue - the default value
9465aa44df4SToby Isaac 
9475aa44df4SToby Isaac   Level: beginner
9485aa44df4SToby Isaac 
9495aa44df4SToby Isaac .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
95084f0b6dfSMatthew G. Knepley @*/
9515aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
9525aa44df4SToby Isaac {
9535aa44df4SToby Isaac   PetscFunctionBegin;
954d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9555aa44df4SToby Isaac   label->defaultValue = defaultValue;
9565aa44df4SToby Isaac   PetscFunctionReturn(0);
9575aa44df4SToby Isaac }
9585aa44df4SToby Isaac 
959c58f1c22SToby Isaac /*@
9605aa44df4SToby 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())
961c58f1c22SToby Isaac 
9625b5e7992SMatthew G. Knepley   Not collective
9635b5e7992SMatthew G. Knepley 
964c58f1c22SToby Isaac   Input Parameters:
965c58f1c22SToby Isaac + label - the DMLabel
966c58f1c22SToby Isaac - point - the point
967c58f1c22SToby Isaac 
968c58f1c22SToby Isaac   Output Parameter:
9698e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
970c58f1c22SToby Isaac 
971c58f1c22SToby Isaac   Level: intermediate
972c58f1c22SToby Isaac 
9735aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
974c58f1c22SToby Isaac @*/
975c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
976c58f1c22SToby Isaac {
977c58f1c22SToby Isaac   PetscInt       v;
978c58f1c22SToby Isaac 
9790c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
980d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
981c58f1c22SToby Isaac   PetscValidPointer(value, 3);
9825aa44df4SToby Isaac   *value = label->defaultValue;
983c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
984ad8374ffSToby Isaac     if (label->validIS[v]) {
985c58f1c22SToby Isaac       PetscInt i;
986c58f1c22SToby Isaac 
9875f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocate(label->points[v], point, &i));
988c58f1c22SToby Isaac       if (i >= 0) {
989c58f1c22SToby Isaac         *value = label->stratumValues[v];
990c58f1c22SToby Isaac         break;
991c58f1c22SToby Isaac       }
992c58f1c22SToby Isaac     } else {
993c58f1c22SToby Isaac       PetscBool has;
994c58f1c22SToby Isaac 
9955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscHSetIHas(label->ht[v], point, &has));
996c58f1c22SToby Isaac       if (has) {
997c58f1c22SToby Isaac         *value = label->stratumValues[v];
998c58f1c22SToby Isaac         break;
999c58f1c22SToby Isaac       }
1000c58f1c22SToby Isaac     }
1001c58f1c22SToby Isaac   }
1002c58f1c22SToby Isaac   PetscFunctionReturn(0);
1003c58f1c22SToby Isaac }
1004c58f1c22SToby Isaac 
1005c58f1c22SToby Isaac /*@
1006367003a6SStefano 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.
1007c58f1c22SToby Isaac 
10085b5e7992SMatthew G. Knepley   Not collective
10095b5e7992SMatthew G. Knepley 
1010c58f1c22SToby Isaac   Input Parameters:
1011c58f1c22SToby Isaac + label - the DMLabel
1012c58f1c22SToby Isaac . point - the point
1013c58f1c22SToby Isaac - value - The point value
1014c58f1c22SToby Isaac 
1015c58f1c22SToby Isaac   Level: intermediate
1016c58f1c22SToby Isaac 
10175aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
1018c58f1c22SToby Isaac @*/
1019c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
1020c58f1c22SToby Isaac {
1021c58f1c22SToby Isaac   PetscInt       v;
1022c58f1c22SToby Isaac 
1023c58f1c22SToby Isaac   PetscFunctionBegin;
1024d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
10250c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10265aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
10275f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupAddStratum(label, value, &v));
1028c58f1c22SToby Isaac   /* Set key */
10295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeInvalid_Private(label, v));
10305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIAdd(label->ht[v], point));
1031c58f1c22SToby Isaac   PetscFunctionReturn(0);
1032c58f1c22SToby Isaac }
1033c58f1c22SToby Isaac 
1034c58f1c22SToby Isaac /*@
1035c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
1036c58f1c22SToby Isaac 
10375b5e7992SMatthew G. Knepley   Not collective
10385b5e7992SMatthew G. Knepley 
1039c58f1c22SToby Isaac   Input Parameters:
1040c58f1c22SToby Isaac + label - the DMLabel
1041c58f1c22SToby Isaac . point - the point
1042c58f1c22SToby Isaac - value - The point value
1043c58f1c22SToby Isaac 
1044c58f1c22SToby Isaac   Level: intermediate
1045c58f1c22SToby Isaac 
1046c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue()
1047c58f1c22SToby Isaac @*/
1048c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
1049c58f1c22SToby Isaac {
1050ad8374ffSToby Isaac   PetscInt       v;
1051c58f1c22SToby Isaac 
1052c58f1c22SToby Isaac   PetscFunctionBegin;
1053d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1054c58f1c22SToby Isaac   /* Find label value */
10555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
10560c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
10570c3c4a36SLisandro Dalcin 
1058eeed21e7SToby Isaac   if (label->bt) {
10592c71b3e2SJacob Faibussowitsch     PetscCheckFalse((point < label->pStart) || (point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
10605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBTClear(label->bt, point - label->pStart));
1061eeed21e7SToby Isaac   }
10620c3c4a36SLisandro Dalcin 
10630c3c4a36SLisandro Dalcin   /* Delete key */
10645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeInvalid_Private(label, v));
10655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIDel(label->ht[v], point));
1066c58f1c22SToby Isaac   PetscFunctionReturn(0);
1067c58f1c22SToby Isaac }
1068c58f1c22SToby Isaac 
1069c58f1c22SToby Isaac /*@
1070c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
1071c58f1c22SToby Isaac 
10725b5e7992SMatthew G. Knepley   Not collective
10735b5e7992SMatthew G. Knepley 
1074c58f1c22SToby Isaac   Input Parameters:
1075c58f1c22SToby Isaac + label - the DMLabel
1076c58f1c22SToby Isaac . is    - the point IS
1077c58f1c22SToby Isaac - value - The point value
1078c58f1c22SToby Isaac 
1079c58f1c22SToby Isaac   Level: intermediate
1080c58f1c22SToby Isaac 
1081c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
1082c58f1c22SToby Isaac @*/
1083c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
1084c58f1c22SToby Isaac {
10850c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1086c58f1c22SToby Isaac   const PetscInt *points;
1087c58f1c22SToby Isaac 
1088c58f1c22SToby Isaac   PetscFunctionBegin;
1089d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1090c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
10910c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10920c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
10935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupAddStratum(label, value, &v));
10940c3c4a36SLisandro Dalcin   /* Set keys */
10955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeInvalid_Private(label, v));
10965f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(is, &n));
10975f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(is, &points));
10985f80ce2aSJacob Faibussowitsch   for (p = 0; p < n; ++p) CHKERRQ(PetscHSetIAdd(label->ht[v], points[p]));
10995f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(is, &points));
1100c58f1c22SToby Isaac   PetscFunctionReturn(0);
1101c58f1c22SToby Isaac }
1102c58f1c22SToby Isaac 
110384f0b6dfSMatthew G. Knepley /*@
110484f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
110584f0b6dfSMatthew G. Knepley 
11065b5e7992SMatthew G. Knepley   Not collective
11075b5e7992SMatthew G. Knepley 
110884f0b6dfSMatthew G. Knepley   Input Parameter:
110984f0b6dfSMatthew G. Knepley . label - the DMLabel
111084f0b6dfSMatthew G. Knepley 
111101d2d390SJose E. Roman   Output Parameter:
111284f0b6dfSMatthew G. Knepley . numValues - the number of values
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 DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1119c58f1c22SToby Isaac {
1120c58f1c22SToby Isaac   PetscFunctionBegin;
1121d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1122c58f1c22SToby Isaac   PetscValidPointer(numValues, 2);
1123c58f1c22SToby Isaac   *numValues = label->numStrata;
1124c58f1c22SToby Isaac   PetscFunctionReturn(0);
1125c58f1c22SToby Isaac }
1126c58f1c22SToby Isaac 
112784f0b6dfSMatthew G. Knepley /*@
112884f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
112984f0b6dfSMatthew G. Knepley 
11305b5e7992SMatthew G. Knepley   Not collective
11315b5e7992SMatthew G. Knepley 
113284f0b6dfSMatthew G. Knepley   Input Parameter:
113384f0b6dfSMatthew G. Knepley . label - the DMLabel
113484f0b6dfSMatthew G. Knepley 
113501d2d390SJose E. Roman   Output Parameter:
113684f0b6dfSMatthew G. Knepley . is    - the value IS
113784f0b6dfSMatthew G. Knepley 
113884f0b6dfSMatthew G. Knepley   Level: intermediate
113984f0b6dfSMatthew G. Knepley 
11401d04cbbeSVaclav Hapla   Notes:
11411d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11421d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
11431d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
11441d04cbbeSVaclav Hapla 
11451d04cbbeSVaclav Hapla .seealso: DMLabelGetNonEmptyStratumValuesIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
114684f0b6dfSMatthew G. Knepley @*/
1147c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1148c58f1c22SToby Isaac {
1149c58f1c22SToby Isaac   PetscFunctionBegin;
1150d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1151c58f1c22SToby Isaac   PetscValidPointer(values, 2);
11525f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
1153c58f1c22SToby Isaac   PetscFunctionReturn(0);
1154c58f1c22SToby Isaac }
1155c58f1c22SToby Isaac 
115684f0b6dfSMatthew G. Knepley /*@
11571d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
11581d04cbbeSVaclav Hapla 
11591d04cbbeSVaclav Hapla   Not collective
11601d04cbbeSVaclav Hapla 
11611d04cbbeSVaclav Hapla   Input Parameter:
11621d04cbbeSVaclav Hapla . label - the DMLabel
11631d04cbbeSVaclav Hapla 
11641d04cbbeSVaclav Hapla   Output Paramater:
11651d04cbbeSVaclav Hapla . is    - the value IS
11661d04cbbeSVaclav Hapla 
11671d04cbbeSVaclav Hapla   Level: intermediate
11681d04cbbeSVaclav Hapla 
11691d04cbbeSVaclav Hapla   Notes:
11701d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
11711d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
11721d04cbbeSVaclav Hapla 
11731d04cbbeSVaclav Hapla .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
11741d04cbbeSVaclav Hapla @*/
11751d04cbbeSVaclav Hapla PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
11761d04cbbeSVaclav Hapla {
11771d04cbbeSVaclav Hapla   PetscInt        i, j;
11781d04cbbeSVaclav Hapla   PetscInt       *valuesArr;
11791d04cbbeSVaclav Hapla 
11801d04cbbeSVaclav Hapla   PetscFunctionBegin;
11811d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
11821d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
11835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(label->numStrata, &valuesArr));
11841d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
11851d04cbbeSVaclav Hapla     PetscInt        n;
11861d04cbbeSVaclav Hapla 
11875f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetStratumSize_Private(label, i, &n));
11881d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
11891d04cbbeSVaclav Hapla   }
11901d04cbbeSVaclav Hapla   if (j == label->numStrata) {
11915f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values));
11921d04cbbeSVaclav Hapla   } else {
11935f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values));
11941d04cbbeSVaclav Hapla   }
11955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(valuesArr));
11961d04cbbeSVaclav Hapla   PetscFunctionReturn(0);
11971d04cbbeSVaclav Hapla }
11981d04cbbeSVaclav Hapla 
11991d04cbbeSVaclav Hapla /*@
1200d123abd9SMatthew G. Knepley   DMLabelGetValueIndex - Get the index of a given value in the list of values for the DMlabel, or -1 if it is not present
1201d123abd9SMatthew G. Knepley 
1202d123abd9SMatthew G. Knepley   Not collective
1203d123abd9SMatthew G. Knepley 
1204d123abd9SMatthew G. Knepley   Input Parameters:
1205d123abd9SMatthew G. Knepley + label - the DMLabel
120697bb3fdcSJose E. Roman - value - the value
1207d123abd9SMatthew G. Knepley 
120801d2d390SJose E. Roman   Output Parameter:
1209d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1210d123abd9SMatthew G. Knepley 
1211d123abd9SMatthew G. Knepley   Level: intermediate
1212d123abd9SMatthew G. Knepley 
1213d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
1214d123abd9SMatthew G. Knepley @*/
1215d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1216d123abd9SMatthew G. Knepley {
1217d123abd9SMatthew G. Knepley   PetscInt v;
1218d123abd9SMatthew G. Knepley 
1219d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1220d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1221d123abd9SMatthew G. Knepley   PetscValidPointer(index, 3);
1222d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
1223d123abd9SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) if (label->stratumValues[v] == value) break;
1224d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1225d123abd9SMatthew G. Knepley   else                       *index = v;
1226d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1227d123abd9SMatthew G. Knepley }
1228d123abd9SMatthew G. Knepley 
1229d123abd9SMatthew G. Knepley /*@
123084f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
123184f0b6dfSMatthew G. Knepley 
12325b5e7992SMatthew G. Knepley   Not collective
12335b5e7992SMatthew G. Knepley 
123484f0b6dfSMatthew G. Knepley   Input Parameters:
123584f0b6dfSMatthew G. Knepley + label - the DMLabel
123684f0b6dfSMatthew G. Knepley - value - the stratum value
123784f0b6dfSMatthew G. Knepley 
123801d2d390SJose E. Roman   Output Parameter:
123984f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
124084f0b6dfSMatthew G. Knepley 
124184f0b6dfSMatthew G. Knepley   Level: intermediate
124284f0b6dfSMatthew G. Knepley 
124384f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
124484f0b6dfSMatthew G. Knepley @*/
1245fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1246fada774cSMatthew G. Knepley {
1247fada774cSMatthew G. Knepley   PetscInt       v;
1248fada774cSMatthew G. Knepley 
1249fada774cSMatthew G. Knepley   PetscFunctionBegin;
1250d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1251fada774cSMatthew G. Knepley   PetscValidPointer(exists, 3);
12525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
12530c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1254fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1255fada774cSMatthew G. Knepley }
1256fada774cSMatthew G. Knepley 
125784f0b6dfSMatthew G. Knepley /*@
125884f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
125984f0b6dfSMatthew G. Knepley 
12605b5e7992SMatthew G. Knepley   Not collective
12615b5e7992SMatthew G. Knepley 
126284f0b6dfSMatthew G. Knepley   Input Parameters:
126384f0b6dfSMatthew G. Knepley + label - the DMLabel
126484f0b6dfSMatthew G. Knepley - value - the stratum value
126584f0b6dfSMatthew G. Knepley 
126601d2d390SJose E. Roman   Output Parameter:
126784f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
126884f0b6dfSMatthew G. Knepley 
126984f0b6dfSMatthew G. Knepley   Level: intermediate
127084f0b6dfSMatthew G. Knepley 
127184f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
127284f0b6dfSMatthew G. Knepley @*/
1273c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1274c58f1c22SToby Isaac {
1275c58f1c22SToby Isaac   PetscInt       v;
1276c58f1c22SToby Isaac 
1277c58f1c22SToby Isaac   PetscFunctionBegin;
1278d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1279c58f1c22SToby Isaac   PetscValidPointer(size, 3);
12805f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
12815f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetStratumSize_Private(label, v, size));
1282c58f1c22SToby Isaac   PetscFunctionReturn(0);
1283c58f1c22SToby Isaac }
1284c58f1c22SToby Isaac 
128584f0b6dfSMatthew G. Knepley /*@
128684f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
128784f0b6dfSMatthew G. Knepley 
12885b5e7992SMatthew G. Knepley   Not collective
12895b5e7992SMatthew G. Knepley 
129084f0b6dfSMatthew G. Knepley   Input Parameters:
129184f0b6dfSMatthew G. Knepley + label - the DMLabel
129284f0b6dfSMatthew G. Knepley - value - the stratum value
129384f0b6dfSMatthew G. Knepley 
129401d2d390SJose E. Roman   Output Parameters:
129584f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
129684f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
129784f0b6dfSMatthew G. Knepley 
129884f0b6dfSMatthew G. Knepley   Level: intermediate
129984f0b6dfSMatthew G. Knepley 
130084f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
130184f0b6dfSMatthew G. Knepley @*/
1302c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1303c58f1c22SToby Isaac {
13040c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1305c58f1c22SToby Isaac 
1306c58f1c22SToby Isaac   PetscFunctionBegin;
1307d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1308cade499fSVaclav Hapla   if (start) {PetscValidPointer(start, 3); *start = -1;}
1309cade499fSVaclav Hapla   if (end)   {PetscValidPointer(end,   4); *end   = -1;}
13105f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
13110c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13125f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeValid_Private(label, v));
13130c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
13145f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetMinMax(label->points[v], &min, &max));
1315d6cb179aSToby Isaac   if (start) *start = min;
1316d6cb179aSToby Isaac   if (end)   *end   = max+1;
1317c58f1c22SToby Isaac   PetscFunctionReturn(0);
1318c58f1c22SToby Isaac }
1319c58f1c22SToby Isaac 
132084f0b6dfSMatthew G. Knepley /*@
132184f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
132284f0b6dfSMatthew G. Knepley 
13235b5e7992SMatthew G. Knepley   Not collective
13245b5e7992SMatthew G. Knepley 
132584f0b6dfSMatthew G. Knepley   Input Parameters:
132684f0b6dfSMatthew G. Knepley + label - the DMLabel
132784f0b6dfSMatthew G. Knepley - value - the stratum value
132884f0b6dfSMatthew G. Knepley 
132901d2d390SJose E. Roman   Output Parameter:
133084f0b6dfSMatthew G. Knepley . points - The stratum points
133184f0b6dfSMatthew G. Knepley 
133284f0b6dfSMatthew G. Knepley   Level: intermediate
133384f0b6dfSMatthew G. Knepley 
1334593ce467SVaclav Hapla   Notes:
1335593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1336593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1337593ce467SVaclav Hapla 
133884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
133984f0b6dfSMatthew G. Knepley @*/
1340c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1341c58f1c22SToby Isaac {
1342c58f1c22SToby Isaac   PetscInt       v;
1343c58f1c22SToby Isaac 
1344c58f1c22SToby Isaac   PetscFunctionBegin;
1345d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1346c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1347c58f1c22SToby Isaac   *points = NULL;
13485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
13490c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13505f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeValid_Private(label, v));
13515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject) label->points[v]));
1352ad8374ffSToby Isaac   *points = label->points[v];
1353c58f1c22SToby Isaac   PetscFunctionReturn(0);
1354c58f1c22SToby Isaac }
1355c58f1c22SToby Isaac 
135684f0b6dfSMatthew G. Knepley /*@
135784f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
135884f0b6dfSMatthew G. Knepley 
13595b5e7992SMatthew G. Knepley   Not collective
13605b5e7992SMatthew G. Knepley 
136184f0b6dfSMatthew G. Knepley   Input Parameters:
136284f0b6dfSMatthew G. Knepley + label - the DMLabel
136384f0b6dfSMatthew G. Knepley . value - the stratum value
136484f0b6dfSMatthew G. Knepley - points - The stratum points
136584f0b6dfSMatthew G. Knepley 
136684f0b6dfSMatthew G. Knepley   Level: intermediate
136784f0b6dfSMatthew G. Knepley 
136884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
136984f0b6dfSMatthew G. Knepley @*/
13704de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
13714de306b1SToby Isaac {
13720c3c4a36SLisandro Dalcin   PetscInt       v;
13734de306b1SToby Isaac 
13744de306b1SToby Isaac   PetscFunctionBegin;
1375d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1376d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
13775f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupAddStratum(label, value, &v));
13784de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
13795f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelClearStratum(label, value));
13805f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(is, &(label->stratumSizes[v])));
13815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)is));
13825f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&(label->points[v])));
13830c3c4a36SLisandro Dalcin   label->points[v]  = is;
13840c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
13855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateIncrease((PetscObject) label));
13864de306b1SToby Isaac   if (label->bt) {
13874de306b1SToby Isaac     const PetscInt *points;
13884de306b1SToby Isaac     PetscInt p;
13894de306b1SToby Isaac 
13905f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(is,&points));
13914de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
13924de306b1SToby Isaac       const PetscInt point = points[p];
13934de306b1SToby Isaac 
13942c71b3e2SJacob Faibussowitsch       PetscCheckFalse((point < label->pStart) || (point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
13955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscBTSet(label->bt, point - label->pStart));
13964de306b1SToby Isaac     }
13974de306b1SToby Isaac   }
13984de306b1SToby Isaac   PetscFunctionReturn(0);
13994de306b1SToby Isaac }
14004de306b1SToby Isaac 
140184f0b6dfSMatthew G. Knepley /*@
140284f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
14034de306b1SToby Isaac 
14045b5e7992SMatthew G. Knepley   Not collective
14055b5e7992SMatthew G. Knepley 
140684f0b6dfSMatthew G. Knepley   Input Parameters:
140784f0b6dfSMatthew G. Knepley + label - the DMLabel
140884f0b6dfSMatthew G. Knepley - value - the stratum value
140984f0b6dfSMatthew G. Knepley 
141084f0b6dfSMatthew G. Knepley   Level: intermediate
141184f0b6dfSMatthew G. Knepley 
141284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
141384f0b6dfSMatthew G. Knepley @*/
1414c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1415c58f1c22SToby Isaac {
1416c58f1c22SToby Isaac   PetscInt       v;
1417c58f1c22SToby Isaac 
1418c58f1c22SToby Isaac   PetscFunctionBegin;
1419d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
14210c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
14224de306b1SToby Isaac   if (label->validIS[v]) {
14234de306b1SToby Isaac     if (label->bt) {
1424c58f1c22SToby Isaac       PetscInt       i;
1425ad8374ffSToby Isaac       const PetscInt *points;
1426c58f1c22SToby Isaac 
14275f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(label->points[v], &points));
1428c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1429ad8374ffSToby Isaac         const PetscInt point = points[i];
1430c58f1c22SToby Isaac 
14312c71b3e2SJacob Faibussowitsch         PetscCheckFalse((point < label->pStart) || (point >= label->pEnd),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
14325f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscBTClear(label->bt, point - label->pStart));
1433c58f1c22SToby Isaac       }
14345f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(label->points[v], &points));
1435c58f1c22SToby Isaac     }
1436c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
14375f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&label->points[v]));
14385f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]));
14395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) label->points[v], "indices"));
14405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectStateIncrease((PetscObject) label));
1441c58f1c22SToby Isaac   } else {
14425f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIClear(label->ht[v]));
1443c58f1c22SToby Isaac   }
1444c58f1c22SToby Isaac   PetscFunctionReturn(0);
1445c58f1c22SToby Isaac }
1446c58f1c22SToby Isaac 
144784f0b6dfSMatthew G. Knepley /*@
1448412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1449412e9a14SMatthew G. Knepley 
1450412e9a14SMatthew G. Knepley   Not collective
1451412e9a14SMatthew G. Knepley 
1452412e9a14SMatthew G. Knepley   Input Parameters:
1453412e9a14SMatthew G. Knepley + label  - The DMLabel
1454412e9a14SMatthew G. Knepley . value  - The label value for all points
1455412e9a14SMatthew G. Knepley . pStart - The first point
1456412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1457412e9a14SMatthew G. Knepley 
1458412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1459412e9a14SMatthew G. Knepley 
1460412e9a14SMatthew G. Knepley   Level: intermediate
1461412e9a14SMatthew G. Knepley 
1462412e9a14SMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelSetStratumIS(), DMLabelGetStratumIS()
1463412e9a14SMatthew G. Knepley @*/
1464412e9a14SMatthew G. Knepley PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1465412e9a14SMatthew G. Knepley {
1466412e9a14SMatthew G. Knepley   IS             pIS;
1467412e9a14SMatthew G. Knepley 
1468412e9a14SMatthew G. Knepley   PetscFunctionBegin;
14695f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS));
14705f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelSetStratumIS(label, value, pIS));
14715f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&pIS));
1472412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1473412e9a14SMatthew G. Knepley }
1474412e9a14SMatthew G. Knepley 
1475412e9a14SMatthew G. Knepley /*@
1476d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1477d123abd9SMatthew G. Knepley 
1478d123abd9SMatthew G. Knepley   Not collective
1479d123abd9SMatthew G. Knepley 
1480d123abd9SMatthew G. Knepley   Input Parameters:
1481d123abd9SMatthew G. Knepley + label  - The DMLabel
1482d123abd9SMatthew G. Knepley . value  - The label value
1483d123abd9SMatthew G. Knepley - p      - A point with this value
1484d123abd9SMatthew G. Knepley 
1485d123abd9SMatthew G. Knepley   Output Parameter:
1486d123abd9SMatthew G. Knepley . index  - The index of this point in the stratum, or -1 if the point is not in the stratum or the stratum does not exist
1487d123abd9SMatthew G. Knepley 
1488d123abd9SMatthew G. Knepley   Level: intermediate
1489d123abd9SMatthew G. Knepley 
1490d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIndex(), DMLabelGetStratumIS(), DMLabelCreate()
1491d123abd9SMatthew G. Knepley @*/
1492d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1493d123abd9SMatthew G. Knepley {
1494d123abd9SMatthew G. Knepley   const PetscInt *indices;
1495d123abd9SMatthew G. Knepley   PetscInt        v;
1496d123abd9SMatthew G. Knepley 
1497d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1498d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1499d123abd9SMatthew G. Knepley   PetscValidPointer(index, 4);
1500d123abd9SMatthew G. Knepley   *index = -1;
15015f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelLookupStratum(label, value, &v));
1502d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
15035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeValid_Private(label, v));
15045f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(label->points[v], &indices));
15055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFindInt(p, label->stratumSizes[v], indices, index));
15065f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(label->points[v], &indices));
1507d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1508d123abd9SMatthew G. Knepley }
1509d123abd9SMatthew G. Knepley 
1510d123abd9SMatthew G. Knepley /*@
151184f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
151284f0b6dfSMatthew G. Knepley 
15135b5e7992SMatthew G. Knepley   Not collective
15145b5e7992SMatthew G. Knepley 
151584f0b6dfSMatthew G. Knepley   Input Parameters:
151684f0b6dfSMatthew G. Knepley + label - the DMLabel
151722cd2cdaSVaclav Hapla . start - the first point kept
151822cd2cdaSVaclav Hapla - end - one more than the last point kept
151984f0b6dfSMatthew G. Knepley 
152084f0b6dfSMatthew G. Knepley   Level: intermediate
152184f0b6dfSMatthew G. Knepley 
152284f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
152384f0b6dfSMatthew G. Knepley @*/
1524c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1525c58f1c22SToby Isaac {
1526c58f1c22SToby Isaac   PetscInt       v;
1527c58f1c22SToby Isaac 
1528c58f1c22SToby Isaac   PetscFunctionBegin;
1529d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
15305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroyIndex(label));
15315f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeAllValid_Private(label));
1532c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
15335f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGeneralFilter(label->points[v], start, end));
1534c58f1c22SToby Isaac   }
15355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreateIndex(label, start, end));
1536c58f1c22SToby Isaac   PetscFunctionReturn(0);
1537c58f1c22SToby Isaac }
1538c58f1c22SToby Isaac 
153984f0b6dfSMatthew G. Knepley /*@
154084f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
154184f0b6dfSMatthew G. Knepley 
15425b5e7992SMatthew G. Knepley   Not collective
15435b5e7992SMatthew G. Knepley 
154484f0b6dfSMatthew G. Knepley   Input Parameters:
154584f0b6dfSMatthew G. Knepley + label - the DMLabel
154684f0b6dfSMatthew G. Knepley - permutation - the point permutation
154784f0b6dfSMatthew G. Knepley 
154884f0b6dfSMatthew G. Knepley   Output Parameter:
154984f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
155084f0b6dfSMatthew G. Knepley 
155184f0b6dfSMatthew G. Knepley   Level: intermediate
155284f0b6dfSMatthew G. Knepley 
155384f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
155484f0b6dfSMatthew G. Knepley @*/
1555c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1556c58f1c22SToby Isaac {
1557c58f1c22SToby Isaac   const PetscInt *perm;
1558c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1559c58f1c22SToby Isaac 
1560c58f1c22SToby Isaac   PetscFunctionBegin;
1561d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1562d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
15635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelMakeAllValid_Private(label));
15645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDuplicate(label, labelNew));
15655f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetNumValues(*labelNew, &numValues));
15665f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(permutation, &numPoints));
15675f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(permutation, &perm));
1568c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1569c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1570ad8374ffSToby Isaac     const PetscInt *points;
1571ad8374ffSToby Isaac     PetscInt *pointsNew;
1572c58f1c22SToby Isaac 
15735f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices((*labelNew)->points[v],&points));
15745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(size,&pointsNew));
1575c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1576ad8374ffSToby Isaac       const PetscInt point = points[q];
1577c58f1c22SToby Isaac 
15782c71b3e2SJacob Faibussowitsch       PetscCheckFalse((point < 0) || (point >= numPoints),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [0, %D) for the remapping", point, numPoints);
1579ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1580c58f1c22SToby Isaac     }
15815f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices((*labelNew)->points[v],&points));
15825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortInt(size, pointsNew));
15835f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&((*labelNew)->points[v])));
1584fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
15855f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v])));
15865f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(pointsNew));
1587fa8e8ae5SToby Isaac     } else {
15885f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v])));
1589fa8e8ae5SToby Isaac     }
15905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices"));
1591c58f1c22SToby Isaac   }
15925f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(permutation, &perm));
1593c58f1c22SToby Isaac   if (label->bt) {
15945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBTDestroy(&label->bt));
15955f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelCreateIndex(label, label->pStart, label->pEnd));
1596c58f1c22SToby Isaac   }
1597c58f1c22SToby Isaac   PetscFunctionReturn(0);
1598c58f1c22SToby Isaac }
1599c58f1c22SToby Isaac 
160026c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
160126c55118SMichael Lange {
160226c55118SMichael Lange   MPI_Comm       comm;
160326c55118SMichael Lange   PetscInt       s, l, nroots, nleaves, dof, offset, size;
160426c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
160526c55118SMichael Lange   PetscSection   rootSection;
160626c55118SMichael Lange   PetscSF        labelSF;
160726c55118SMichael Lange 
160826c55118SMichael Lange   PetscFunctionBegin;
16095f80ce2aSJacob Faibussowitsch   if (label) CHKERRQ(DMLabelMakeAllValid_Private(label));
16105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)sf, &comm));
161126c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
161226c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
16135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
16145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, &rootSection));
16155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(rootSection, 0, nroots));
161626c55118SMichael Lange   if (label) {
161726c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1618ad8374ffSToby Isaac       const PetscInt *points;
1619ad8374ffSToby Isaac 
16205f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(label->points[s], &points));
162126c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
16225f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(rootSection, points[l], &dof));
16235f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionSetDof(rootSection, points[l], dof+1));
162426c55118SMichael Lange       }
16255f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(label->points[s], &points));
162626c55118SMichael Lange     }
162726c55118SMichael Lange   }
16285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(rootSection));
162926c55118SMichael Lange   /* Create a point-wise array of stratum values */
16305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(rootSection, &size));
16315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(size, &rootStrata));
16325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(nroots, &rootIdx));
163326c55118SMichael Lange   if (label) {
163426c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1635ad8374ffSToby Isaac       const PetscInt *points;
1636ad8374ffSToby Isaac 
16375f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(label->points[s], &points));
163826c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1639ad8374ffSToby Isaac         const PetscInt p = points[l];
16405f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(rootSection, p, &offset));
164126c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
164226c55118SMichael Lange       }
16435f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(label->points[s], &points));
164426c55118SMichael Lange     }
164526c55118SMichael Lange   }
164626c55118SMichael Lange   /* Build SF that maps label points to remote processes */
16475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, leafSection));
16485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection));
16495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF));
16505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(remoteOffsets));
165126c55118SMichael Lange   /* Send the strata for each point over the derived SF */
16525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(*leafSection, &size));
16535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(size, leafStrata));
16545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
16555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE));
165626c55118SMichael Lange   /* Clean up */
16575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(rootStrata));
16585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(rootIdx));
16595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&rootSection));
16605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&labelSF));
166126c55118SMichael Lange   PetscFunctionReturn(0);
166226c55118SMichael Lange }
166326c55118SMichael Lange 
166484f0b6dfSMatthew G. Knepley /*@
166584f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
166684f0b6dfSMatthew G. Knepley 
16675b5e7992SMatthew G. Knepley   Collective on sf
16685b5e7992SMatthew G. Knepley 
166984f0b6dfSMatthew G. Knepley   Input Parameters:
167084f0b6dfSMatthew G. Knepley + label - the DMLabel
167184f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
167284f0b6dfSMatthew G. Knepley 
167384f0b6dfSMatthew G. Knepley   Output Parameter:
167484f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
167584f0b6dfSMatthew G. Knepley 
167684f0b6dfSMatthew G. Knepley   Level: intermediate
167784f0b6dfSMatthew G. Knepley 
167884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
167984f0b6dfSMatthew G. Knepley @*/
1680c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1681c58f1c22SToby Isaac {
1682c58f1c22SToby Isaac   MPI_Comm       comm;
168326c55118SMichael Lange   PetscSection   leafSection;
168426c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
168526c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1686ad8374ffSToby Isaac   PetscInt     **points;
1687d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1688c58f1c22SToby Isaac   char          *name;
1689c58f1c22SToby Isaac   PetscInt       nameSize;
1690e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1691c58f1c22SToby Isaac   size_t         len = 0;
169226c55118SMichael Lange   PetscMPIInt    rank;
1693c58f1c22SToby Isaac 
1694c58f1c22SToby Isaac   PetscFunctionBegin;
1695d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1696f018e600SMatthew G. Knepley   if (label) {
1697f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
16985f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelMakeAllValid_Private(label));
1699f018e600SMatthew G. Knepley   }
17005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)sf, &comm));
17015f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
1702c58f1c22SToby Isaac   /* Bcast name */
1703dd400576SPatrick Sanan   if (rank == 0) {
17045f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) label, &lname));
17055f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrlen(lname, &len));
1706d67d17b1SMatthew G. Knepley   }
1707c58f1c22SToby Isaac   nameSize = len;
17085f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
17095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nameSize+1, &name));
17105f80ce2aSJacob Faibussowitsch   if (rank == 0) CHKERRQ(PetscArraycpy(name, lname, nameSize+1));
17115f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
17125f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
17135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(name));
171477d236dfSMichael Lange   /* Bcast defaultValue */
1715dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
17165f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm));
171726c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
17185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata));
17195cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
17205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetICreate(&stratumHash));
17215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(leafSection, &size));
17225f80ce2aSJacob Faibussowitsch   for (p = 0; p < size; ++p) CHKERRQ(PetscHSetIAdd(stratumHash, leafStrata[p]));
17235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata));
17245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS));
1725ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
17265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues));
17275cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
17285cbdf6fcSMichael Lange   offset = 0;
17295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues));
17305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues));
173190e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s));
173390e9b2aeSLisandro Dalcin   }
17345cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1735231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1736231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
17375cbdf6fcSMichael Lange     }
17385cbdf6fcSMichael Lange   }
1739c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
17405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes));
17415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1742c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(leafSection, p, &dof));
17445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(leafSection, p, &offset));
1745c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1746c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1747c58f1c22SToby Isaac     }
1748c58f1c22SToby Isaac   }
17495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht));
17505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points));
17515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1((*labelNew)->numStrata,&points));
1752c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
17535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetICreate(&(*labelNew)->ht[s]));
17545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s])));
1755c58f1c22SToby Isaac   }
1756c58f1c22SToby Isaac   /* Insert points into new strata */
17575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1((*labelNew)->numStrata, &strataIdx));
17585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(leafSection, &pStart, &pEnd));
1759c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
17605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(leafSection, p, &dof));
17615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(leafSection, p, &offset));
1762c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1763c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1764ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1765c58f1c22SToby Isaac     }
1766c58f1c22SToby Isaac   }
1767ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
17685f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s])));
17695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices"));
1770ad8374ffSToby Isaac   }
17715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(points));
17725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIDestroy(&stratumHash));
17735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(leafStrata));
17745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(strataIdx));
17755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&leafSection));
1776c58f1c22SToby Isaac   PetscFunctionReturn(0);
1777c58f1c22SToby Isaac }
1778c58f1c22SToby Isaac 
17797937d9ceSMichael Lange /*@
17807937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
17817937d9ceSMichael Lange 
17825b5e7992SMatthew G. Knepley   Collective on sf
17835b5e7992SMatthew G. Knepley 
17847937d9ceSMichael Lange   Input Parameters:
17857937d9ceSMichael Lange + label - the DMLabel
178684f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
17877937d9ceSMichael Lange 
178884f0b6dfSMatthew G. Knepley   Output Parameters:
178984f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
17907937d9ceSMichael Lange 
17917937d9ceSMichael Lange   Level: developer
17927937d9ceSMichael Lange 
17937937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
17947937d9ceSMichael Lange 
17957937d9ceSMichael Lange .seealso: DMLabelDistribute()
17967937d9ceSMichael Lange @*/
17977937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
17987937d9ceSMichael Lange {
17997937d9ceSMichael Lange   MPI_Comm       comm;
18007937d9ceSMichael Lange   PetscSection   rootSection;
18017937d9ceSMichael Lange   PetscSF        sfLabel;
18027937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
18037937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
18047937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
18057937d9ceSMichael Lange   PetscInt       *rootStrata;
1806d67d17b1SMatthew G. Knepley   const char    *lname;
18077937d9ceSMichael Lange   char          *name;
18087937d9ceSMichael Lange   PetscInt       nameSize;
18097937d9ceSMichael Lange   size_t         len = 0;
18109852e123SBarry Smith   PetscMPIInt    rank, size;
18117937d9ceSMichael Lange 
18127937d9ceSMichael Lange   PetscFunctionBegin;
1813d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1814d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
18155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)sf, &comm));
18165f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
18175f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
18187937d9ceSMichael Lange   /* Bcast name */
1819dd400576SPatrick Sanan   if (rank == 0) {
18205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) label, &lname));
18215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrlen(lname, &len));
1822d67d17b1SMatthew G. Knepley   }
18237937d9ceSMichael Lange   nameSize = len;
18245f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm));
18255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nameSize+1, &name));
18265f80ce2aSJacob Faibussowitsch   if (rank == 0) CHKERRQ(PetscArraycpy(name, lname, nameSize+1));
18275f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm));
18285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, name, labelNew));
18295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(name));
18307937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
18317937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
18327937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
18335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL));
18345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nroots, &leafPoints));
1835dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
18367937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
18378212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
18388212dd46SStefano Zampini 
18398212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
18408212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
18417937d9ceSMichael Lange   }
18425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeBegin(sf, &rootDegree));
18435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeEnd(sf, &rootDegree));
18447937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
18455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nmultiroots, &rootPoints));
18465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints));
18475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints));
18485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(comm,& sfLabel));
18495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER));
18507937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
18515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata));
18527937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
18537937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
18547937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
18555f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(rootSection, idx+d, &dof));
18565f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(rootSection, idx+d, &offset));
18575f80ce2aSJacob Faibussowitsch       for (s = 0; s < dof; s++) CHKERRQ(DMLabelSetValue(*labelNew, p, rootStrata[offset+s]));
18587937d9ceSMichael Lange     }
18597937d9ceSMichael Lange     idx += rootDegree[p];
18607937d9ceSMichael Lange   }
18615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(leafPoints));
18625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(rootStrata));
18635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&rootSection));
18645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sfLabel));
18657937d9ceSMichael Lange   PetscFunctionReturn(0);
18667937d9ceSMichael Lange }
18677937d9ceSMichael Lange 
186884f0b6dfSMatthew G. Knepley /*@
186984f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
187084f0b6dfSMatthew G. Knepley 
18715b5e7992SMatthew G. Knepley   Not collective
18725b5e7992SMatthew G. Knepley 
187384f0b6dfSMatthew G. Knepley   Input Parameter:
187484f0b6dfSMatthew G. Knepley . label - the DMLabel
187584f0b6dfSMatthew G. Knepley 
187684f0b6dfSMatthew G. Knepley   Output Parameters:
187784f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
187884f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
187984f0b6dfSMatthew G. Knepley 
188084f0b6dfSMatthew G. Knepley   Level: developer
188184f0b6dfSMatthew G. Knepley 
188284f0b6dfSMatthew G. Knepley .seealso: DMLabelDistribute()
188384f0b6dfSMatthew G. Knepley @*/
1884c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
1885c58f1c22SToby Isaac {
1886c58f1c22SToby Isaac   IS              vIS;
1887c58f1c22SToby Isaac   const PetscInt *values;
1888c58f1c22SToby Isaac   PetscInt       *points;
1889c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
1890c58f1c22SToby Isaac 
1891c58f1c22SToby Isaac   PetscFunctionBegin;
1892d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
18935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetNumValues(label, &nV));
18945f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetValueIS(label, &vIS));
18955f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(vIS, &values));
1896c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
1897c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
1898c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
1899c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
1900c58f1c22SToby Isaac   }
19015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF, section));
19025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(*section, vS, vE));
1903c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1904c58f1c22SToby Isaac     PetscInt n;
1905c58f1c22SToby Isaac 
19065f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetStratumSize(label, values[v], &n));
19075f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(*section, values[v], n));
1908c58f1c22SToby Isaac   }
19095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(*section));
19105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(*section, &N));
19115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(N, &points));
1912c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1913c58f1c22SToby Isaac     IS              is;
1914c58f1c22SToby Isaac     const PetscInt *spoints;
1915c58f1c22SToby Isaac     PetscInt        dof, off, p;
1916c58f1c22SToby Isaac 
19175f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(*section, values[v], &dof));
19185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(*section, values[v], &off));
19195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetStratumIS(label, values[v], &is));
19205f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(is, &spoints));
1921c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
19225f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(is, &spoints));
19235f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
1924c58f1c22SToby Isaac   }
19255f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(vIS, &values));
19265f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&vIS));
19275f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is));
1928c58f1c22SToby Isaac   PetscFunctionReturn(0);
1929c58f1c22SToby Isaac }
1930c58f1c22SToby Isaac 
193184f0b6dfSMatthew G. Knepley /*@
1932c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
1933c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
1934c58f1c22SToby Isaac 
19355b5e7992SMatthew G. Knepley   Collective on sf
19365b5e7992SMatthew G. Knepley 
1937c58f1c22SToby Isaac   Input Parameters:
1938c58f1c22SToby Isaac   + s - The PetscSection for the local field layout
1939c58f1c22SToby Isaac   . sf - The SF describing parallel layout of the section points
1940c58f1c22SToby Isaac   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1941c58f1c22SToby Isaac   . label - The label specifying the points
1942c58f1c22SToby Isaac   - labelValue - The label stratum specifying the points
1943c58f1c22SToby Isaac 
1944c58f1c22SToby Isaac   Output Parameter:
1945c58f1c22SToby Isaac   . gsection - The PetscSection for the global field layout
1946c58f1c22SToby Isaac 
1947c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
1948c58f1c22SToby Isaac 
1949c58f1c22SToby Isaac   Level: developer
1950c58f1c22SToby Isaac 
1951c58f1c22SToby Isaac .seealso: PetscSectionCreate()
1952c58f1c22SToby Isaac @*/
1953c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
1954c58f1c22SToby Isaac {
1955c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
1956c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
1957c58f1c22SToby Isaac 
1958c58f1c22SToby Isaac   PetscFunctionBegin;
1959d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1960d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1961d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
19625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection));
19635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(s, &pStart, &pEnd));
19645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(*gsection, pStart, pEnd));
19655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL));
1966c58f1c22SToby Isaac   if (nroots >= 0) {
19672c71b3e2SJacob Faibussowitsch     PetscCheckFalse(nroots < pEnd-pStart,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
19685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(nroots, &neg));
1969c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
19705f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(nroots, &tmpOff));
1971c58f1c22SToby Isaac     } else {
1972c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
1973c58f1c22SToby Isaac     }
1974c58f1c22SToby Isaac   }
1975c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
1976c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
1977c58f1c22SToby Isaac     PetscInt value;
1978c58f1c22SToby Isaac 
19795f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetValue(label, p, &value));
1980c58f1c22SToby Isaac     if (value != labelValue) continue;
19815f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(s, p, &dof));
19825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(*gsection, p, dof));
19835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetConstraintDof(s, p, &cdof));
19845f80ce2aSJacob Faibussowitsch     if (!includeConstraints && cdof > 0) CHKERRQ(PetscSectionSetConstraintDof(*gsection, p, cdof));
1985c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
1986c58f1c22SToby Isaac   }
19875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUpBC(*gsection));
1988c58f1c22SToby Isaac   if (nroots >= 0) {
19895f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
19905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
1991c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1992c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
1993c58f1c22SToby Isaac     }
1994c58f1c22SToby Isaac   }
1995c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
1996c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1997c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
1998c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
1999c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
2000c58f1c22SToby Isaac   }
20015f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s)));
2002c58f1c22SToby Isaac   globalOff -= off;
2003c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
2004c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
2005c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
2006c58f1c22SToby Isaac   }
2007c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
2008c58f1c22SToby Isaac   if (nroots >= 0) {
20095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
20105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE));
2011c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
2012c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
2013c58f1c22SToby Isaac     }
2014c58f1c22SToby Isaac   }
20155f80ce2aSJacob Faibussowitsch   if (nroots >= 0 && nroots > pEnd-pStart) CHKERRQ(PetscFree(tmpOff));
20165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(neg));
2017c58f1c22SToby Isaac   PetscFunctionReturn(0);
2018c58f1c22SToby Isaac }
2019c58f1c22SToby Isaac 
20205fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
20215fdea053SToby Isaac {
20225fdea053SToby Isaac   DMLabel           label;
20235fdea053SToby Isaac   PetscCopyMode     *modes;
20245fdea053SToby Isaac   PetscInt          *sizes;
20255fdea053SToby Isaac   const PetscInt    ***perms;
20265fdea053SToby Isaac   const PetscScalar ***rots;
20275fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
20285fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
20295fdea053SToby Isaac } PetscSectionSym_Label;
20305fdea053SToby Isaac 
20315fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
20325fdea053SToby Isaac {
20335fdea053SToby Isaac   PetscInt              i, j;
20345fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
20355fdea053SToby Isaac 
20365fdea053SToby Isaac   PetscFunctionBegin;
20375fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
20385fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
20395fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
20405f80ce2aSJacob Faibussowitsch         if (sl->perms[i]) CHKERRQ(PetscFree(sl->perms[i][j]));
20415f80ce2aSJacob Faibussowitsch         if (sl->rots[i]) CHKERRQ(PetscFree(sl->rots[i][j]));
20425fdea053SToby Isaac       }
20435fdea053SToby Isaac       if (sl->perms[i]) {
20445fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
20455fdea053SToby Isaac 
20465f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(perms));
20475fdea053SToby Isaac       }
20485fdea053SToby Isaac       if (sl->rots[i]) {
20495fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
20505fdea053SToby Isaac 
20515f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(rots));
20525fdea053SToby Isaac       }
20535fdea053SToby Isaac     }
20545fdea053SToby Isaac   }
20555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients));
20565f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroy(&sl->label));
20575fdea053SToby Isaac   sl->numStrata = 0;
20585fdea053SToby Isaac   PetscFunctionReturn(0);
20595fdea053SToby Isaac }
20605fdea053SToby Isaac 
20615fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
20625fdea053SToby Isaac {
20635fdea053SToby Isaac   PetscFunctionBegin;
20645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSymLabelReset(sym));
20655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(sym->data));
20665fdea053SToby Isaac   PetscFunctionReturn(0);
20675fdea053SToby Isaac }
20685fdea053SToby Isaac 
20695fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
20705fdea053SToby Isaac {
20715fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
20725fdea053SToby Isaac   PetscBool             isAscii;
20735fdea053SToby Isaac   DMLabel               label = sl->label;
2074d67d17b1SMatthew G. Knepley   const char           *name;
20755fdea053SToby Isaac 
20765fdea053SToby Isaac   PetscFunctionBegin;
20775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii));
20785fdea053SToby Isaac   if (isAscii) {
20795fdea053SToby Isaac     PetscInt          i, j, k;
20805fdea053SToby Isaac     PetscViewerFormat format;
20815fdea053SToby Isaac 
20825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer,&format));
20835fdea053SToby Isaac     if (label) {
20845f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerGetFormat(viewer,&format));
20855fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
20865f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPushTab(viewer));
20875f80ce2aSJacob Faibussowitsch         CHKERRQ(DMLabelView(label, viewer));
20885f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPopTab(viewer));
20895fdea053SToby Isaac       } else {
20905f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectGetName((PetscObject) sl->label, &name));
20915f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name));
20925fdea053SToby Isaac       }
20935fdea053SToby Isaac     } else {
20945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "No label given\n"));
20955fdea053SToby Isaac     }
20965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPushTab(viewer));
20975fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
20985fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
20995fdea053SToby Isaac 
21005fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
21015f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point): no symmetries\n", value, sl->sizes[i]));
21025fdea053SToby Isaac       } else {
21035f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point):\n", value, sl->sizes[i]));
21045f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPushTab(viewer));
21055f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "Orientation range: [%D, %D)\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]));
21065fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
21075f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPushTab(viewer));
21085fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
21095fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
21105f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscViewerASCIIPrintf(viewer, "Orientation %D: identity\n",j));
21115fdea053SToby Isaac             } else {
21125fdea053SToby Isaac               PetscInt tab;
21135fdea053SToby Isaac 
21145f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscViewerASCIIPrintf(viewer, "Orientation %D:\n",j));
21155f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscViewerASCIIPushTab(viewer));
21165f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscViewerASCIIGetTab(viewer,&tab));
21175fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
21185f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Permutation:"));
21195f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIISetTab(viewer,0));
21205f80ce2aSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) CHKERRQ(PetscViewerASCIIPrintf(viewer," %D",sl->perms[i][j][k]));
21215f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
21225f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIISetTab(viewer,tab));
21235fdea053SToby Isaac               }
21245fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
21255f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Rotations:  "));
21265f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIISetTab(viewer,0));
21275fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
21285f80ce2aSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) CHKERRQ(PetscViewerASCIIPrintf(viewer," %+f+i*%+f",PetscRealPart(sl->rots[i][j][k]),PetscImaginaryPart(sl->rots[i][j][k])));
21295fdea053SToby Isaac #else
21305f80ce2aSJacob Faibussowitsch                 for (k = 0; k < sl->sizes[i]; k++) CHKERRQ(PetscViewerASCIIPrintf(viewer," %+f",sl->rots[i][j][k]));
21315fdea053SToby Isaac #endif
21325f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
21335f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIISetTab(viewer,tab));
21345fdea053SToby Isaac               }
21355f80ce2aSJacob Faibussowitsch               CHKERRQ(PetscViewerASCIIPopTab(viewer));
21365fdea053SToby Isaac             }
21375fdea053SToby Isaac           }
21385f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPopTab(viewer));
21395fdea053SToby Isaac         }
21405f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPopTab(viewer));
21415fdea053SToby Isaac       }
21425fdea053SToby Isaac     }
21435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPopTab(viewer));
21445fdea053SToby Isaac   }
21455fdea053SToby Isaac   PetscFunctionReturn(0);
21465fdea053SToby Isaac }
21475fdea053SToby Isaac 
21485fdea053SToby Isaac /*@
21495fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
21505fdea053SToby Isaac 
21515fdea053SToby Isaac   Logically collective on sym
21525fdea053SToby Isaac 
21535fdea053SToby Isaac   Input parameters:
21545fdea053SToby Isaac + sym - the section symmetries
21555fdea053SToby Isaac - label - the DMLabel describing the types of points
21565fdea053SToby Isaac 
21575fdea053SToby Isaac   Level: developer:
21585fdea053SToby Isaac 
21595fdea053SToby Isaac .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreateLabel(), PetscSectionGetPointSyms()
21605fdea053SToby Isaac @*/
21615fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
21625fdea053SToby Isaac {
21635fdea053SToby Isaac   PetscSectionSym_Label *sl;
21645fdea053SToby Isaac 
21655fdea053SToby Isaac   PetscFunctionBegin;
21665fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
21675fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
21685f80ce2aSJacob Faibussowitsch   if (sl->label && sl->label != label) CHKERRQ(PetscSectionSymLabelReset(sym));
21695fdea053SToby Isaac   if (label) {
21705fdea053SToby Isaac     sl->label = label;
21715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject) label));
21725f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetNumValues(label,&sl->numStrata));
21735f80ce2aSJacob Faibussowitsch     CHKERRQ(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));
21745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode)));
21755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt)));
21765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **)));
21775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **)));
21785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2])));
21795fdea053SToby Isaac   }
21805fdea053SToby Isaac   PetscFunctionReturn(0);
21815fdea053SToby Isaac }
21825fdea053SToby Isaac 
21835fdea053SToby Isaac /*@C
2184b004864fSMatthew G. Knepley   PetscSectionSymLabelGetStratum - get the symmetries for the orientations of a stratum
2185b004864fSMatthew G. Knepley 
2186b004864fSMatthew G. Knepley   Logically collective on sym
2187b004864fSMatthew G. Knepley 
2188b004864fSMatthew G. Knepley   Input Parameters:
2189b004864fSMatthew G. Knepley + sym       - the section symmetries
2190b004864fSMatthew G. Knepley - stratum   - the stratum value in the label that we are assigning symmetries for
2191b004864fSMatthew G. Knepley 
2192b004864fSMatthew G. Knepley   Output Parameters:
2193b004864fSMatthew G. Knepley + size      - the number of dofs for points in the stratum of the label
2194b004864fSMatthew G. Knepley . minOrient - the smallest orientation for a point in this stratum
2195b004864fSMatthew G. Knepley . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
2196b004864fSMatthew G. Knepley . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2197b004864fSMatthew G. Knepley - rots      - NULL if there are no rotations, or (maxOrient - minOrient) sets of rotations, one for each orientation.  A NULL set of orientations is the identity
2198b004864fSMatthew G. Knepley 
2199b004864fSMatthew G. Knepley   Level: developer
2200b004864fSMatthew G. Knepley 
2201b004864fSMatthew G. Knepley .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
2202b004864fSMatthew G. Knepley @*/
2203b004864fSMatthew G. Knepley PetscErrorCode PetscSectionSymLabelGetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt *size, PetscInt *minOrient, PetscInt *maxOrient, const PetscInt ***perms, const PetscScalar ***rots)
2204b004864fSMatthew G. Knepley {
2205b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl;
2206b004864fSMatthew G. Knepley   const char            *name;
2207b004864fSMatthew G. Knepley   PetscInt               i;
2208b004864fSMatthew G. Knepley 
2209b004864fSMatthew G. Knepley   PetscFunctionBegin;
2210b004864fSMatthew G. Knepley   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
2211b004864fSMatthew G. Knepley   sl = (PetscSectionSym_Label *) sym->data;
2212b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
2213b004864fSMatthew G. Knepley   for (i = 0; i <= sl->numStrata; i++) {
2214b004864fSMatthew G. Knepley     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
2215b004864fSMatthew G. Knepley 
2216b004864fSMatthew G. Knepley     if (stratum == value) break;
2217b004864fSMatthew G. Knepley   }
22185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) sl->label, &name));
2219b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %" PetscInt_FMT " not found in label %s", stratum, name);
2220b004864fSMatthew G. Knepley   if (size)      {PetscValidIntPointer(size, 3);      *size      = sl->sizes[i];}
2221b004864fSMatthew G. Knepley   if (minOrient) {PetscValidIntPointer(minOrient, 4); *minOrient = sl->minMaxOrients[i][0];}
2222b004864fSMatthew G. Knepley   if (maxOrient) {PetscValidIntPointer(maxOrient, 5); *maxOrient = sl->minMaxOrients[i][1];}
2223b004864fSMatthew G. Knepley   if (perms)     {PetscValidPointer(perms, 6);        *perms     = sl->perms[i] ? &sl->perms[i][sl->minMaxOrients[i][0]] : NULL;}
2224b004864fSMatthew G. Knepley   if (rots)      {PetscValidPointer(rots, 7);         *rots      = sl->rots[i]  ? &sl->rots[i][sl->minMaxOrients[i][0]]  : NULL;}
2225b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2226b004864fSMatthew G. Knepley }
2227b004864fSMatthew G. Knepley 
2228b004864fSMatthew G. Knepley /*@C
22295fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
22305fdea053SToby Isaac 
22315b5e7992SMatthew G. Knepley   Logically collective on sym
22325fdea053SToby Isaac 
22335fdea053SToby Isaac   InputParameters:
22345b5e7992SMatthew G. Knepley + sym       - the section symmetries
22355fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
22365fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
22375fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
22385fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
22395fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
22405fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2241a2b725a8SWilliam Gropp - rots      - NULL if there are no rotations, or (maxOrient - minOrient) sets of rotations, one for each orientation.  A NULL set of orientations is the identity
22425fdea053SToby Isaac 
22435fdea053SToby Isaac   Level: developer
22445fdea053SToby Isaac 
2245b004864fSMatthew G. Knepley .seealso: PetscSectionSymLabelGetStratum(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
22465fdea053SToby Isaac @*/
22475fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
22485fdea053SToby Isaac {
22495fdea053SToby Isaac   PetscSectionSym_Label *sl;
2250d67d17b1SMatthew G. Knepley   const char            *name;
2251d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
22525fdea053SToby Isaac 
22535fdea053SToby Isaac   PetscFunctionBegin;
22545fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
22555fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
2256b004864fSMatthew G. Knepley   PetscCheck(sl->label, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_WRONGSTATE, "No label set yet");
22575fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
22585fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
22595fdea053SToby Isaac 
22605fdea053SToby Isaac     if (stratum == value) break;
22615fdea053SToby Isaac   }
22625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) sl->label, &name));
2263b004864fSMatthew G. Knepley   PetscCheck(i <= sl->numStrata, PetscObjectComm((PetscObject) sym), PETSC_ERR_ARG_OUTOFRANGE, "Stratum %D not found in label %s", stratum, name);
22645fdea053SToby Isaac   sl->sizes[i] = size;
22655fdea053SToby Isaac   sl->modes[i] = mode;
22665fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
22675fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
22685fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
22695fdea053SToby Isaac     if (perms) {
22705fdea053SToby Isaac       PetscInt    **ownPerms;
22715fdea053SToby Isaac 
22725f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(maxOrient - minOrient,&ownPerms));
22735fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
22745fdea053SToby Isaac         if (perms[j]) {
22755f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscMalloc1(size,&ownPerms[j]));
22765fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
22775fdea053SToby Isaac         }
22785fdea053SToby Isaac       }
22795fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
22805fdea053SToby Isaac     }
22815fdea053SToby Isaac     if (rots) {
22825fdea053SToby Isaac       PetscScalar **ownRots;
22835fdea053SToby Isaac 
22845f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(maxOrient - minOrient,&ownRots));
22855fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
22865fdea053SToby Isaac         if (rots[j]) {
22875f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscMalloc1(size,&ownRots[j]));
22885fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
22895fdea053SToby Isaac         }
22905fdea053SToby Isaac       }
22915fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
22925fdea053SToby Isaac     }
22935fdea053SToby Isaac   } else {
22945fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
22955fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
22965fdea053SToby Isaac   }
22975fdea053SToby Isaac   PetscFunctionReturn(0);
22985fdea053SToby Isaac }
22995fdea053SToby Isaac 
23005fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
23015fdea053SToby Isaac {
23025fdea053SToby Isaac   PetscInt              i, j, numStrata;
23035fdea053SToby Isaac   PetscSectionSym_Label *sl;
23045fdea053SToby Isaac   DMLabel               label;
23055fdea053SToby Isaac 
23065fdea053SToby Isaac   PetscFunctionBegin;
23075fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
23085fdea053SToby Isaac   numStrata = sl->numStrata;
23095fdea053SToby Isaac   label     = sl->label;
23105fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
23115fdea053SToby Isaac     PetscInt point = points[2*i];
23125fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
23135fdea053SToby Isaac 
23145fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
23155fdea053SToby Isaac       if (label->validIS[j]) {
23165fdea053SToby Isaac         PetscInt k;
23175fdea053SToby Isaac 
23185f80ce2aSJacob Faibussowitsch         CHKERRQ(ISLocate(label->points[j],point,&k));
23195fdea053SToby Isaac         if (k >= 0) break;
23205fdea053SToby Isaac       } else {
23215fdea053SToby Isaac         PetscBool has;
23225fdea053SToby Isaac 
23235f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscHSetIHas(label->ht[j], point, &has));
23245fdea053SToby Isaac         if (has) break;
23255fdea053SToby Isaac       }
23265fdea053SToby Isaac     }
23272c71b3e2SJacob Faibussowitsch     PetscCheckFalse((sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) && (ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1]),PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"point %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);
23285fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
23295fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
23305fdea053SToby Isaac   }
23315fdea053SToby Isaac   PetscFunctionReturn(0);
23325fdea053SToby Isaac }
23335fdea053SToby Isaac 
2334b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymCopy_Label(PetscSectionSym sym, PetscSectionSym nsym)
2335b004864fSMatthew G. Knepley {
2336b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) nsym->data;
2337b004864fSMatthew G. Knepley   IS                     valIS;
2338b004864fSMatthew G. Knepley   const PetscInt        *values;
2339b004864fSMatthew G. Knepley   PetscInt               Nv, v;
2340b004864fSMatthew G. Knepley 
2341b004864fSMatthew G. Knepley   PetscFunctionBegin;
23425f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetNumValues(sl->label, &Nv));
23435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetValueIS(sl->label, &valIS));
23445f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(valIS, &values));
2345b004864fSMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
2346b004864fSMatthew G. Knepley     const PetscInt      val = values[v];
2347b004864fSMatthew G. Knepley     PetscInt            size, minOrient, maxOrient;
2348b004864fSMatthew G. Knepley     const PetscInt    **perms;
2349b004864fSMatthew G. Knepley     const PetscScalar **rots;
2350b004864fSMatthew G. Knepley 
23515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSymLabelGetStratum(sym,  val, &size, &minOrient, &maxOrient, &perms, &rots));
23525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSymLabelSetStratum(nsym, val,  size,  minOrient,  maxOrient, PETSC_COPY_VALUES, perms, rots));
2353b004864fSMatthew G. Knepley   }
23545f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&valIS));
2355b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2356b004864fSMatthew G. Knepley }
2357b004864fSMatthew G. Knepley 
2358b004864fSMatthew G. Knepley static PetscErrorCode PetscSectionSymDistribute_Label(PetscSectionSym sym, PetscSF migrationSF, PetscSectionSym *dsym)
2359b004864fSMatthew G. Knepley {
2360b004864fSMatthew G. Knepley   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
2361b004864fSMatthew G. Knepley   DMLabel                dlabel;
2362b004864fSMatthew G. Knepley 
2363b004864fSMatthew G. Knepley   PetscFunctionBegin;
23645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDistribute(sl->label, migrationSF, &dlabel));
23655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSymCreateLabel(PetscObjectComm((PetscObject) sym), dlabel, dsym));
23665f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroy(&dlabel));
23675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSymCopy(sym, *dsym));
2368b004864fSMatthew G. Knepley   PetscFunctionReturn(0);
2369b004864fSMatthew G. Knepley }
2370b004864fSMatthew G. Knepley 
23715fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
23725fdea053SToby Isaac {
23735fdea053SToby Isaac   PetscSectionSym_Label *sl;
23745fdea053SToby Isaac 
23755fdea053SToby Isaac   PetscFunctionBegin;
23765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(sym,&sl));
23775fdea053SToby Isaac   sym->ops->getpoints  = PetscSectionSymGetPoints_Label;
2378b004864fSMatthew G. Knepley   sym->ops->distribute = PetscSectionSymDistribute_Label;
2379b004864fSMatthew G. Knepley   sym->ops->copy       = PetscSectionSymCopy_Label;
23805fdea053SToby Isaac   sym->ops->view       = PetscSectionSymView_Label;
23815fdea053SToby Isaac   sym->ops->destroy    = PetscSectionSymDestroy_Label;
23825fdea053SToby Isaac   sym->data            = (void *) sl;
23835fdea053SToby Isaac   PetscFunctionReturn(0);
23845fdea053SToby Isaac }
23855fdea053SToby Isaac 
23865fdea053SToby Isaac /*@
23875fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
23885fdea053SToby Isaac 
23895fdea053SToby Isaac   Collective
23905fdea053SToby Isaac 
23915fdea053SToby Isaac   Input Parameters:
23925fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
23935fdea053SToby Isaac - label - the label defining the strata
23945fdea053SToby Isaac 
23955fdea053SToby Isaac   Output Parameters:
23965fdea053SToby Isaac . sym - the section symmetries
23975fdea053SToby Isaac 
23985fdea053SToby Isaac   Level: developer
23995fdea053SToby Isaac 
24005fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms()
24015fdea053SToby Isaac @*/
24025fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
24035fdea053SToby Isaac {
24045fdea053SToby Isaac   PetscFunctionBegin;
24055f80ce2aSJacob Faibussowitsch   CHKERRQ(DMInitializePackage());
24065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSymCreate(comm,sym));
24075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL));
24085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSymLabelSetLabel(*sym,label));
24095fdea053SToby Isaac   PetscFunctionReturn(0);
24105fdea053SToby Isaac }
2411