xref: /petsc/src/dm/label/dmlabel.c (revision 1d04cbbefc3422143dc520c67b0078a7a21900d3)
15fdea053SToby Isaac #include <petscdm.h>
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h>   /*I      "petscdmlabel.h"   I*/
3ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h>   /*I      "petscsection.h"   I*/
4c58f1c22SToby Isaac #include <petscsf.h>
5ea844a1aSMatthew Knepley #include <petscsection.h>
6c58f1c22SToby Isaac 
7c58f1c22SToby Isaac /*@C
8c58f1c22SToby Isaac   DMLabelCreate - Create a DMLabel object, which is a multimap
9c58f1c22SToby Isaac 
105b5e7992SMatthew G. Knepley   Collective
115b5e7992SMatthew G. Knepley 
12d67d17b1SMatthew G. Knepley   Input parameters:
13d67d17b1SMatthew G. Knepley + comm - The communicator, usually PETSC_COMM_SELF
14d67d17b1SMatthew G. Knepley - name - The label name
15c58f1c22SToby Isaac 
16c58f1c22SToby Isaac   Output parameter:
17c58f1c22SToby Isaac . label - The DMLabel
18c58f1c22SToby Isaac 
19c58f1c22SToby Isaac   Level: beginner
20c58f1c22SToby Isaac 
2105ab7a9fSVaclav Hapla   Notes:
2205ab7a9fSVaclav Hapla   The label name is actually usual PetscObject name.
2305ab7a9fSVaclav Hapla   One can get/set it with PetscObjectGetName()/PetscObjectSetName().
2405ab7a9fSVaclav Hapla 
25c58f1c22SToby Isaac .seealso: DMLabelDestroy()
26c58f1c22SToby Isaac @*/
27d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelCreate(MPI_Comm comm, const char name[], DMLabel *label)
28c58f1c22SToby Isaac {
29c58f1c22SToby Isaac   PetscErrorCode ierr;
30c58f1c22SToby Isaac 
31c58f1c22SToby Isaac   PetscFunctionBegin;
32064a246eSJacob Faibussowitsch   PetscValidPointer(label,3);
33d67d17b1SMatthew G. Knepley   ierr = DMInitializePackage();CHKERRQ(ierr);
34c58f1c22SToby Isaac 
35d67d17b1SMatthew G. Knepley   ierr = PetscHeaderCreate(*label,DMLABEL_CLASSID,"DMLabel","DMLabel","DM",comm,DMLabelDestroy,DMLabelView);CHKERRQ(ierr);
36d67d17b1SMatthew G. Knepley 
37c58f1c22SToby Isaac   (*label)->numStrata      = 0;
385aa44df4SToby Isaac   (*label)->defaultValue   = -1;
39c58f1c22SToby Isaac   (*label)->stratumValues  = NULL;
40ad8374ffSToby Isaac   (*label)->validIS        = NULL;
41c58f1c22SToby Isaac   (*label)->stratumSizes   = NULL;
42c58f1c22SToby Isaac   (*label)->points         = NULL;
43c58f1c22SToby Isaac   (*label)->ht             = NULL;
44c58f1c22SToby Isaac   (*label)->pStart         = -1;
45c58f1c22SToby Isaac   (*label)->pEnd           = -1;
46c58f1c22SToby Isaac   (*label)->bt             = NULL;
47b9907514SLisandro Dalcin   ierr = PetscHMapICreate(&(*label)->hmap);CHKERRQ(ierr);
48d67d17b1SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *label, name);CHKERRQ(ierr);
49c58f1c22SToby Isaac   PetscFunctionReturn(0);
50c58f1c22SToby Isaac }
51c58f1c22SToby Isaac 
52c58f1c22SToby Isaac /*
53c58f1c22SToby Isaac   DMLabelMakeValid_Private - Transfer stratum data from the hash format to the sorted list format
54c58f1c22SToby Isaac 
555b5e7992SMatthew G. Knepley   Not collective
565b5e7992SMatthew G. Knepley 
57c58f1c22SToby Isaac   Input parameter:
58c58f1c22SToby Isaac + label - The DMLabel
59c58f1c22SToby Isaac - v - The stratum value
60c58f1c22SToby Isaac 
61c58f1c22SToby Isaac   Output parameter:
62c58f1c22SToby Isaac . label - The DMLabel with stratum in sorted list format
63c58f1c22SToby Isaac 
64c58f1c22SToby Isaac   Level: developer
65c58f1c22SToby Isaac 
66c58f1c22SToby Isaac .seealso: DMLabelCreate()
67c58f1c22SToby Isaac */
68c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeValid_Private(DMLabel label, PetscInt v)
69c58f1c22SToby Isaac {
70277ea44aSLisandro Dalcin   IS             is;
71b9907514SLisandro Dalcin   PetscInt       off = 0, *pointArray, p;
72c58f1c22SToby Isaac   PetscErrorCode ierr;
73c58f1c22SToby Isaac 
74b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && label->validIS[v]) return 0;
75c58f1c22SToby Isaac   PetscFunctionBegin;
760c3c4a36SLisandro Dalcin   if (v < 0 || v >= label->numStrata) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeValid_Private\n", v);
77e8f14785SLisandro Dalcin   ierr = PetscHSetIGetSize(label->ht[v], &label->stratumSizes[v]);CHKERRQ(ierr);
78ad8374ffSToby Isaac   ierr = PetscMalloc1(label->stratumSizes[v], &pointArray);CHKERRQ(ierr);
79e8f14785SLisandro Dalcin   ierr = PetscHSetIGetElems(label->ht[v], &off, pointArray);CHKERRQ(ierr);
80b9907514SLisandro Dalcin   ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr);
81ad8374ffSToby Isaac   ierr = PetscSortInt(label->stratumSizes[v], pointArray);CHKERRQ(ierr);
82c58f1c22SToby Isaac   if (label->bt) {
83c58f1c22SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
84ad8374ffSToby Isaac       const PetscInt point = pointArray[p];
85c58f1c22SToby Isaac       if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
86c58f1c22SToby Isaac       ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr);
87c58f1c22SToby Isaac     }
88c58f1c22SToby Isaac   }
89ba2698f1SMatthew G. Knepley   if (label->stratumSizes[v] > 0 && pointArray[label->stratumSizes[v]-1] == pointArray[0] + label->stratumSizes[v]-1) {
90ba2698f1SMatthew G. Knepley     ierr = ISCreateStride(PETSC_COMM_SELF, label->stratumSizes[v], pointArray[0], 1, &is);CHKERRQ(ierr);
91ba2698f1SMatthew G. Knepley     ierr = PetscFree(pointArray);CHKERRQ(ierr);
92ba2698f1SMatthew G. Knepley   } else {
93277ea44aSLisandro Dalcin     ierr = ISCreateGeneral(PETSC_COMM_SELF, label->stratumSizes[v], pointArray, PETSC_OWN_POINTER, &is);CHKERRQ(ierr);
94ba2698f1SMatthew G. Knepley   }
95277ea44aSLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) is, "indices");CHKERRQ(ierr);
96277ea44aSLisandro Dalcin   label->points[v]  = is;
97ad8374ffSToby Isaac   label->validIS[v] = PETSC_TRUE;
98d67d17b1SMatthew G. Knepley   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
99c58f1c22SToby Isaac   PetscFunctionReturn(0);
100c58f1c22SToby Isaac }
101c58f1c22SToby Isaac 
102c58f1c22SToby Isaac /*
103c58f1c22SToby Isaac   DMLabelMakeAllValid_Private - Transfer all strata from the hash format to the sorted list format
104c58f1c22SToby Isaac 
1055b5e7992SMatthew G. Knepley   Not collective
1065b5e7992SMatthew G. Knepley 
107c58f1c22SToby Isaac   Input parameter:
108c58f1c22SToby Isaac . label - The DMLabel
109c58f1c22SToby Isaac 
110c58f1c22SToby Isaac   Output parameter:
111c58f1c22SToby Isaac . label - The DMLabel with all strata in sorted list format
112c58f1c22SToby Isaac 
113c58f1c22SToby Isaac   Level: developer
114c58f1c22SToby Isaac 
115c58f1c22SToby Isaac .seealso: DMLabelCreate()
116c58f1c22SToby Isaac */
117c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeAllValid_Private(DMLabel label)
118c58f1c22SToby Isaac {
119c58f1c22SToby Isaac   PetscInt       v;
120c58f1c22SToby Isaac   PetscErrorCode ierr;
121c58f1c22SToby Isaac 
122c58f1c22SToby Isaac   PetscFunctionBegin;
123c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; v++) {
124c58f1c22SToby Isaac     ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
125c58f1c22SToby Isaac   }
126c58f1c22SToby Isaac   PetscFunctionReturn(0);
127c58f1c22SToby Isaac }
128c58f1c22SToby Isaac 
129c58f1c22SToby Isaac /*
130c58f1c22SToby Isaac   DMLabelMakeInvalid_Private - Transfer stratum data from the sorted list format to the hash format
131c58f1c22SToby Isaac 
1325b5e7992SMatthew G. Knepley   Not collective
1335b5e7992SMatthew G. Knepley 
134c58f1c22SToby Isaac   Input parameter:
135c58f1c22SToby Isaac + label - The DMLabel
136c58f1c22SToby Isaac - v - The stratum value
137c58f1c22SToby Isaac 
138c58f1c22SToby Isaac   Output parameter:
139c58f1c22SToby Isaac . label - The DMLabel with stratum in hash format
140c58f1c22SToby Isaac 
141c58f1c22SToby Isaac   Level: developer
142c58f1c22SToby Isaac 
143c58f1c22SToby Isaac .seealso: DMLabelCreate()
144c58f1c22SToby Isaac */
145c58f1c22SToby Isaac static PetscErrorCode DMLabelMakeInvalid_Private(DMLabel label, PetscInt v)
146c58f1c22SToby Isaac {
147c58f1c22SToby Isaac   PetscInt       p;
148ad8374ffSToby Isaac   const PetscInt *points;
149c58f1c22SToby Isaac   PetscErrorCode ierr;
150c58f1c22SToby Isaac 
151b9907514SLisandro Dalcin   if (PetscLikely(v >= 0 && v < label->numStrata) && !label->validIS[v]) return 0;
152c58f1c22SToby Isaac   PetscFunctionBegin;
1530c3c4a36SLisandro Dalcin   if (v < 0 || v >= label->numStrata) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to access invalid stratum %D in DMLabelMakeInvalid_Private\n", v);
154ad8374ffSToby Isaac   if (label->points[v]) {
155ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
156e8f14785SLisandro Dalcin     for (p = 0; p < label->stratumSizes[v]; ++p) {
157e8f14785SLisandro Dalcin       ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);
158e8f14785SLisandro Dalcin     }
159ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr);
160ad8374ffSToby Isaac     ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr);
161ad8374ffSToby Isaac   }
162ad8374ffSToby Isaac   label->validIS[v] = PETSC_FALSE;
163c58f1c22SToby Isaac   PetscFunctionReturn(0);
164c58f1c22SToby Isaac }
165c58f1c22SToby Isaac 
166b9907514SLisandro Dalcin #if !defined(DMLABEL_LOOKUP_THRESHOLD)
167b9907514SLisandro Dalcin #define DMLABEL_LOOKUP_THRESHOLD 16
168b9907514SLisandro Dalcin #endif
169b9907514SLisandro Dalcin 
1700c3c4a36SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupStratum(DMLabel label, PetscInt value, PetscInt *index)
1710c3c4a36SLisandro Dalcin {
1720c3c4a36SLisandro Dalcin   PetscInt       v;
173b9907514SLisandro Dalcin   PetscErrorCode ierr;
1740e79e033SBarry Smith 
1750c3c4a36SLisandro Dalcin   PetscFunctionBegin;
1760e79e033SBarry Smith   *index = -1;
177b9907514SLisandro Dalcin   if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
178b9907514SLisandro Dalcin     for (v = 0; v < label->numStrata; ++v)
179b9907514SLisandro Dalcin       if (label->stratumValues[v] == value) {*index = v; break;}
180b9907514SLisandro Dalcin   } else {
181b9907514SLisandro Dalcin     ierr = PetscHMapIGet(label->hmap, value, index);CHKERRQ(ierr);
1820e79e033SBarry Smith   }
18376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) { /* Check strata hash map consistency */
18490e9b2aeSLisandro Dalcin     PetscInt len, loc = -1;
18590e9b2aeSLisandro Dalcin     ierr = PetscHMapIGetSize(label->hmap, &len);CHKERRQ(ierr);
18690e9b2aeSLisandro Dalcin     if (len != label->numStrata) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map size");
18790e9b2aeSLisandro Dalcin     if (label->numStrata <= DMLABEL_LOOKUP_THRESHOLD) {
18890e9b2aeSLisandro Dalcin       ierr = PetscHMapIGet(label->hmap, value, &loc);CHKERRQ(ierr);
18990e9b2aeSLisandro Dalcin     } else {
19090e9b2aeSLisandro Dalcin       for (v = 0; v < label->numStrata; ++v)
19190e9b2aeSLisandro Dalcin         if (label->stratumValues[v] == value) {loc = v; break;}
19290e9b2aeSLisandro Dalcin     }
19390e9b2aeSLisandro Dalcin     if (loc != *index) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent strata hash map lookup");
19490e9b2aeSLisandro Dalcin   }
1950c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
1960c3c4a36SLisandro Dalcin }
1970c3c4a36SLisandro Dalcin 
198b9907514SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelNewStratum(DMLabel label, PetscInt value, PetscInt *index)
199c58f1c22SToby Isaac {
200b9907514SLisandro Dalcin   PetscInt       v;
201b9907514SLisandro Dalcin   PetscInt      *tmpV;
202b9907514SLisandro Dalcin   PetscInt      *tmpS;
203b9907514SLisandro Dalcin   PetscHSetI    *tmpH, ht;
204b9907514SLisandro Dalcin   IS            *tmpP, is;
205c58f1c22SToby Isaac   PetscBool     *tmpB;
206b9907514SLisandro Dalcin   PetscHMapI     hmap = label->hmap;
207c58f1c22SToby Isaac   PetscErrorCode ierr;
208c58f1c22SToby Isaac 
209c58f1c22SToby Isaac   PetscFunctionBegin;
210b9907514SLisandro Dalcin   v    = label->numStrata;
211b9907514SLisandro Dalcin   tmpV = label->stratumValues;
212b9907514SLisandro Dalcin   tmpS = label->stratumSizes;
213b9907514SLisandro Dalcin   tmpH = label->ht;
214b9907514SLisandro Dalcin   tmpP = label->points;
215b9907514SLisandro Dalcin   tmpB = label->validIS;
2168e1f8cf0SLisandro Dalcin   { /* TODO: PetscRealloc() is broken, use malloc+memcpy+free  */
2178e1f8cf0SLisandro Dalcin     PetscInt   *oldV = tmpV;
2188e1f8cf0SLisandro Dalcin     PetscInt   *oldS = tmpS;
2198e1f8cf0SLisandro Dalcin     PetscHSetI *oldH = tmpH;
2208e1f8cf0SLisandro Dalcin     IS         *oldP = tmpP;
2218e1f8cf0SLisandro Dalcin     PetscBool  *oldB = tmpB;
2228e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpV), &tmpV);CHKERRQ(ierr);
2238e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpS), &tmpS);CHKERRQ(ierr);
2248e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpH), &tmpH);CHKERRQ(ierr);
2258e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpP), &tmpP);CHKERRQ(ierr);
2268e1f8cf0SLisandro Dalcin     ierr = PetscMalloc((v+1)*sizeof(*tmpB), &tmpB);CHKERRQ(ierr);
227580bdb30SBarry Smith     ierr = PetscArraycpy(tmpV, oldV, v);CHKERRQ(ierr);
228580bdb30SBarry Smith     ierr = PetscArraycpy(tmpS, oldS, v);CHKERRQ(ierr);
229580bdb30SBarry Smith     ierr = PetscArraycpy(tmpH, oldH, v);CHKERRQ(ierr);
230580bdb30SBarry Smith     ierr = PetscArraycpy(tmpP, oldP, v);CHKERRQ(ierr);
231580bdb30SBarry Smith     ierr = PetscArraycpy(tmpB, oldB, v);CHKERRQ(ierr);
2328e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldV);CHKERRQ(ierr);
2338e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldS);CHKERRQ(ierr);
2348e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldH);CHKERRQ(ierr);
2358e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldP);CHKERRQ(ierr);
2368e1f8cf0SLisandro Dalcin     ierr = PetscFree(oldB);CHKERRQ(ierr);
2378e1f8cf0SLisandro Dalcin   }
238b9907514SLisandro Dalcin   label->numStrata     = v+1;
239c58f1c22SToby Isaac   label->stratumValues = tmpV;
240c58f1c22SToby Isaac   label->stratumSizes  = tmpS;
241c58f1c22SToby Isaac   label->ht            = tmpH;
242c58f1c22SToby Isaac   label->points        = tmpP;
243ad8374ffSToby Isaac   label->validIS       = tmpB;
244b9907514SLisandro Dalcin   ierr = PetscHSetICreate(&ht);CHKERRQ(ierr);
245b9907514SLisandro Dalcin   ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr);
246b9907514SLisandro Dalcin   ierr = PetscHMapISet(hmap, value, v);CHKERRQ(ierr);
247b9907514SLisandro Dalcin   tmpV[v] = value;
248b9907514SLisandro Dalcin   tmpS[v] = 0;
249b9907514SLisandro Dalcin   tmpH[v] = ht;
250b9907514SLisandro Dalcin   tmpP[v] = is;
251b9907514SLisandro Dalcin   tmpB[v] = PETSC_TRUE;
252277ea44aSLisandro Dalcin   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
2530c3c4a36SLisandro Dalcin   *index = v;
2540c3c4a36SLisandro Dalcin   PetscFunctionReturn(0);
2550c3c4a36SLisandro Dalcin }
2560c3c4a36SLisandro Dalcin 
257b9907514SLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode DMLabelLookupAddStratum(DMLabel label, PetscInt value, PetscInt *index)
258b9907514SLisandro Dalcin {
259b9907514SLisandro Dalcin   PetscErrorCode ierr;
260b9907514SLisandro Dalcin   PetscFunctionBegin;
261b9907514SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, index);CHKERRQ(ierr);
262b9907514SLisandro Dalcin   if (*index < 0) {ierr = DMLabelNewStratum(label, value, index);CHKERRQ(ierr);}
263b9907514SLisandro Dalcin   PetscFunctionReturn(0);
264b9907514SLisandro Dalcin }
265b9907514SLisandro Dalcin 
2669e63cc69SVaclav Hapla PETSC_STATIC_INLINE PetscErrorCode DMLabelGetStratumSize_Private(DMLabel label, PetscInt v, PetscInt *size)
2679e63cc69SVaclav Hapla {
2689e63cc69SVaclav Hapla   PetscErrorCode ierr;
2699e63cc69SVaclav Hapla 
2709e63cc69SVaclav Hapla   PetscFunctionBegin;
2719e63cc69SVaclav Hapla   *size = 0;
2729e63cc69SVaclav Hapla   if (v < 0) PetscFunctionReturn(0);
2739e63cc69SVaclav Hapla   if (label->validIS[v]) {
2749e63cc69SVaclav Hapla     *size = label->stratumSizes[v];
2759e63cc69SVaclav Hapla   } else {
2769e63cc69SVaclav Hapla     ierr = PetscHSetIGetSize(label->ht[v], size);CHKERRQ(ierr);
2779e63cc69SVaclav Hapla   }
2789e63cc69SVaclav Hapla   PetscFunctionReturn(0);
2799e63cc69SVaclav Hapla }
2809e63cc69SVaclav Hapla 
281b9907514SLisandro Dalcin /*@
282b9907514SLisandro Dalcin   DMLabelAddStratum - Adds a new stratum value in a DMLabel
283b9907514SLisandro Dalcin 
284d8d19677SJose E. Roman   Input Parameters:
285b9907514SLisandro Dalcin + label - The DMLabel
286b9907514SLisandro Dalcin - value - The stratum value
287b9907514SLisandro Dalcin 
288b9907514SLisandro Dalcin   Level: beginner
289b9907514SLisandro Dalcin 
290b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
291b9907514SLisandro Dalcin @*/
2920c3c4a36SLisandro Dalcin PetscErrorCode DMLabelAddStratum(DMLabel label, PetscInt value)
2930c3c4a36SLisandro Dalcin {
2940c3c4a36SLisandro Dalcin   PetscInt       v;
2950c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
2960c3c4a36SLisandro Dalcin 
2970c3c4a36SLisandro Dalcin   PetscFunctionBegin;
298d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
299b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
300b9907514SLisandro Dalcin   PetscFunctionReturn(0);
301b9907514SLisandro Dalcin }
302b9907514SLisandro Dalcin 
303b9907514SLisandro Dalcin /*@
304b9907514SLisandro Dalcin   DMLabelAddStrata - Adds new stratum values in a DMLabel
305b9907514SLisandro Dalcin 
3065b5e7992SMatthew G. Knepley   Not collective
3075b5e7992SMatthew G. Knepley 
308d8d19677SJose E. Roman   Input Parameters:
309b9907514SLisandro Dalcin + label - The DMLabel
310b9907514SLisandro Dalcin . numStrata - The number of stratum values
311b9907514SLisandro Dalcin - stratumValues - The stratum values
312b9907514SLisandro Dalcin 
313b9907514SLisandro Dalcin   Level: beginner
314b9907514SLisandro Dalcin 
315b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
316b9907514SLisandro Dalcin @*/
317b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrata(DMLabel label, PetscInt numStrata, const PetscInt stratumValues[])
318b9907514SLisandro Dalcin {
319b9907514SLisandro Dalcin   PetscInt       *values, v;
320b9907514SLisandro Dalcin   PetscErrorCode ierr;
321b9907514SLisandro Dalcin 
322b9907514SLisandro Dalcin   PetscFunctionBegin;
323b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
324b9907514SLisandro Dalcin   if (numStrata) PetscValidIntPointer(stratumValues, 3);
325b9907514SLisandro Dalcin   ierr = PetscMalloc1(numStrata, &values);CHKERRQ(ierr);
326580bdb30SBarry Smith   ierr = PetscArraycpy(values, stratumValues, numStrata);CHKERRQ(ierr);
327b9907514SLisandro Dalcin   ierr = PetscSortRemoveDupsInt(&numStrata, values);CHKERRQ(ierr);
328b9907514SLisandro Dalcin   if (!label->numStrata) { /* Fast preallocation */
329b9907514SLisandro Dalcin     PetscInt   *tmpV;
330b9907514SLisandro Dalcin     PetscInt   *tmpS;
331b9907514SLisandro Dalcin     PetscHSetI *tmpH, ht;
332b9907514SLisandro Dalcin     IS         *tmpP, is;
333b9907514SLisandro Dalcin     PetscBool  *tmpB;
334b9907514SLisandro Dalcin     PetscHMapI  hmap = label->hmap;
335b9907514SLisandro Dalcin 
336b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpV);CHKERRQ(ierr);
337b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpS);CHKERRQ(ierr);
338b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpH);CHKERRQ(ierr);
339b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpP);CHKERRQ(ierr);
340b9907514SLisandro Dalcin     ierr = PetscMalloc1(numStrata, &tmpB);CHKERRQ(ierr);
341b9907514SLisandro Dalcin     label->numStrata     = numStrata;
342b9907514SLisandro Dalcin     label->stratumValues = tmpV;
343b9907514SLisandro Dalcin     label->stratumSizes  = tmpS;
344b9907514SLisandro Dalcin     label->ht            = tmpH;
345b9907514SLisandro Dalcin     label->points        = tmpP;
346b9907514SLisandro Dalcin     label->validIS       = tmpB;
347b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
348b9907514SLisandro Dalcin       ierr = PetscHSetICreate(&ht);CHKERRQ(ierr);
349b9907514SLisandro Dalcin       ierr = ISCreateStride(PETSC_COMM_SELF,0,0,1,&is);CHKERRQ(ierr);
350b9907514SLisandro Dalcin       ierr = PetscHMapISet(hmap, values[v], v);CHKERRQ(ierr);
351b9907514SLisandro Dalcin       tmpV[v] = values[v];
352b9907514SLisandro Dalcin       tmpS[v] = 0;
353b9907514SLisandro Dalcin       tmpH[v] = ht;
354b9907514SLisandro Dalcin       tmpP[v] = is;
355b9907514SLisandro Dalcin       tmpB[v] = PETSC_TRUE;
356b9907514SLisandro Dalcin     }
357277ea44aSLisandro Dalcin     ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
358b9907514SLisandro Dalcin   } else {
359b9907514SLisandro Dalcin     for (v = 0; v < numStrata; ++v) {
360b9907514SLisandro Dalcin       ierr = DMLabelAddStratum(label, values[v]);CHKERRQ(ierr);
361b9907514SLisandro Dalcin     }
362b9907514SLisandro Dalcin   }
363b9907514SLisandro Dalcin   ierr = PetscFree(values);CHKERRQ(ierr);
364b9907514SLisandro Dalcin   PetscFunctionReturn(0);
365b9907514SLisandro Dalcin }
366b9907514SLisandro Dalcin 
367b9907514SLisandro Dalcin /*@
368b9907514SLisandro Dalcin   DMLabelAddStrataIS - Adds new stratum values in a DMLabel
369b9907514SLisandro Dalcin 
3705b5e7992SMatthew G. Knepley   Not collective
3715b5e7992SMatthew G. Knepley 
372d8d19677SJose E. Roman   Input Parameters:
373b9907514SLisandro Dalcin + label - The DMLabel
374b9907514SLisandro Dalcin - valueIS - Index set with stratum values
375b9907514SLisandro Dalcin 
376b9907514SLisandro Dalcin   Level: beginner
377b9907514SLisandro Dalcin 
378b9907514SLisandro Dalcin .seealso:  DMLabelCreate(), DMLabelDestroy()
379b9907514SLisandro Dalcin @*/
380b9907514SLisandro Dalcin PetscErrorCode DMLabelAddStrataIS(DMLabel label, IS valueIS)
381b9907514SLisandro Dalcin {
382b9907514SLisandro Dalcin   PetscInt       numStrata;
383b9907514SLisandro Dalcin   const PetscInt *stratumValues;
384b9907514SLisandro Dalcin   PetscErrorCode ierr;
385b9907514SLisandro Dalcin 
386b9907514SLisandro Dalcin   PetscFunctionBegin;
387b9907514SLisandro Dalcin   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
388b9907514SLisandro Dalcin   PetscValidHeaderSpecific(valueIS, IS_CLASSID, 2);
389b9907514SLisandro Dalcin   ierr = ISGetLocalSize(valueIS, &numStrata);CHKERRQ(ierr);
390b9907514SLisandro Dalcin   ierr = ISGetIndices(valueIS, &stratumValues);CHKERRQ(ierr);
391b9907514SLisandro Dalcin   ierr = DMLabelAddStrata(label, numStrata, stratumValues);CHKERRQ(ierr);
392c58f1c22SToby Isaac   PetscFunctionReturn(0);
393c58f1c22SToby Isaac }
394c58f1c22SToby Isaac 
395c58f1c22SToby Isaac static PetscErrorCode DMLabelView_Ascii(DMLabel label, PetscViewer viewer)
396c58f1c22SToby Isaac {
397c58f1c22SToby Isaac   PetscInt       v;
398c58f1c22SToby Isaac   PetscMPIInt    rank;
399c58f1c22SToby Isaac   PetscErrorCode ierr;
400c58f1c22SToby Isaac 
401c58f1c22SToby Isaac   PetscFunctionBegin;
402ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr);
403c58f1c22SToby Isaac   ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
404c58f1c22SToby Isaac   if (label) {
405d67d17b1SMatthew G. Knepley     const char *name;
406d67d17b1SMatthew G. Knepley 
407d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
408d67d17b1SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Label '%s':\n", name);CHKERRQ(ierr);
409c58f1c22SToby Isaac     if (label->bt) {ierr = PetscViewerASCIIPrintf(viewer, "  Index has been calculated in [%D, %D)\n", label->pStart, label->pEnd);CHKERRQ(ierr);}
410c58f1c22SToby Isaac     for (v = 0; v < label->numStrata; ++v) {
411c58f1c22SToby Isaac       const PetscInt value = label->stratumValues[v];
412ad8374ffSToby Isaac       const PetscInt *points;
413c58f1c22SToby Isaac       PetscInt       p;
414c58f1c22SToby Isaac 
415ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
416c58f1c22SToby Isaac       for (p = 0; p < label->stratumSizes[v]; ++p) {
417ad8374ffSToby Isaac         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D (%D)\n", rank, points[p], value);CHKERRQ(ierr);
418c58f1c22SToby Isaac       }
419ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[v],&points);CHKERRQ(ierr);
420c58f1c22SToby Isaac     }
421c58f1c22SToby Isaac   }
422c58f1c22SToby Isaac   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
423c58f1c22SToby Isaac   ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
424c58f1c22SToby Isaac   PetscFunctionReturn(0);
425c58f1c22SToby Isaac }
426c58f1c22SToby Isaac 
427c58f1c22SToby Isaac /*@C
428c58f1c22SToby Isaac   DMLabelView - View the label
429c58f1c22SToby Isaac 
4305b5e7992SMatthew G. Knepley   Collective on viewer
4315b5e7992SMatthew G. Knepley 
432c58f1c22SToby Isaac   Input Parameters:
433c58f1c22SToby Isaac + label - The DMLabel
434c58f1c22SToby Isaac - viewer - The PetscViewer
435c58f1c22SToby Isaac 
436c58f1c22SToby Isaac   Level: intermediate
437c58f1c22SToby Isaac 
438c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelDestroy()
439c58f1c22SToby Isaac @*/
440c58f1c22SToby Isaac PetscErrorCode DMLabelView(DMLabel label, PetscViewer viewer)
441c58f1c22SToby Isaac {
442c58f1c22SToby Isaac   PetscBool      iascii;
443c58f1c22SToby Isaac   PetscErrorCode ierr;
444c58f1c22SToby Isaac 
445c58f1c22SToby Isaac   PetscFunctionBegin;
446d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
447b9907514SLisandro Dalcin   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)label), &viewer);CHKERRQ(ierr);}
448c58f1c22SToby Isaac   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
449c58f1c22SToby Isaac   if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);}
450c58f1c22SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
451c58f1c22SToby Isaac   if (iascii) {
452c58f1c22SToby Isaac     ierr = DMLabelView_Ascii(label, viewer);CHKERRQ(ierr);
453c58f1c22SToby Isaac   }
454c58f1c22SToby Isaac   PetscFunctionReturn(0);
455c58f1c22SToby Isaac }
456c58f1c22SToby Isaac 
45784f0b6dfSMatthew G. Knepley /*@
458d67d17b1SMatthew G. Knepley   DMLabelReset - Destroys internal data structures in a DMLabel
459d67d17b1SMatthew G. Knepley 
4605b5e7992SMatthew G. Knepley   Not collective
4615b5e7992SMatthew G. Knepley 
462d67d17b1SMatthew G. Knepley   Input Parameter:
463d67d17b1SMatthew G. Knepley . label - The DMLabel
464d67d17b1SMatthew G. Knepley 
465d67d17b1SMatthew G. Knepley   Level: beginner
466d67d17b1SMatthew G. Knepley 
467d67d17b1SMatthew G. Knepley .seealso: DMLabelDestroy(), DMLabelCreate()
468d67d17b1SMatthew G. Knepley @*/
469d67d17b1SMatthew G. Knepley PetscErrorCode DMLabelReset(DMLabel label)
470d67d17b1SMatthew G. Knepley {
471d67d17b1SMatthew G. Knepley   PetscInt       v;
472d67d17b1SMatthew G. Knepley   PetscErrorCode ierr;
473d67d17b1SMatthew G. Knepley 
474d67d17b1SMatthew G. Knepley   PetscFunctionBegin;
475d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
476d67d17b1SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
477d67d17b1SMatthew G. Knepley     ierr = PetscHSetIDestroy(&label->ht[v]);CHKERRQ(ierr);
478d67d17b1SMatthew G. Knepley     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
479d67d17b1SMatthew G. Knepley   }
480b9907514SLisandro Dalcin   label->numStrata = 0;
481b9907514SLisandro Dalcin   ierr = PetscFree(label->stratumValues);CHKERRQ(ierr);
482b9907514SLisandro Dalcin   ierr = PetscFree(label->stratumSizes);CHKERRQ(ierr);
483d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->ht);CHKERRQ(ierr);
484d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->points);CHKERRQ(ierr);
485d67d17b1SMatthew G. Knepley   ierr = PetscFree(label->validIS);CHKERRQ(ierr);
486f9244615SMatthew G. Knepley   label->stratumValues = NULL;
487f9244615SMatthew G. Knepley   label->stratumSizes  = NULL;
488f9244615SMatthew G. Knepley   label->ht            = NULL;
489f9244615SMatthew G. Knepley   label->points        = NULL;
490f9244615SMatthew G. Knepley   label->validIS       = NULL;
491b9907514SLisandro Dalcin   ierr = PetscHMapIReset(label->hmap);CHKERRQ(ierr);
492b9907514SLisandro Dalcin   label->pStart = -1;
493b9907514SLisandro Dalcin   label->pEnd   = -1;
494d67d17b1SMatthew G. Knepley   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
495d67d17b1SMatthew G. Knepley   PetscFunctionReturn(0);
496d67d17b1SMatthew G. Knepley }
497d67d17b1SMatthew G. Knepley 
498d67d17b1SMatthew G. Knepley /*@
49984f0b6dfSMatthew G. Knepley   DMLabelDestroy - Destroys a DMLabel
50084f0b6dfSMatthew G. Knepley 
5015b5e7992SMatthew G. Knepley   Collective on label
5025b5e7992SMatthew G. Knepley 
50384f0b6dfSMatthew G. Knepley   Input Parameter:
50484f0b6dfSMatthew G. Knepley . label - The DMLabel
50584f0b6dfSMatthew G. Knepley 
50684f0b6dfSMatthew G. Knepley   Level: beginner
50784f0b6dfSMatthew G. Knepley 
508d67d17b1SMatthew G. Knepley .seealso: DMLabelReset(), DMLabelCreate()
50984f0b6dfSMatthew G. Knepley @*/
510c58f1c22SToby Isaac PetscErrorCode DMLabelDestroy(DMLabel *label)
511c58f1c22SToby Isaac {
512c58f1c22SToby Isaac   PetscErrorCode ierr;
513c58f1c22SToby Isaac 
514c58f1c22SToby Isaac   PetscFunctionBegin;
515d67d17b1SMatthew G. Knepley   if (!*label) PetscFunctionReturn(0);
516d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific((*label),DMLABEL_CLASSID,1);
517b9907514SLisandro Dalcin   if (--((PetscObject)(*label))->refct > 0) {*label = NULL; PetscFunctionReturn(0);}
518d67d17b1SMatthew G. Knepley   ierr = DMLabelReset(*label);CHKERRQ(ierr);
519b9907514SLisandro Dalcin   ierr = PetscHMapIDestroy(&(*label)->hmap);CHKERRQ(ierr);
520d67d17b1SMatthew G. Knepley   ierr = PetscHeaderDestroy(label);CHKERRQ(ierr);
521c58f1c22SToby Isaac   PetscFunctionReturn(0);
522c58f1c22SToby Isaac }
523c58f1c22SToby Isaac 
52484f0b6dfSMatthew G. Knepley /*@
52584f0b6dfSMatthew G. Knepley   DMLabelDuplicate - Duplicates a DMLabel
52684f0b6dfSMatthew G. Knepley 
5275b5e7992SMatthew G. Knepley   Collective on label
5285b5e7992SMatthew G. Knepley 
52984f0b6dfSMatthew G. Knepley   Input Parameter:
53084f0b6dfSMatthew G. Knepley . label - The DMLabel
53184f0b6dfSMatthew G. Knepley 
53284f0b6dfSMatthew G. Knepley   Output Parameter:
53384f0b6dfSMatthew G. Knepley . labelnew - location to put new vector
53484f0b6dfSMatthew G. Knepley 
53584f0b6dfSMatthew G. Knepley   Level: intermediate
53684f0b6dfSMatthew G. Knepley 
53784f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelDestroy()
53884f0b6dfSMatthew G. Knepley @*/
539c58f1c22SToby Isaac PetscErrorCode DMLabelDuplicate(DMLabel label, DMLabel *labelnew)
540c58f1c22SToby Isaac {
541d67d17b1SMatthew G. Knepley   const char    *name;
542ad8374ffSToby Isaac   PetscInt       v;
543c58f1c22SToby Isaac   PetscErrorCode ierr;
544c58f1c22SToby Isaac 
545c58f1c22SToby Isaac   PetscFunctionBegin;
546d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
547c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
548d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
549d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PetscObjectComm((PetscObject) label), name, labelnew);CHKERRQ(ierr);
550c58f1c22SToby Isaac 
551c58f1c22SToby Isaac   (*labelnew)->numStrata    = label->numStrata;
5525aa44df4SToby Isaac   (*labelnew)->defaultValue = label->defaultValue;
553c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumValues);CHKERRQ(ierr);
554c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->stratumSizes);CHKERRQ(ierr);
555c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->ht);CHKERRQ(ierr);
556c58f1c22SToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->points);CHKERRQ(ierr);
557ad8374ffSToby Isaac   ierr = PetscMalloc1(label->numStrata, &(*labelnew)->validIS);CHKERRQ(ierr);
558c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
559e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelnew)->ht[v]);CHKERRQ(ierr);
560c58f1c22SToby Isaac     (*labelnew)->stratumValues[v]  = label->stratumValues[v];
561c58f1c22SToby Isaac     (*labelnew)->stratumSizes[v]   = label->stratumSizes[v];
562ad8374ffSToby Isaac     ierr = PetscObjectReference((PetscObject) (label->points[v]));CHKERRQ(ierr);
563ad8374ffSToby Isaac     (*labelnew)->points[v]         = label->points[v];
564b9907514SLisandro Dalcin     (*labelnew)->validIS[v]        = PETSC_TRUE;
565c58f1c22SToby Isaac   }
566f14fe40dSLisandro Dalcin   ierr = PetscHMapIDestroy(&(*labelnew)->hmap);CHKERRQ(ierr);
567b9907514SLisandro Dalcin   ierr = PetscHMapIDuplicate(label->hmap,&(*labelnew)->hmap);CHKERRQ(ierr);
568c58f1c22SToby Isaac   (*labelnew)->pStart = -1;
569c58f1c22SToby Isaac   (*labelnew)->pEnd   = -1;
570c58f1c22SToby Isaac   (*labelnew)->bt     = NULL;
571c58f1c22SToby Isaac   PetscFunctionReturn(0);
572c58f1c22SToby Isaac }
573c58f1c22SToby Isaac 
574c6a43d28SMatthew G. Knepley /*@
575c6a43d28SMatthew G. Knepley   DMLabelComputeIndex - Create an index structure for membership determination, automatically determining the bounds
576c6a43d28SMatthew G. Knepley 
5775b5e7992SMatthew G. Knepley   Not collective
5785b5e7992SMatthew G. Knepley 
579c6a43d28SMatthew G. Knepley   Input Parameter:
580c6a43d28SMatthew G. Knepley . label  - The DMLabel
581c6a43d28SMatthew G. Knepley 
582c6a43d28SMatthew G. Knepley   Level: intermediate
583c6a43d28SMatthew G. Knepley 
584c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
585c6a43d28SMatthew G. Knepley @*/
586c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelComputeIndex(DMLabel label)
587c6a43d28SMatthew G. Knepley {
588c6a43d28SMatthew G. Knepley   PetscInt       pStart = PETSC_MAX_INT, pEnd = -1, v;
589c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
590c6a43d28SMatthew G. Knepley 
591c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
592c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
593c6a43d28SMatthew G. Knepley   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
594c6a43d28SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) {
595c6a43d28SMatthew G. Knepley     const PetscInt *points;
596c6a43d28SMatthew G. Knepley     PetscInt       i;
597c6a43d28SMatthew G. Knepley 
598c6a43d28SMatthew G. Knepley     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
599c6a43d28SMatthew G. Knepley     for (i = 0; i < label->stratumSizes[v]; ++i) {
600c6a43d28SMatthew G. Knepley       const PetscInt point = points[i];
601c6a43d28SMatthew G. Knepley 
602c6a43d28SMatthew G. Knepley       pStart = PetscMin(point,   pStart);
603c6a43d28SMatthew G. Knepley       pEnd   = PetscMax(point+1, pEnd);
604c6a43d28SMatthew G. Knepley     }
605c6a43d28SMatthew G. Knepley     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
606c6a43d28SMatthew G. Knepley   }
607c6a43d28SMatthew G. Knepley   label->pStart = pStart == PETSC_MAX_INT ? -1 : pStart;
608c6a43d28SMatthew G. Knepley   label->pEnd   = pEnd;
609c6a43d28SMatthew G. Knepley   ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
610c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
611c6a43d28SMatthew G. Knepley }
612c6a43d28SMatthew G. Knepley 
613c6a43d28SMatthew G. Knepley /*@
614c6a43d28SMatthew G. Knepley   DMLabelCreateIndex - Create an index structure for membership determination
615c6a43d28SMatthew G. Knepley 
6165b5e7992SMatthew G. Knepley   Not collective
6175b5e7992SMatthew G. Knepley 
618c6a43d28SMatthew G. Knepley   Input Parameters:
619c6a43d28SMatthew G. Knepley + label  - The DMLabel
620c6a43d28SMatthew G. Knepley . pStart - The smallest point
621c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
622c6a43d28SMatthew G. Knepley 
623c6a43d28SMatthew G. Knepley   Level: intermediate
624c6a43d28SMatthew G. Knepley 
625c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelComputeIndex(), DMLabelDestroyIndex(), DMLabelGetValue(), DMLabelSetValue()
626c6a43d28SMatthew G. Knepley @*/
627c58f1c22SToby Isaac PetscErrorCode DMLabelCreateIndex(DMLabel label, PetscInt pStart, PetscInt pEnd)
628c58f1c22SToby Isaac {
629c58f1c22SToby Isaac   PetscInt       v;
630c58f1c22SToby Isaac   PetscErrorCode ierr;
631c58f1c22SToby Isaac 
632c58f1c22SToby Isaac   PetscFunctionBegin;
633d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
6340c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
635c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
636c58f1c22SToby Isaac   label->pStart = pStart;
637c58f1c22SToby Isaac   label->pEnd   = pEnd;
638c6a43d28SMatthew G. Knepley   /* This can be hooked into SetValue(),  ClearValue(), etc. for updating */
639c58f1c22SToby Isaac   ierr = PetscBTCreate(pEnd - pStart, &label->bt);CHKERRQ(ierr);
640c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
641ad8374ffSToby Isaac     const PetscInt *points;
642c58f1c22SToby Isaac     PetscInt       i;
643c58f1c22SToby Isaac 
644ad8374ffSToby Isaac     ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
645c58f1c22SToby Isaac     for (i = 0; i < label->stratumSizes[v]; ++i) {
646ad8374ffSToby Isaac       const PetscInt point = points[i];
647c58f1c22SToby Isaac 
648c58f1c22SToby Isaac       if ((point < pStart) || (point >= pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, pStart, pEnd);
649c58f1c22SToby Isaac       ierr = PetscBTSet(label->bt, point - pStart);CHKERRQ(ierr);
650c58f1c22SToby Isaac     }
651ad8374ffSToby Isaac     ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
652c58f1c22SToby Isaac   }
653c58f1c22SToby Isaac   PetscFunctionReturn(0);
654c58f1c22SToby Isaac }
655c58f1c22SToby Isaac 
656c6a43d28SMatthew G. Knepley /*@
657c6a43d28SMatthew G. Knepley   DMLabelDestroyIndex - Destroy the index structure
658c6a43d28SMatthew G. Knepley 
6595b5e7992SMatthew G. Knepley   Not collective
6605b5e7992SMatthew G. Knepley 
661c6a43d28SMatthew G. Knepley   Input Parameter:
662c6a43d28SMatthew G. Knepley . label - the DMLabel
663c6a43d28SMatthew G. Knepley 
664c6a43d28SMatthew G. Knepley   Level: intermediate
665c6a43d28SMatthew G. Knepley 
666c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
667c6a43d28SMatthew G. Knepley @*/
668c58f1c22SToby Isaac PetscErrorCode DMLabelDestroyIndex(DMLabel label)
669c58f1c22SToby Isaac {
670c58f1c22SToby Isaac   PetscErrorCode ierr;
671c58f1c22SToby Isaac 
672c58f1c22SToby Isaac   PetscFunctionBegin;
673d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
674c58f1c22SToby Isaac   label->pStart = -1;
675c58f1c22SToby Isaac   label->pEnd   = -1;
6760c3c4a36SLisandro Dalcin   ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
677c58f1c22SToby Isaac   PetscFunctionReturn(0);
678c58f1c22SToby Isaac }
679c58f1c22SToby Isaac 
680c58f1c22SToby Isaac /*@
681c6a43d28SMatthew G. Knepley   DMLabelGetBounds - Return the smallest and largest point in the label
682c6a43d28SMatthew G. Knepley 
6835b5e7992SMatthew G. Knepley   Not collective
6845b5e7992SMatthew G. Knepley 
685c6a43d28SMatthew G. Knepley   Input Parameter:
686c6a43d28SMatthew G. Knepley . label - the DMLabel
687c6a43d28SMatthew G. Knepley 
688c6a43d28SMatthew G. Knepley   Output Parameters:
689c6a43d28SMatthew G. Knepley + pStart - The smallest point
690c6a43d28SMatthew G. Knepley - pEnd   - The largest point + 1
691c6a43d28SMatthew G. Knepley 
692c6a43d28SMatthew G. Knepley   Note: This will compute an index for the label if one does not exist.
693c6a43d28SMatthew G. Knepley 
694c6a43d28SMatthew G. Knepley   Level: intermediate
695c6a43d28SMatthew G. Knepley 
696c6a43d28SMatthew G. Knepley .seealso: DMLabelHasPoint(), DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
697c6a43d28SMatthew G. Knepley @*/
698c6a43d28SMatthew G. Knepley PetscErrorCode DMLabelGetBounds(DMLabel label, PetscInt *pStart, PetscInt *pEnd)
699c6a43d28SMatthew G. Knepley {
700c6a43d28SMatthew G. Knepley   PetscErrorCode ierr;
701c6a43d28SMatthew G. Knepley 
702c6a43d28SMatthew G. Knepley   PetscFunctionBegin;
703c6a43d28SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
704c6a43d28SMatthew G. Knepley   if ((label->pStart == -1) && (label->pEnd == -1)) {ierr = DMLabelComputeIndex(label);CHKERRQ(ierr);}
705c6a43d28SMatthew G. Knepley   if (pStart) {
706534a8f05SLisandro Dalcin     PetscValidIntPointer(pStart, 2);
707c6a43d28SMatthew G. Knepley     *pStart = label->pStart;
708c6a43d28SMatthew G. Knepley   }
709c6a43d28SMatthew G. Knepley   if (pEnd) {
710534a8f05SLisandro Dalcin     PetscValidIntPointer(pEnd, 3);
711c6a43d28SMatthew G. Knepley     *pEnd = label->pEnd;
712c6a43d28SMatthew G. Knepley   }
713c6a43d28SMatthew G. Knepley   PetscFunctionReturn(0);
714c6a43d28SMatthew G. Knepley }
715c6a43d28SMatthew G. Knepley 
716c6a43d28SMatthew G. Knepley /*@
717c58f1c22SToby Isaac   DMLabelHasValue - Determine whether a label assigns the value to any point
718c58f1c22SToby Isaac 
7195b5e7992SMatthew G. Knepley   Not collective
7205b5e7992SMatthew G. Knepley 
721c58f1c22SToby Isaac   Input Parameters:
722c58f1c22SToby Isaac + label - the DMLabel
723c58f1c22SToby Isaac - value - the value
724c58f1c22SToby Isaac 
725c58f1c22SToby Isaac   Output Parameter:
726c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this value to any point
727c58f1c22SToby Isaac 
728c58f1c22SToby Isaac   Level: developer
729c58f1c22SToby Isaac 
730c58f1c22SToby Isaac .seealso: DMLabelHasPoint(), DMLabelGetValue(), DMLabelSetValue()
731c58f1c22SToby Isaac @*/
732c58f1c22SToby Isaac PetscErrorCode DMLabelHasValue(DMLabel label, PetscInt value, PetscBool *contains)
733c58f1c22SToby Isaac {
734c58f1c22SToby Isaac   PetscInt v;
7350c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
736c58f1c22SToby Isaac 
737c58f1c22SToby Isaac   PetscFunctionBegin;
738d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
739534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
7400c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
7410c3c4a36SLisandro Dalcin   *contains = v < 0 ? PETSC_FALSE : PETSC_TRUE;
742c58f1c22SToby Isaac   PetscFunctionReturn(0);
743c58f1c22SToby Isaac }
744c58f1c22SToby Isaac 
745c58f1c22SToby Isaac /*@
746c58f1c22SToby Isaac   DMLabelHasPoint - Determine whether a label assigns a value to a point
747c58f1c22SToby Isaac 
7485b5e7992SMatthew G. Knepley   Not collective
7495b5e7992SMatthew G. Knepley 
750c58f1c22SToby Isaac   Input Parameters:
751c58f1c22SToby Isaac + label - the DMLabel
752c58f1c22SToby Isaac - point - the point
753c58f1c22SToby Isaac 
754c58f1c22SToby Isaac   Output Parameter:
755c58f1c22SToby Isaac . contains - Flag indicating whether the label maps this point to a value
756c58f1c22SToby Isaac 
757c58f1c22SToby Isaac   Note: The user must call DMLabelCreateIndex() before this function.
758c58f1c22SToby Isaac 
759c58f1c22SToby Isaac   Level: developer
760c58f1c22SToby Isaac 
761c58f1c22SToby Isaac .seealso: DMLabelCreateIndex(), DMLabelGetValue(), DMLabelSetValue()
762c58f1c22SToby Isaac @*/
763c58f1c22SToby Isaac PetscErrorCode DMLabelHasPoint(DMLabel label, PetscInt point, PetscBool *contains)
764c58f1c22SToby Isaac {
765c58f1c22SToby Isaac   PetscErrorCode ierr;
766c58f1c22SToby Isaac 
767c58f1c22SToby Isaac   PetscFunctionBeginHot;
768d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
769534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 3);
770c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
77176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
772c58f1c22SToby Isaac     if (!label->bt) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call DMLabelCreateIndex() before DMLabelHasPoint()");
773c58f1c22SToby Isaac     if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
77476bd3646SJed Brown   }
775c58f1c22SToby Isaac   *contains = PetscBTLookup(label->bt, point - label->pStart) ? PETSC_TRUE : PETSC_FALSE;
776c58f1c22SToby Isaac   PetscFunctionReturn(0);
777c58f1c22SToby Isaac }
778c58f1c22SToby Isaac 
779c58f1c22SToby Isaac /*@
780c58f1c22SToby Isaac   DMLabelStratumHasPoint - Return true if the stratum contains a point
781c58f1c22SToby Isaac 
7825b5e7992SMatthew G. Knepley   Not collective
7835b5e7992SMatthew G. Knepley 
784c58f1c22SToby Isaac   Input Parameters:
785c58f1c22SToby Isaac + label - the DMLabel
786c58f1c22SToby Isaac . value - the stratum value
787c58f1c22SToby Isaac - point - the point
788c58f1c22SToby Isaac 
789c58f1c22SToby Isaac   Output Parameter:
790c58f1c22SToby Isaac . contains - true if the stratum contains the point
791c58f1c22SToby Isaac 
792c58f1c22SToby Isaac   Level: intermediate
793c58f1c22SToby Isaac 
794c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue()
795c58f1c22SToby Isaac @*/
796c58f1c22SToby Isaac PetscErrorCode DMLabelStratumHasPoint(DMLabel label, PetscInt value, PetscInt point, PetscBool *contains)
797c58f1c22SToby Isaac {
798c58f1c22SToby Isaac   PetscInt       v;
799c58f1c22SToby Isaac   PetscErrorCode ierr;
800c58f1c22SToby Isaac 
8010c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
802d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
803534a8f05SLisandro Dalcin   PetscValidBoolPointer(contains, 4);
804c58f1c22SToby Isaac   *contains = PETSC_FALSE;
8050c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
8060c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
8070c3c4a36SLisandro Dalcin 
808ad8374ffSToby Isaac   if (label->validIS[v]) {
809c58f1c22SToby Isaac     PetscInt i;
810c58f1c22SToby Isaac 
811a2d74346SToby Isaac     ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
8120c3c4a36SLisandro Dalcin     if (i >= 0) *contains = PETSC_TRUE;
813c58f1c22SToby Isaac   } else {
814c58f1c22SToby Isaac     PetscBool has;
815c58f1c22SToby Isaac 
816b9907514SLisandro Dalcin     ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
8170c3c4a36SLisandro Dalcin     if (has) *contains = PETSC_TRUE;
818c58f1c22SToby Isaac   }
819c58f1c22SToby Isaac   PetscFunctionReturn(0);
820c58f1c22SToby Isaac }
821c58f1c22SToby Isaac 
82284f0b6dfSMatthew G. Knepley /*@
8235aa44df4SToby Isaac   DMLabelGetDefaultValue - Get the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8245aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8255aa44df4SToby Isaac 
8265b5e7992SMatthew G. Knepley   Not collective
8275b5e7992SMatthew G. Knepley 
8285aa44df4SToby Isaac   Input parameter:
8295aa44df4SToby Isaac . label - a DMLabel object
8305aa44df4SToby Isaac 
8315aa44df4SToby Isaac   Output parameter:
8325aa44df4SToby Isaac . defaultValue - the default value
8335aa44df4SToby Isaac 
8345aa44df4SToby Isaac   Level: beginner
8355aa44df4SToby Isaac 
8365aa44df4SToby Isaac .seealso: DMLabelSetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
83784f0b6dfSMatthew G. Knepley @*/
8385aa44df4SToby Isaac PetscErrorCode DMLabelGetDefaultValue(DMLabel label, PetscInt *defaultValue)
8395aa44df4SToby Isaac {
8405aa44df4SToby Isaac   PetscFunctionBegin;
841d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8425aa44df4SToby Isaac   *defaultValue = label->defaultValue;
8435aa44df4SToby Isaac   PetscFunctionReturn(0);
8445aa44df4SToby Isaac }
8455aa44df4SToby Isaac 
84684f0b6dfSMatthew G. Knepley /*@
8475aa44df4SToby Isaac   DMLabelSetDefaultValue - Set the default value returned by DMLabelGetValue() if a point has not been explicitly given a value.
8485aa44df4SToby Isaac   When a label is created, it is initialized to -1.
8495aa44df4SToby Isaac 
8505b5e7992SMatthew G. Knepley   Not collective
8515b5e7992SMatthew G. Knepley 
8525aa44df4SToby Isaac   Input parameter:
8535aa44df4SToby Isaac . label - a DMLabel object
8545aa44df4SToby Isaac 
8555aa44df4SToby Isaac   Output parameter:
8565aa44df4SToby Isaac . defaultValue - the default value
8575aa44df4SToby Isaac 
8585aa44df4SToby Isaac   Level: beginner
8595aa44df4SToby Isaac 
8605aa44df4SToby Isaac .seealso: DMLabelGetDefaultValue(), DMLabelGetValue(), DMLabelSetValue()
86184f0b6dfSMatthew G. Knepley @*/
8625aa44df4SToby Isaac PetscErrorCode DMLabelSetDefaultValue(DMLabel label, PetscInt defaultValue)
8635aa44df4SToby Isaac {
8645aa44df4SToby Isaac   PetscFunctionBegin;
865d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
8665aa44df4SToby Isaac   label->defaultValue = defaultValue;
8675aa44df4SToby Isaac   PetscFunctionReturn(0);
8685aa44df4SToby Isaac }
8695aa44df4SToby Isaac 
870c58f1c22SToby Isaac /*@
8715aa44df4SToby 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())
872c58f1c22SToby Isaac 
8735b5e7992SMatthew G. Knepley   Not collective
8745b5e7992SMatthew G. Knepley 
875c58f1c22SToby Isaac   Input Parameters:
876c58f1c22SToby Isaac + label - the DMLabel
877c58f1c22SToby Isaac - point - the point
878c58f1c22SToby Isaac 
879c58f1c22SToby Isaac   Output Parameter:
8808e68afcfSMatthew G. Knepley . value - The point value, or the default value (-1 by default)
881c58f1c22SToby Isaac 
882c58f1c22SToby Isaac   Level: intermediate
883c58f1c22SToby Isaac 
8845aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelSetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
885c58f1c22SToby Isaac @*/
886c58f1c22SToby Isaac PetscErrorCode DMLabelGetValue(DMLabel label, PetscInt point, PetscInt *value)
887c58f1c22SToby Isaac {
888c58f1c22SToby Isaac   PetscInt       v;
889c58f1c22SToby Isaac   PetscErrorCode ierr;
890c58f1c22SToby Isaac 
8910c3c4a36SLisandro Dalcin   PetscFunctionBeginHot;
892d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
893c58f1c22SToby Isaac   PetscValidPointer(value, 3);
8945aa44df4SToby Isaac   *value = label->defaultValue;
895c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
896ad8374ffSToby Isaac     if (label->validIS[v]) {
897c58f1c22SToby Isaac       PetscInt i;
898c58f1c22SToby Isaac 
899a2d74346SToby Isaac       ierr = ISLocate(label->points[v], point, &i);CHKERRQ(ierr);
900c58f1c22SToby Isaac       if (i >= 0) {
901c58f1c22SToby Isaac         *value = label->stratumValues[v];
902c58f1c22SToby Isaac         break;
903c58f1c22SToby Isaac       }
904c58f1c22SToby Isaac     } else {
905c58f1c22SToby Isaac       PetscBool has;
906c58f1c22SToby Isaac 
907b9907514SLisandro Dalcin       ierr = PetscHSetIHas(label->ht[v], point, &has);CHKERRQ(ierr);
908c58f1c22SToby Isaac       if (has) {
909c58f1c22SToby Isaac         *value = label->stratumValues[v];
910c58f1c22SToby Isaac         break;
911c58f1c22SToby Isaac       }
912c58f1c22SToby Isaac     }
913c58f1c22SToby Isaac   }
914c58f1c22SToby Isaac   PetscFunctionReturn(0);
915c58f1c22SToby Isaac }
916c58f1c22SToby Isaac 
917c58f1c22SToby Isaac /*@
918367003a6SStefano 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.
919c58f1c22SToby Isaac 
9205b5e7992SMatthew G. Knepley   Not collective
9215b5e7992SMatthew G. Knepley 
922c58f1c22SToby Isaac   Input Parameters:
923c58f1c22SToby Isaac + label - the DMLabel
924c58f1c22SToby Isaac . point - the point
925c58f1c22SToby Isaac - value - The point value
926c58f1c22SToby Isaac 
927c58f1c22SToby Isaac   Level: intermediate
928c58f1c22SToby Isaac 
9295aa44df4SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelClearValue(), DMLabelGetDefaultValue(), DMLabelSetDefaultValue()
930c58f1c22SToby Isaac @*/
931c58f1c22SToby Isaac PetscErrorCode DMLabelSetValue(DMLabel label, PetscInt point, PetscInt value)
932c58f1c22SToby Isaac {
933c58f1c22SToby Isaac   PetscInt       v;
934c58f1c22SToby Isaac   PetscErrorCode ierr;
935c58f1c22SToby Isaac 
936c58f1c22SToby Isaac   PetscFunctionBegin;
937d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
9380c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
9395aa44df4SToby Isaac   if (value == label->defaultValue) PetscFunctionReturn(0);
940b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
941c58f1c22SToby Isaac   /* Set key */
9420c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
943e8f14785SLisandro Dalcin   ierr = PetscHSetIAdd(label->ht[v], point);CHKERRQ(ierr);
944c58f1c22SToby Isaac   PetscFunctionReturn(0);
945c58f1c22SToby Isaac }
946c58f1c22SToby Isaac 
947c58f1c22SToby Isaac /*@
948c58f1c22SToby Isaac   DMLabelClearValue - Clear the value a label assigns to a point
949c58f1c22SToby Isaac 
9505b5e7992SMatthew G. Knepley   Not collective
9515b5e7992SMatthew G. Knepley 
952c58f1c22SToby Isaac   Input Parameters:
953c58f1c22SToby Isaac + label - the DMLabel
954c58f1c22SToby Isaac . point - the point
955c58f1c22SToby Isaac - value - The point value
956c58f1c22SToby Isaac 
957c58f1c22SToby Isaac   Level: intermediate
958c58f1c22SToby Isaac 
959c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue()
960c58f1c22SToby Isaac @*/
961c58f1c22SToby Isaac PetscErrorCode DMLabelClearValue(DMLabel label, PetscInt point, PetscInt value)
962c58f1c22SToby Isaac {
963ad8374ffSToby Isaac   PetscInt       v;
964c58f1c22SToby Isaac   PetscErrorCode ierr;
965c58f1c22SToby Isaac 
966c58f1c22SToby Isaac   PetscFunctionBegin;
967d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
968c58f1c22SToby Isaac   /* Find label value */
9690c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
9700c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
9710c3c4a36SLisandro Dalcin 
972eeed21e7SToby Isaac   if (label->bt) {
973eeed21e7SToby Isaac     if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
974eeed21e7SToby Isaac     ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
975eeed21e7SToby Isaac   }
9760c3c4a36SLisandro Dalcin 
9770c3c4a36SLisandro Dalcin   /* Delete key */
9780c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
979e8f14785SLisandro Dalcin   ierr = PetscHSetIDel(label->ht[v], point);CHKERRQ(ierr);
980c58f1c22SToby Isaac   PetscFunctionReturn(0);
981c58f1c22SToby Isaac }
982c58f1c22SToby Isaac 
983c58f1c22SToby Isaac /*@
984c58f1c22SToby Isaac   DMLabelInsertIS - Set all points in the IS to a value
985c58f1c22SToby Isaac 
9865b5e7992SMatthew G. Knepley   Not collective
9875b5e7992SMatthew G. Knepley 
988c58f1c22SToby Isaac   Input Parameters:
989c58f1c22SToby Isaac + label - the DMLabel
990c58f1c22SToby Isaac . is    - the point IS
991c58f1c22SToby Isaac - value - The point value
992c58f1c22SToby Isaac 
993c58f1c22SToby Isaac   Level: intermediate
994c58f1c22SToby Isaac 
995c58f1c22SToby Isaac .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
996c58f1c22SToby Isaac @*/
997c58f1c22SToby Isaac PetscErrorCode DMLabelInsertIS(DMLabel label, IS is, PetscInt value)
998c58f1c22SToby Isaac {
9990c3c4a36SLisandro Dalcin   PetscInt        v, n, p;
1000c58f1c22SToby Isaac   const PetscInt *points;
1001c58f1c22SToby Isaac   PetscErrorCode  ierr;
1002c58f1c22SToby Isaac 
1003c58f1c22SToby Isaac   PetscFunctionBegin;
1004d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1005c58f1c22SToby Isaac   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
10060c3c4a36SLisandro Dalcin   /* Find label value, add new entry if needed */
10070c3c4a36SLisandro Dalcin   if (value == label->defaultValue) PetscFunctionReturn(0);
1008b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
10090c3c4a36SLisandro Dalcin   /* Set keys */
10100c3c4a36SLisandro Dalcin   ierr = DMLabelMakeInvalid_Private(label, v);CHKERRQ(ierr);
1011c58f1c22SToby Isaac   ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr);
1012c58f1c22SToby Isaac   ierr = ISGetIndices(is, &points);CHKERRQ(ierr);
1013e8f14785SLisandro Dalcin   for (p = 0; p < n; ++p) {ierr = PetscHSetIAdd(label->ht[v], points[p]);CHKERRQ(ierr);}
1014c58f1c22SToby Isaac   ierr = ISRestoreIndices(is, &points);CHKERRQ(ierr);
1015c58f1c22SToby Isaac   PetscFunctionReturn(0);
1016c58f1c22SToby Isaac }
1017c58f1c22SToby Isaac 
101884f0b6dfSMatthew G. Knepley /*@
101984f0b6dfSMatthew G. Knepley   DMLabelGetNumValues - Get the number of values that the DMLabel takes
102084f0b6dfSMatthew G. Knepley 
10215b5e7992SMatthew G. Knepley   Not collective
10225b5e7992SMatthew G. Knepley 
102384f0b6dfSMatthew G. Knepley   Input Parameter:
102484f0b6dfSMatthew G. Knepley . label - the DMLabel
102584f0b6dfSMatthew G. Knepley 
102601d2d390SJose E. Roman   Output Parameter:
102784f0b6dfSMatthew G. Knepley . numValues - the number of values
102884f0b6dfSMatthew G. Knepley 
102984f0b6dfSMatthew G. Knepley   Level: intermediate
103084f0b6dfSMatthew G. Knepley 
103184f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
103284f0b6dfSMatthew G. Knepley @*/
1033c58f1c22SToby Isaac PetscErrorCode DMLabelGetNumValues(DMLabel label, PetscInt *numValues)
1034c58f1c22SToby Isaac {
1035c58f1c22SToby Isaac   PetscFunctionBegin;
1036d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1037c58f1c22SToby Isaac   PetscValidPointer(numValues, 2);
1038c58f1c22SToby Isaac   *numValues = label->numStrata;
1039c58f1c22SToby Isaac   PetscFunctionReturn(0);
1040c58f1c22SToby Isaac }
1041c58f1c22SToby Isaac 
104284f0b6dfSMatthew G. Knepley /*@
104384f0b6dfSMatthew G. Knepley   DMLabelGetValueIS - Get an IS of all values that the DMlabel takes
104484f0b6dfSMatthew G. Knepley 
10455b5e7992SMatthew G. Knepley   Not collective
10465b5e7992SMatthew G. Knepley 
104784f0b6dfSMatthew G. Knepley   Input Parameter:
104884f0b6dfSMatthew G. Knepley . label - the DMLabel
104984f0b6dfSMatthew G. Knepley 
105001d2d390SJose E. Roman   Output Parameter:
105184f0b6dfSMatthew G. Knepley . is    - the value IS
105284f0b6dfSMatthew G. Knepley 
105384f0b6dfSMatthew G. Knepley   Level: intermediate
105484f0b6dfSMatthew G. Knepley 
1055*1d04cbbeSVaclav Hapla   Notes:
1056*1d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
1057*1d04cbbeSVaclav Hapla   Strata which are allocated but empty [DMLabelGetStratumSize() yields 0] are counted.
1058*1d04cbbeSVaclav Hapla   If you need to count only nonempty strata, use DMLabelGetNonEmptyStratumValuesIS().
1059*1d04cbbeSVaclav Hapla 
1060*1d04cbbeSVaclav Hapla .seealso: DMLabelGetNonEmptyStratumValuesIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
106184f0b6dfSMatthew G. Knepley @*/
1062c58f1c22SToby Isaac PetscErrorCode DMLabelGetValueIS(DMLabel label, IS *values)
1063c58f1c22SToby Isaac {
1064c58f1c22SToby Isaac   PetscErrorCode ierr;
1065c58f1c22SToby Isaac 
1066c58f1c22SToby Isaac   PetscFunctionBegin;
1067d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1068c58f1c22SToby Isaac   PetscValidPointer(values, 2);
1069c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values);CHKERRQ(ierr);
1070c58f1c22SToby Isaac   PetscFunctionReturn(0);
1071c58f1c22SToby Isaac }
1072c58f1c22SToby Isaac 
107384f0b6dfSMatthew G. Knepley /*@
1074*1d04cbbeSVaclav Hapla   DMLabelGetNonEmptyStratumValuesIS - Get an IS of all values that the DMlabel takes
1075*1d04cbbeSVaclav Hapla 
1076*1d04cbbeSVaclav Hapla   Not collective
1077*1d04cbbeSVaclav Hapla 
1078*1d04cbbeSVaclav Hapla   Input Parameter:
1079*1d04cbbeSVaclav Hapla . label - the DMLabel
1080*1d04cbbeSVaclav Hapla 
1081*1d04cbbeSVaclav Hapla   Output Paramater:
1082*1d04cbbeSVaclav Hapla . is    - the value IS
1083*1d04cbbeSVaclav Hapla 
1084*1d04cbbeSVaclav Hapla   Level: intermediate
1085*1d04cbbeSVaclav Hapla 
1086*1d04cbbeSVaclav Hapla   Notes:
1087*1d04cbbeSVaclav Hapla   The output IS should be destroyed when no longer needed.
1088*1d04cbbeSVaclav Hapla   This is similar to DMLabelGetValueIS() but counts only nonempty strata.
1089*1d04cbbeSVaclav Hapla 
1090*1d04cbbeSVaclav Hapla .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
1091*1d04cbbeSVaclav Hapla @*/
1092*1d04cbbeSVaclav Hapla PetscErrorCode DMLabelGetNonEmptyStratumValuesIS(DMLabel label, IS *values)
1093*1d04cbbeSVaclav Hapla {
1094*1d04cbbeSVaclav Hapla   PetscInt        i, j;
1095*1d04cbbeSVaclav Hapla   PetscInt       *valuesArr;
1096*1d04cbbeSVaclav Hapla   PetscErrorCode  ierr;
1097*1d04cbbeSVaclav Hapla 
1098*1d04cbbeSVaclav Hapla   PetscFunctionBegin;
1099*1d04cbbeSVaclav Hapla   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1100*1d04cbbeSVaclav Hapla   PetscValidPointer(values, 2);
1101*1d04cbbeSVaclav Hapla   ierr = PetscMalloc1(label->numStrata, &valuesArr);CHKERRQ(ierr);
1102*1d04cbbeSVaclav Hapla   for (i = 0, j = 0; i < label->numStrata; i++) {
1103*1d04cbbeSVaclav Hapla     PetscInt        n;
1104*1d04cbbeSVaclav Hapla 
1105*1d04cbbeSVaclav Hapla     ierr = DMLabelGetStratumSize_Private(label, i, &n);CHKERRQ(ierr);
1106*1d04cbbeSVaclav Hapla     if (n) valuesArr[j++] = label->stratumValues[i];
1107*1d04cbbeSVaclav Hapla   }
1108*1d04cbbeSVaclav Hapla   if (j == label->numStrata) {
1109*1d04cbbeSVaclav Hapla     ierr = ISCreateGeneral(PETSC_COMM_SELF, label->numStrata, label->stratumValues, PETSC_USE_POINTER, values);CHKERRQ(ierr);
1110*1d04cbbeSVaclav Hapla   } else {
1111*1d04cbbeSVaclav Hapla     ierr = ISCreateGeneral(PETSC_COMM_SELF, j, valuesArr, PETSC_COPY_VALUES, values);CHKERRQ(ierr);
1112*1d04cbbeSVaclav Hapla   }
1113*1d04cbbeSVaclav Hapla   ierr = PetscFree(valuesArr);CHKERRQ(ierr);
1114*1d04cbbeSVaclav Hapla   PetscFunctionReturn(0);
1115*1d04cbbeSVaclav Hapla }
1116*1d04cbbeSVaclav Hapla 
1117*1d04cbbeSVaclav Hapla /*@
1118d123abd9SMatthew 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
1119d123abd9SMatthew G. Knepley 
1120d123abd9SMatthew G. Knepley   Not collective
1121d123abd9SMatthew G. Knepley 
1122d123abd9SMatthew G. Knepley   Input Parameters:
1123d123abd9SMatthew G. Knepley + label - the DMLabel
112497bb3fdcSJose E. Roman - value - the value
1125d123abd9SMatthew G. Knepley 
112601d2d390SJose E. Roman   Output Parameter:
1127d123abd9SMatthew G. Knepley . index - the index of value in the list of values
1128d123abd9SMatthew G. Knepley 
1129d123abd9SMatthew G. Knepley   Level: intermediate
1130d123abd9SMatthew G. Knepley 
1131d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIS(), DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
1132d123abd9SMatthew G. Knepley @*/
1133d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetValueIndex(DMLabel label, PetscInt value, PetscInt *index)
1134d123abd9SMatthew G. Knepley {
1135d123abd9SMatthew G. Knepley   PetscInt v;
1136d123abd9SMatthew G. Knepley 
1137d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1138d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1139d123abd9SMatthew G. Knepley   PetscValidPointer(index, 3);
1140d123abd9SMatthew G. Knepley   /* Do not assume they are sorted */
1141d123abd9SMatthew G. Knepley   for (v = 0; v < label->numStrata; ++v) if (label->stratumValues[v] == value) break;
1142d123abd9SMatthew G. Knepley   if (v >= label->numStrata) *index = -1;
1143d123abd9SMatthew G. Knepley   else                       *index = v;
1144d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1145d123abd9SMatthew G. Knepley }
1146d123abd9SMatthew G. Knepley 
1147d123abd9SMatthew G. Knepley /*@
114884f0b6dfSMatthew G. Knepley   DMLabelHasStratum - Determine whether points exist with the given value
114984f0b6dfSMatthew G. Knepley 
11505b5e7992SMatthew G. Knepley   Not collective
11515b5e7992SMatthew G. Knepley 
115284f0b6dfSMatthew G. Knepley   Input Parameters:
115384f0b6dfSMatthew G. Knepley + label - the DMLabel
115484f0b6dfSMatthew G. Knepley - value - the stratum value
115584f0b6dfSMatthew G. Knepley 
115601d2d390SJose E. Roman   Output Parameter:
115784f0b6dfSMatthew G. Knepley . exists - Flag saying whether points exist
115884f0b6dfSMatthew G. Knepley 
115984f0b6dfSMatthew G. Knepley   Level: intermediate
116084f0b6dfSMatthew G. Knepley 
116184f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
116284f0b6dfSMatthew G. Knepley @*/
1163fada774cSMatthew G. Knepley PetscErrorCode DMLabelHasStratum(DMLabel label, PetscInt value, PetscBool *exists)
1164fada774cSMatthew G. Knepley {
1165fada774cSMatthew G. Knepley   PetscInt       v;
11660c3c4a36SLisandro Dalcin   PetscErrorCode ierr;
1167fada774cSMatthew G. Knepley 
1168fada774cSMatthew G. Knepley   PetscFunctionBegin;
1169d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1170fada774cSMatthew G. Knepley   PetscValidPointer(exists, 3);
11710c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
11720c3c4a36SLisandro Dalcin   *exists = v < 0 ? PETSC_FALSE : PETSC_TRUE;
1173fada774cSMatthew G. Knepley   PetscFunctionReturn(0);
1174fada774cSMatthew G. Knepley }
1175fada774cSMatthew G. Knepley 
117684f0b6dfSMatthew G. Knepley /*@
117784f0b6dfSMatthew G. Knepley   DMLabelGetStratumSize - Get the size of a stratum
117884f0b6dfSMatthew G. Knepley 
11795b5e7992SMatthew G. Knepley   Not collective
11805b5e7992SMatthew G. Knepley 
118184f0b6dfSMatthew G. Knepley   Input Parameters:
118284f0b6dfSMatthew G. Knepley + label - the DMLabel
118384f0b6dfSMatthew G. Knepley - value - the stratum value
118484f0b6dfSMatthew G. Knepley 
118501d2d390SJose E. Roman   Output Parameter:
118684f0b6dfSMatthew G. Knepley . size - The number of points in the stratum
118784f0b6dfSMatthew G. Knepley 
118884f0b6dfSMatthew G. Knepley   Level: intermediate
118984f0b6dfSMatthew G. Knepley 
119084f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
119184f0b6dfSMatthew G. Knepley @*/
1192c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumSize(DMLabel label, PetscInt value, PetscInt *size)
1193c58f1c22SToby Isaac {
1194c58f1c22SToby Isaac   PetscInt       v;
1195c58f1c22SToby Isaac   PetscErrorCode ierr;
1196c58f1c22SToby Isaac 
1197c58f1c22SToby Isaac   PetscFunctionBegin;
1198d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1199c58f1c22SToby Isaac   PetscValidPointer(size, 3);
12000c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
12019e63cc69SVaclav Hapla   ierr = DMLabelGetStratumSize_Private(label, v, size);CHKERRQ(ierr);
1202c58f1c22SToby Isaac   PetscFunctionReturn(0);
1203c58f1c22SToby Isaac }
1204c58f1c22SToby Isaac 
120584f0b6dfSMatthew G. Knepley /*@
120684f0b6dfSMatthew G. Knepley   DMLabelGetStratumBounds - Get the largest and smallest point of a stratum
120784f0b6dfSMatthew G. Knepley 
12085b5e7992SMatthew G. Knepley   Not collective
12095b5e7992SMatthew G. Knepley 
121084f0b6dfSMatthew G. Knepley   Input Parameters:
121184f0b6dfSMatthew G. Knepley + label - the DMLabel
121284f0b6dfSMatthew G. Knepley - value - the stratum value
121384f0b6dfSMatthew G. Knepley 
121401d2d390SJose E. Roman   Output Parameters:
121584f0b6dfSMatthew G. Knepley + start - the smallest point in the stratum
121684f0b6dfSMatthew G. Knepley - end - the largest point in the stratum
121784f0b6dfSMatthew G. Knepley 
121884f0b6dfSMatthew G. Knepley   Level: intermediate
121984f0b6dfSMatthew G. Knepley 
122084f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
122184f0b6dfSMatthew G. Knepley @*/
1222c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumBounds(DMLabel label, PetscInt value, PetscInt *start, PetscInt *end)
1223c58f1c22SToby Isaac {
12240c3c4a36SLisandro Dalcin   PetscInt       v, min, max;
1225c58f1c22SToby Isaac   PetscErrorCode ierr;
1226c58f1c22SToby Isaac 
1227c58f1c22SToby Isaac   PetscFunctionBegin;
1228d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1229cade499fSVaclav Hapla   if (start) {PetscValidPointer(start, 3); *start = -1;}
1230cade499fSVaclav Hapla   if (end)   {PetscValidPointer(end,   4); *end   = -1;}
12310c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
12320c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1233c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
12340c3c4a36SLisandro Dalcin   if (label->stratumSizes[v] <= 0) PetscFunctionReturn(0);
1235d6cb179aSToby Isaac   ierr = ISGetMinMax(label->points[v], &min, &max);CHKERRQ(ierr);
1236d6cb179aSToby Isaac   if (start) *start = min;
1237d6cb179aSToby Isaac   if (end)   *end   = max+1;
1238c58f1c22SToby Isaac   PetscFunctionReturn(0);
1239c58f1c22SToby Isaac }
1240c58f1c22SToby Isaac 
124184f0b6dfSMatthew G. Knepley /*@
124284f0b6dfSMatthew G. Knepley   DMLabelGetStratumIS - Get an IS with the stratum points
124384f0b6dfSMatthew G. Knepley 
12445b5e7992SMatthew G. Knepley   Not collective
12455b5e7992SMatthew G. Knepley 
124684f0b6dfSMatthew G. Knepley   Input Parameters:
124784f0b6dfSMatthew G. Knepley + label - the DMLabel
124884f0b6dfSMatthew G. Knepley - value - the stratum value
124984f0b6dfSMatthew G. Knepley 
125001d2d390SJose E. Roman   Output Parameter:
125184f0b6dfSMatthew G. Knepley . points - The stratum points
125284f0b6dfSMatthew G. Knepley 
125384f0b6dfSMatthew G. Knepley   Level: intermediate
125484f0b6dfSMatthew G. Knepley 
1255593ce467SVaclav Hapla   Notes:
1256593ce467SVaclav Hapla   The output IS should be destroyed when no longer needed.
1257593ce467SVaclav Hapla   Returns NULL if the stratum is empty.
1258593ce467SVaclav Hapla 
125984f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
126084f0b6dfSMatthew G. Knepley @*/
1261c58f1c22SToby Isaac PetscErrorCode DMLabelGetStratumIS(DMLabel label, PetscInt value, IS *points)
1262c58f1c22SToby Isaac {
1263c58f1c22SToby Isaac   PetscInt       v;
1264c58f1c22SToby Isaac   PetscErrorCode ierr;
1265c58f1c22SToby Isaac 
1266c58f1c22SToby Isaac   PetscFunctionBegin;
1267d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1268c58f1c22SToby Isaac   PetscValidPointer(points, 3);
1269c58f1c22SToby Isaac   *points = NULL;
12700c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
12710c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
1272c58f1c22SToby Isaac   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1273ad8374ffSToby Isaac   ierr = PetscObjectReference((PetscObject) label->points[v]);CHKERRQ(ierr);
1274ad8374ffSToby Isaac   *points = label->points[v];
1275c58f1c22SToby Isaac   PetscFunctionReturn(0);
1276c58f1c22SToby Isaac }
1277c58f1c22SToby Isaac 
127884f0b6dfSMatthew G. Knepley /*@
127984f0b6dfSMatthew G. Knepley   DMLabelSetStratumIS - Set the stratum points using an IS
128084f0b6dfSMatthew G. Knepley 
12815b5e7992SMatthew G. Knepley   Not collective
12825b5e7992SMatthew G. Knepley 
128384f0b6dfSMatthew G. Knepley   Input Parameters:
128484f0b6dfSMatthew G. Knepley + label - the DMLabel
128584f0b6dfSMatthew G. Knepley . value - the stratum value
128684f0b6dfSMatthew G. Knepley - points - The stratum points
128784f0b6dfSMatthew G. Knepley 
128884f0b6dfSMatthew G. Knepley   Level: intermediate
128984f0b6dfSMatthew G. Knepley 
129084f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
129184f0b6dfSMatthew G. Knepley @*/
12924de306b1SToby Isaac PetscErrorCode DMLabelSetStratumIS(DMLabel label, PetscInt value, IS is)
12934de306b1SToby Isaac {
12940c3c4a36SLisandro Dalcin   PetscInt       v;
12954de306b1SToby Isaac   PetscErrorCode ierr;
12964de306b1SToby Isaac 
12974de306b1SToby Isaac   PetscFunctionBegin;
1298d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1299d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(is, IS_CLASSID, 3);
1300b9907514SLisandro Dalcin   ierr = DMLabelLookupAddStratum(label, value, &v);CHKERRQ(ierr);
13014de306b1SToby Isaac   if (is == label->points[v]) PetscFunctionReturn(0);
13024de306b1SToby Isaac   ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr);
13034de306b1SToby Isaac   ierr = ISGetLocalSize(is, &(label->stratumSizes[v]));CHKERRQ(ierr);
13044de306b1SToby Isaac   ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr);
13054de306b1SToby Isaac   ierr = ISDestroy(&(label->points[v]));CHKERRQ(ierr);
13060c3c4a36SLisandro Dalcin   label->points[v]  = is;
13070c3c4a36SLisandro Dalcin   label->validIS[v] = PETSC_TRUE;
1308277ea44aSLisandro Dalcin   ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
13094de306b1SToby Isaac   if (label->bt) {
13104de306b1SToby Isaac     const PetscInt *points;
13114de306b1SToby Isaac     PetscInt p;
13124de306b1SToby Isaac 
13134de306b1SToby Isaac     ierr = ISGetIndices(is,&points);CHKERRQ(ierr);
13144de306b1SToby Isaac     for (p = 0; p < label->stratumSizes[v]; ++p) {
13154de306b1SToby Isaac       const PetscInt point = points[p];
13164de306b1SToby Isaac 
13174de306b1SToby Isaac       if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
13184de306b1SToby Isaac       ierr = PetscBTSet(label->bt, point - label->pStart);CHKERRQ(ierr);
13194de306b1SToby Isaac     }
13204de306b1SToby Isaac   }
13214de306b1SToby Isaac   PetscFunctionReturn(0);
13224de306b1SToby Isaac }
13234de306b1SToby Isaac 
132484f0b6dfSMatthew G. Knepley /*@
132584f0b6dfSMatthew G. Knepley   DMLabelClearStratum - Remove a stratum
13264de306b1SToby Isaac 
13275b5e7992SMatthew G. Knepley   Not collective
13285b5e7992SMatthew G. Knepley 
132984f0b6dfSMatthew G. Knepley   Input Parameters:
133084f0b6dfSMatthew G. Knepley + label - the DMLabel
133184f0b6dfSMatthew G. Knepley - value - the stratum value
133284f0b6dfSMatthew G. Knepley 
133384f0b6dfSMatthew G. Knepley   Level: intermediate
133484f0b6dfSMatthew G. Knepley 
133584f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
133684f0b6dfSMatthew G. Knepley @*/
1337c58f1c22SToby Isaac PetscErrorCode DMLabelClearStratum(DMLabel label, PetscInt value)
1338c58f1c22SToby Isaac {
1339c58f1c22SToby Isaac   PetscInt       v;
1340c58f1c22SToby Isaac   PetscErrorCode ierr;
1341c58f1c22SToby Isaac 
1342c58f1c22SToby Isaac   PetscFunctionBegin;
1343d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
13440c3c4a36SLisandro Dalcin   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
13450c3c4a36SLisandro Dalcin   if (v < 0) PetscFunctionReturn(0);
13464de306b1SToby Isaac   if (label->validIS[v]) {
13474de306b1SToby Isaac     if (label->bt) {
1348c58f1c22SToby Isaac       PetscInt       i;
1349ad8374ffSToby Isaac       const PetscInt *points;
1350c58f1c22SToby Isaac 
1351ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[v], &points);CHKERRQ(ierr);
1352c58f1c22SToby Isaac       for (i = 0; i < label->stratumSizes[v]; ++i) {
1353ad8374ffSToby Isaac         const PetscInt point = points[i];
1354c58f1c22SToby Isaac 
1355c58f1c22SToby Isaac         if ((point < label->pStart) || (point >= label->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [%D, %D)", point, label->pStart, label->pEnd);
1356c58f1c22SToby Isaac         ierr = PetscBTClear(label->bt, point - label->pStart);CHKERRQ(ierr);
1357c58f1c22SToby Isaac       }
1358ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[v], &points);CHKERRQ(ierr);
1359c58f1c22SToby Isaac     }
1360c58f1c22SToby Isaac     label->stratumSizes[v] = 0;
13610c3c4a36SLisandro Dalcin     ierr = ISDestroy(&label->points[v]);CHKERRQ(ierr);
1362277ea44aSLisandro Dalcin     ierr = ISCreateStride(PETSC_COMM_SELF, 0, 0, 1, &label->points[v]);CHKERRQ(ierr);
13630c3c4a36SLisandro Dalcin     ierr = PetscObjectSetName((PetscObject) label->points[v], "indices");CHKERRQ(ierr);
1364277ea44aSLisandro Dalcin     ierr = PetscObjectStateIncrease((PetscObject) label);CHKERRQ(ierr);
1365c58f1c22SToby Isaac   } else {
1366b9907514SLisandro Dalcin     ierr = PetscHSetIClear(label->ht[v]);CHKERRQ(ierr);
1367c58f1c22SToby Isaac   }
1368c58f1c22SToby Isaac   PetscFunctionReturn(0);
1369c58f1c22SToby Isaac }
1370c58f1c22SToby Isaac 
137184f0b6dfSMatthew G. Knepley /*@
1372412e9a14SMatthew G. Knepley   DMLabelSetStratumBounds - Efficiently give a contiguous set of points a given label value
1373412e9a14SMatthew G. Knepley 
1374412e9a14SMatthew G. Knepley   Not collective
1375412e9a14SMatthew G. Knepley 
1376412e9a14SMatthew G. Knepley   Input Parameters:
1377412e9a14SMatthew G. Knepley + label  - The DMLabel
1378412e9a14SMatthew G. Knepley . value  - The label value for all points
1379412e9a14SMatthew G. Knepley . pStart - The first point
1380412e9a14SMatthew G. Knepley - pEnd   - A point beyond all marked points
1381412e9a14SMatthew G. Knepley 
1382412e9a14SMatthew G. Knepley   Note: The marks points are [pStart, pEnd), and only the bounds are stored.
1383412e9a14SMatthew G. Knepley 
1384412e9a14SMatthew G. Knepley   Level: intermediate
1385412e9a14SMatthew G. Knepley 
1386412e9a14SMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelSetStratumIS(), DMLabelGetStratumIS()
1387412e9a14SMatthew G. Knepley @*/
1388412e9a14SMatthew G. Knepley PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt pStart, PetscInt pEnd)
1389412e9a14SMatthew G. Knepley {
1390412e9a14SMatthew G. Knepley   IS             pIS;
1391412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1392412e9a14SMatthew G. Knepley 
1393412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1394412e9a14SMatthew G. Knepley   ierr = ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &pIS);CHKERRQ(ierr);
1395412e9a14SMatthew G. Knepley   ierr = DMLabelSetStratumIS(label, value, pIS);CHKERRQ(ierr);
1396412e9a14SMatthew G. Knepley   ierr = ISDestroy(&pIS);CHKERRQ(ierr);
1397412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1398412e9a14SMatthew G. Knepley }
1399412e9a14SMatthew G. Knepley 
1400412e9a14SMatthew G. Knepley /*@
1401d123abd9SMatthew G. Knepley   DMLabelGetStratumPointIndex - Get the index of a point in a given stratum
1402d123abd9SMatthew G. Knepley 
1403d123abd9SMatthew G. Knepley   Not collective
1404d123abd9SMatthew G. Knepley 
1405d123abd9SMatthew G. Knepley   Input Parameters:
1406d123abd9SMatthew G. Knepley + label  - The DMLabel
1407d123abd9SMatthew G. Knepley . value  - The label value
1408d123abd9SMatthew G. Knepley - p      - A point with this value
1409d123abd9SMatthew G. Knepley 
1410d123abd9SMatthew G. Knepley   Output Parameter:
1411d123abd9SMatthew 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
1412d123abd9SMatthew G. Knepley 
1413d123abd9SMatthew G. Knepley   Level: intermediate
1414d123abd9SMatthew G. Knepley 
1415d123abd9SMatthew G. Knepley .seealso: DMLabelGetValueIndex(), DMLabelGetStratumIS(), DMLabelCreate()
1416d123abd9SMatthew G. Knepley @*/
1417d123abd9SMatthew G. Knepley PetscErrorCode DMLabelGetStratumPointIndex(DMLabel label, PetscInt value, PetscInt p, PetscInt *index)
1418d123abd9SMatthew G. Knepley {
1419d123abd9SMatthew G. Knepley   const PetscInt *indices;
1420d123abd9SMatthew G. Knepley   PetscInt        v;
1421d123abd9SMatthew G. Knepley   PetscErrorCode  ierr;
1422d123abd9SMatthew G. Knepley 
1423d123abd9SMatthew G. Knepley   PetscFunctionBegin;
1424d123abd9SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1425d123abd9SMatthew G. Knepley   PetscValidPointer(index, 4);
1426d123abd9SMatthew G. Knepley   *index = -1;
1427d123abd9SMatthew G. Knepley   ierr = DMLabelLookupStratum(label, value, &v);CHKERRQ(ierr);
1428d123abd9SMatthew G. Knepley   if (v < 0) PetscFunctionReturn(0);
1429d123abd9SMatthew G. Knepley   ierr = DMLabelMakeValid_Private(label, v);CHKERRQ(ierr);
1430d123abd9SMatthew G. Knepley   ierr = ISGetIndices(label->points[v], &indices);CHKERRQ(ierr);
1431d123abd9SMatthew G. Knepley   ierr = PetscFindInt(p, label->stratumSizes[v], indices, index);CHKERRQ(ierr);
1432d123abd9SMatthew G. Knepley   ierr = ISRestoreIndices(label->points[v], &indices);CHKERRQ(ierr);
1433d123abd9SMatthew G. Knepley   PetscFunctionReturn(0);
1434d123abd9SMatthew G. Knepley }
1435d123abd9SMatthew G. Knepley 
1436d123abd9SMatthew G. Knepley /*@
143784f0b6dfSMatthew G. Knepley   DMLabelFilter - Remove all points outside of [start, end)
143884f0b6dfSMatthew G. Knepley 
14395b5e7992SMatthew G. Knepley   Not collective
14405b5e7992SMatthew G. Knepley 
144184f0b6dfSMatthew G. Knepley   Input Parameters:
144284f0b6dfSMatthew G. Knepley + label - the DMLabel
144322cd2cdaSVaclav Hapla . start - the first point kept
144422cd2cdaSVaclav Hapla - end - one more than the last point kept
144584f0b6dfSMatthew G. Knepley 
144684f0b6dfSMatthew G. Knepley   Level: intermediate
144784f0b6dfSMatthew G. Knepley 
144884f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
144984f0b6dfSMatthew G. Knepley @*/
1450c58f1c22SToby Isaac PetscErrorCode DMLabelFilter(DMLabel label, PetscInt start, PetscInt end)
1451c58f1c22SToby Isaac {
1452c58f1c22SToby Isaac   PetscInt       v;
1453c58f1c22SToby Isaac   PetscErrorCode ierr;
1454c58f1c22SToby Isaac 
1455c58f1c22SToby Isaac   PetscFunctionBegin;
1456d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
14570c3c4a36SLisandro Dalcin   ierr = DMLabelDestroyIndex(label);CHKERRQ(ierr);
1458c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1459c58f1c22SToby Isaac   for (v = 0; v < label->numStrata; ++v) {
14609106b633SVaclav Hapla     ierr = ISGeneralFilter(label->points[v], start, end);CHKERRQ(ierr);
1461c58f1c22SToby Isaac   }
1462c58f1c22SToby Isaac   ierr = DMLabelCreateIndex(label, start, end);CHKERRQ(ierr);
1463c58f1c22SToby Isaac   PetscFunctionReturn(0);
1464c58f1c22SToby Isaac }
1465c58f1c22SToby Isaac 
146684f0b6dfSMatthew G. Knepley /*@
146784f0b6dfSMatthew G. Knepley   DMLabelPermute - Create a new label with permuted points
146884f0b6dfSMatthew G. Knepley 
14695b5e7992SMatthew G. Knepley   Not collective
14705b5e7992SMatthew G. Knepley 
147184f0b6dfSMatthew G. Knepley   Input Parameters:
147284f0b6dfSMatthew G. Knepley + label - the DMLabel
147384f0b6dfSMatthew G. Knepley - permutation - the point permutation
147484f0b6dfSMatthew G. Knepley 
147584f0b6dfSMatthew G. Knepley   Output Parameter:
147684f0b6dfSMatthew G. Knepley . labelnew - the new label containing the permuted points
147784f0b6dfSMatthew G. Knepley 
147884f0b6dfSMatthew G. Knepley   Level: intermediate
147984f0b6dfSMatthew G. Knepley 
148084f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
148184f0b6dfSMatthew G. Knepley @*/
1482c58f1c22SToby Isaac PetscErrorCode DMLabelPermute(DMLabel label, IS permutation, DMLabel *labelNew)
1483c58f1c22SToby Isaac {
1484c58f1c22SToby Isaac   const PetscInt *perm;
1485c58f1c22SToby Isaac   PetscInt        numValues, numPoints, v, q;
1486c58f1c22SToby Isaac   PetscErrorCode  ierr;
1487c58f1c22SToby Isaac 
1488c58f1c22SToby Isaac   PetscFunctionBegin;
1489d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1490d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
1491c58f1c22SToby Isaac   ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1492c58f1c22SToby Isaac   ierr = DMLabelDuplicate(label, labelNew);CHKERRQ(ierr);
1493c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(*labelNew, &numValues);CHKERRQ(ierr);
1494c58f1c22SToby Isaac   ierr = ISGetLocalSize(permutation, &numPoints);CHKERRQ(ierr);
1495c58f1c22SToby Isaac   ierr = ISGetIndices(permutation, &perm);CHKERRQ(ierr);
1496c58f1c22SToby Isaac   for (v = 0; v < numValues; ++v) {
1497c58f1c22SToby Isaac     const PetscInt size   = (*labelNew)->stratumSizes[v];
1498ad8374ffSToby Isaac     const PetscInt *points;
1499ad8374ffSToby Isaac     PetscInt *pointsNew;
1500c58f1c22SToby Isaac 
1501ad8374ffSToby Isaac     ierr = ISGetIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1502ad8374ffSToby Isaac     ierr = PetscMalloc1(size,&pointsNew);CHKERRQ(ierr);
1503c58f1c22SToby Isaac     for (q = 0; q < size; ++q) {
1504ad8374ffSToby Isaac       const PetscInt point = points[q];
1505c58f1c22SToby Isaac 
1506c58f1c22SToby Isaac       if ((point < 0) || (point >= numPoints)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label point %D is not in [0, %D) for the remapping", point, numPoints);
1507ad8374ffSToby Isaac       pointsNew[q] = perm[point];
1508c58f1c22SToby Isaac     }
1509ad8374ffSToby Isaac     ierr = ISRestoreIndices((*labelNew)->points[v],&points);CHKERRQ(ierr);
1510ad8374ffSToby Isaac     ierr = PetscSortInt(size, pointsNew);CHKERRQ(ierr);
1511ad8374ffSToby Isaac     ierr = ISDestroy(&((*labelNew)->points[v]));CHKERRQ(ierr);
1512fa8e8ae5SToby Isaac     if (size > 0 && pointsNew[size - 1] == pointsNew[0] + size - 1) {
1513fa8e8ae5SToby Isaac       ierr = ISCreateStride(PETSC_COMM_SELF,size,pointsNew[0],1,&((*labelNew)->points[v]));CHKERRQ(ierr);
1514fa8e8ae5SToby Isaac       ierr = PetscFree(pointsNew);CHKERRQ(ierr);
1515fa8e8ae5SToby Isaac     } else {
1516ad8374ffSToby Isaac       ierr = ISCreateGeneral(PETSC_COMM_SELF,size,pointsNew,PETSC_OWN_POINTER,&((*labelNew)->points[v]));CHKERRQ(ierr);
1517fa8e8ae5SToby Isaac     }
1518ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject) ((*labelNew)->points[v]), "indices");CHKERRQ(ierr);
1519c58f1c22SToby Isaac   }
1520c58f1c22SToby Isaac   ierr = ISRestoreIndices(permutation, &perm);CHKERRQ(ierr);
1521c58f1c22SToby Isaac   if (label->bt) {
1522c58f1c22SToby Isaac     ierr = PetscBTDestroy(&label->bt);CHKERRQ(ierr);
1523c58f1c22SToby Isaac     ierr = DMLabelCreateIndex(label, label->pStart, label->pEnd);CHKERRQ(ierr);
1524c58f1c22SToby Isaac   }
1525c58f1c22SToby Isaac   PetscFunctionReturn(0);
1526c58f1c22SToby Isaac }
1527c58f1c22SToby Isaac 
152826c55118SMichael Lange PetscErrorCode DMLabelDistribute_Internal(DMLabel label, PetscSF sf, PetscSection *leafSection, PetscInt **leafStrata)
152926c55118SMichael Lange {
153026c55118SMichael Lange   MPI_Comm       comm;
153126c55118SMichael Lange   PetscInt       s, l, nroots, nleaves, dof, offset, size;
153226c55118SMichael Lange   PetscInt      *remoteOffsets, *rootStrata, *rootIdx;
153326c55118SMichael Lange   PetscSection   rootSection;
153426c55118SMichael Lange   PetscSF        labelSF;
153526c55118SMichael Lange   PetscErrorCode ierr;
153626c55118SMichael Lange 
153726c55118SMichael Lange   PetscFunctionBegin;
153826c55118SMichael Lange   if (label) {ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);}
153926c55118SMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
154026c55118SMichael Lange   /* Build a section of stratum values per point, generate the according SF
154126c55118SMichael Lange      and distribute point-wise stratum values to leaves. */
154226c55118SMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL);CHKERRQ(ierr);
154326c55118SMichael Lange   ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr);
154426c55118SMichael Lange   ierr = PetscSectionSetChart(rootSection, 0, nroots);CHKERRQ(ierr);
154526c55118SMichael Lange   if (label) {
154626c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1547ad8374ffSToby Isaac       const PetscInt *points;
1548ad8374ffSToby Isaac 
1549ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
155026c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1551ad8374ffSToby Isaac         ierr = PetscSectionGetDof(rootSection, points[l], &dof);CHKERRQ(ierr);
1552ad8374ffSToby Isaac         ierr = PetscSectionSetDof(rootSection, points[l], dof+1);CHKERRQ(ierr);
155326c55118SMichael Lange       }
1554ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
155526c55118SMichael Lange     }
155626c55118SMichael Lange   }
155726c55118SMichael Lange   ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr);
155826c55118SMichael Lange   /* Create a point-wise array of stratum values */
155926c55118SMichael Lange   ierr = PetscSectionGetStorageSize(rootSection, &size);CHKERRQ(ierr);
156026c55118SMichael Lange   ierr = PetscMalloc1(size, &rootStrata);CHKERRQ(ierr);
156126c55118SMichael Lange   ierr = PetscCalloc1(nroots, &rootIdx);CHKERRQ(ierr);
156226c55118SMichael Lange   if (label) {
156326c55118SMichael Lange     for (s = 0; s < label->numStrata; ++s) {
1564ad8374ffSToby Isaac       const PetscInt *points;
1565ad8374ffSToby Isaac 
1566ad8374ffSToby Isaac       ierr = ISGetIndices(label->points[s], &points);CHKERRQ(ierr);
156726c55118SMichael Lange       for (l = 0; l < label->stratumSizes[s]; l++) {
1568ad8374ffSToby Isaac         const PetscInt p = points[l];
156926c55118SMichael Lange         ierr = PetscSectionGetOffset(rootSection, p, &offset);CHKERRQ(ierr);
157026c55118SMichael Lange         rootStrata[offset+rootIdx[p]++] = label->stratumValues[s];
157126c55118SMichael Lange       }
1572ad8374ffSToby Isaac       ierr = ISRestoreIndices(label->points[s], &points);CHKERRQ(ierr);
157326c55118SMichael Lange     }
157426c55118SMichael Lange   }
157526c55118SMichael Lange   /* Build SF that maps label points to remote processes */
157626c55118SMichael Lange   ierr = PetscSectionCreate(comm, leafSection);CHKERRQ(ierr);
157726c55118SMichael Lange   ierr = PetscSFDistributeSection(sf, rootSection, &remoteOffsets, *leafSection);CHKERRQ(ierr);
157826c55118SMichael Lange   ierr = PetscSFCreateSectionSF(sf, rootSection, remoteOffsets, *leafSection, &labelSF);CHKERRQ(ierr);
157926c55118SMichael Lange   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
158026c55118SMichael Lange   /* Send the strata for each point over the derived SF */
158126c55118SMichael Lange   ierr = PetscSectionGetStorageSize(*leafSection, &size);CHKERRQ(ierr);
158226c55118SMichael Lange   ierr = PetscMalloc1(size, leafStrata);CHKERRQ(ierr);
1583ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE);CHKERRQ(ierr);
1584ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(labelSF, MPIU_INT, rootStrata, *leafStrata,MPI_REPLACE);CHKERRQ(ierr);
158526c55118SMichael Lange   /* Clean up */
158626c55118SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
158726c55118SMichael Lange   ierr = PetscFree(rootIdx);CHKERRQ(ierr);
158826c55118SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
158926c55118SMichael Lange   ierr = PetscSFDestroy(&labelSF);CHKERRQ(ierr);
159026c55118SMichael Lange   PetscFunctionReturn(0);
159126c55118SMichael Lange }
159226c55118SMichael Lange 
159384f0b6dfSMatthew G. Knepley /*@
159484f0b6dfSMatthew G. Knepley   DMLabelDistribute - Create a new label pushed forward over the PetscSF
159584f0b6dfSMatthew G. Knepley 
15965b5e7992SMatthew G. Knepley   Collective on sf
15975b5e7992SMatthew G. Knepley 
159884f0b6dfSMatthew G. Knepley   Input Parameters:
159984f0b6dfSMatthew G. Knepley + label - the DMLabel
160084f0b6dfSMatthew G. Knepley - sf    - the map from old to new distribution
160184f0b6dfSMatthew G. Knepley 
160284f0b6dfSMatthew G. Knepley   Output Parameter:
160384f0b6dfSMatthew G. Knepley . labelnew - the new redistributed label
160484f0b6dfSMatthew G. Knepley 
160584f0b6dfSMatthew G. Knepley   Level: intermediate
160684f0b6dfSMatthew G. Knepley 
160784f0b6dfSMatthew G. Knepley .seealso: DMLabelCreate(), DMLabelGetValue(), DMLabelSetValue(), DMLabelClearValue()
160884f0b6dfSMatthew G. Knepley @*/
1609c58f1c22SToby Isaac PetscErrorCode DMLabelDistribute(DMLabel label, PetscSF sf, DMLabel *labelNew)
1610c58f1c22SToby Isaac {
1611c58f1c22SToby Isaac   MPI_Comm       comm;
161226c55118SMichael Lange   PetscSection   leafSection;
161326c55118SMichael Lange   PetscInt       p, pStart, pEnd, s, size, dof, offset, stratum;
161426c55118SMichael Lange   PetscInt      *leafStrata, *strataIdx;
1615ad8374ffSToby Isaac   PetscInt     **points;
1616d67d17b1SMatthew G. Knepley   const char    *lname = NULL;
1617c58f1c22SToby Isaac   char          *name;
1618c58f1c22SToby Isaac   PetscInt       nameSize;
1619e8f14785SLisandro Dalcin   PetscHSetI     stratumHash;
1620c58f1c22SToby Isaac   size_t         len = 0;
162126c55118SMichael Lange   PetscMPIInt    rank;
1622c58f1c22SToby Isaac   PetscErrorCode ierr;
1623c58f1c22SToby Isaac 
1624c58f1c22SToby Isaac   PetscFunctionBegin;
1625d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1626f018e600SMatthew G. Knepley   if (label) {
1627f018e600SMatthew G. Knepley     PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1628f018e600SMatthew G. Knepley     ierr = DMLabelMakeAllValid_Private(label);CHKERRQ(ierr);
1629f018e600SMatthew G. Knepley   }
1630c58f1c22SToby Isaac   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
1631ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1632c58f1c22SToby Isaac   /* Bcast name */
1633dd400576SPatrick Sanan   if (rank == 0) {
1634d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1635d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1636d67d17b1SMatthew G. Knepley   }
1637c58f1c22SToby Isaac   nameSize = len;
1638ffc4695bSBarry Smith   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1639c58f1c22SToby Isaac   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1640dd400576SPatrick Sanan   if (rank == 0) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
1641ffc4695bSBarry Smith   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr);
1642d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
1643c58f1c22SToby Isaac   ierr = PetscFree(name);CHKERRQ(ierr);
164477d236dfSMichael Lange   /* Bcast defaultValue */
1645dd400576SPatrick Sanan   if (rank == 0) (*labelNew)->defaultValue = label->defaultValue;
1646ffc4695bSBarry Smith   ierr = MPI_Bcast(&(*labelNew)->defaultValue, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
164726c55118SMichael Lange   /* Distribute stratum values over the SF and get the point mapping on the receiver */
164826c55118SMichael Lange   ierr = DMLabelDistribute_Internal(label, sf, &leafSection, &leafStrata);CHKERRQ(ierr);
16495cbdf6fcSMichael Lange   /* Determine received stratum values and initialise new label*/
1650e8f14785SLisandro Dalcin   ierr = PetscHSetICreate(&stratumHash);CHKERRQ(ierr);
165126c55118SMichael Lange   ierr = PetscSectionGetStorageSize(leafSection, &size);CHKERRQ(ierr);
1652e8f14785SLisandro Dalcin   for (p = 0; p < size; ++p) {ierr = PetscHSetIAdd(stratumHash, leafStrata[p]);CHKERRQ(ierr);}
1653e8f14785SLisandro Dalcin   ierr = PetscHSetIGetSize(stratumHash, &(*labelNew)->numStrata);CHKERRQ(ierr);
1654ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->validIS);CHKERRQ(ierr);
1655ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) (*labelNew)->validIS[s] = PETSC_TRUE;
16565cbdf6fcSMichael Lange   ierr = PetscMalloc1((*labelNew)->numStrata, &(*labelNew)->stratumValues);CHKERRQ(ierr);
16575cbdf6fcSMichael Lange   /* Turn leafStrata into indices rather than stratum values */
16585cbdf6fcSMichael Lange   offset = 0;
1659e8f14785SLisandro Dalcin   ierr = PetscHSetIGetElems(stratumHash, &offset, (*labelNew)->stratumValues);CHKERRQ(ierr);
1660a205f1fdSToby Isaac   ierr = PetscSortInt((*labelNew)->numStrata,(*labelNew)->stratumValues);CHKERRQ(ierr);
166190e9b2aeSLisandro Dalcin   for (s = 0; s < (*labelNew)->numStrata; ++s) {
166290e9b2aeSLisandro Dalcin     ierr = PetscHMapISet((*labelNew)->hmap, (*labelNew)->stratumValues[s], s);CHKERRQ(ierr);
166390e9b2aeSLisandro Dalcin   }
16645cbdf6fcSMichael Lange   for (p = 0; p < size; ++p) {
1665231b9e6fSMatthew G. Knepley     for (s = 0; s < (*labelNew)->numStrata; ++s) {
1666231b9e6fSMatthew G. Knepley       if (leafStrata[p] == (*labelNew)->stratumValues[s]) {leafStrata[p] = s; break;}
16675cbdf6fcSMichael Lange     }
16685cbdf6fcSMichael Lange   }
1669c58f1c22SToby Isaac   /* Rebuild the point strata on the receiver */
1670c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->stratumSizes);CHKERRQ(ierr);
1671c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1672c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1673c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1674c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1675c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1676c58f1c22SToby Isaac       (*labelNew)->stratumSizes[leafStrata[offset+s]]++;
1677c58f1c22SToby Isaac     }
1678c58f1c22SToby Isaac   }
1679c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata,&(*labelNew)->ht);CHKERRQ(ierr);
1680c58f1c22SToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&(*labelNew)->points);CHKERRQ(ierr);
1681ad8374ffSToby Isaac   ierr = PetscMalloc1((*labelNew)->numStrata,&points);CHKERRQ(ierr);
1682c58f1c22SToby Isaac   for (s = 0; s < (*labelNew)->numStrata; ++s) {
1683e8f14785SLisandro Dalcin     ierr = PetscHSetICreate(&(*labelNew)->ht[s]);CHKERRQ(ierr);
1684ad8374ffSToby Isaac     ierr = PetscMalloc1((*labelNew)->stratumSizes[s], &(points[s]));CHKERRQ(ierr);
1685c58f1c22SToby Isaac   }
1686c58f1c22SToby Isaac   /* Insert points into new strata */
1687c58f1c22SToby Isaac   ierr = PetscCalloc1((*labelNew)->numStrata, &strataIdx);CHKERRQ(ierr);
1688c58f1c22SToby Isaac   ierr = PetscSectionGetChart(leafSection, &pStart, &pEnd);CHKERRQ(ierr);
1689c58f1c22SToby Isaac   for (p=pStart; p<pEnd; p++) {
1690c58f1c22SToby Isaac     ierr = PetscSectionGetDof(leafSection, p, &dof);CHKERRQ(ierr);
1691c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(leafSection, p, &offset);CHKERRQ(ierr);
1692c58f1c22SToby Isaac     for (s=0; s<dof; s++) {
1693c58f1c22SToby Isaac       stratum = leafStrata[offset+s];
1694ad8374ffSToby Isaac       points[stratum][strataIdx[stratum]++] = p;
1695c58f1c22SToby Isaac     }
1696c58f1c22SToby Isaac   }
1697ad8374ffSToby Isaac   for (s = 0; s < (*labelNew)->numStrata; s++) {
1698ad8374ffSToby Isaac     ierr = ISCreateGeneral(PETSC_COMM_SELF,(*labelNew)->stratumSizes[s],&(points[s][0]),PETSC_OWN_POINTER,&((*labelNew)->points[s]));CHKERRQ(ierr);
1699ad8374ffSToby Isaac     ierr = PetscObjectSetName((PetscObject)((*labelNew)->points[s]),"indices");CHKERRQ(ierr);
1700ad8374ffSToby Isaac   }
1701ad8374ffSToby Isaac   ierr = PetscFree(points);CHKERRQ(ierr);
1702e8f14785SLisandro Dalcin   ierr = PetscHSetIDestroy(&stratumHash);CHKERRQ(ierr);
1703c58f1c22SToby Isaac   ierr = PetscFree(leafStrata);CHKERRQ(ierr);
1704c58f1c22SToby Isaac   ierr = PetscFree(strataIdx);CHKERRQ(ierr);
1705c58f1c22SToby Isaac   ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr);
1706c58f1c22SToby Isaac   PetscFunctionReturn(0);
1707c58f1c22SToby Isaac }
1708c58f1c22SToby Isaac 
17097937d9ceSMichael Lange /*@
17107937d9ceSMichael Lange   DMLabelGather - Gather all label values from leafs into roots
17117937d9ceSMichael Lange 
17125b5e7992SMatthew G. Knepley   Collective on sf
17135b5e7992SMatthew G. Knepley 
17147937d9ceSMichael Lange   Input Parameters:
17157937d9ceSMichael Lange + label - the DMLabel
171684f0b6dfSMatthew G. Knepley - sf - the Star Forest point communication map
17177937d9ceSMichael Lange 
171884f0b6dfSMatthew G. Knepley   Output Parameters:
171984f0b6dfSMatthew G. Knepley . labelNew - the new DMLabel with localised leaf values
17207937d9ceSMichael Lange 
17217937d9ceSMichael Lange   Level: developer
17227937d9ceSMichael Lange 
17237937d9ceSMichael Lange   Note: This is the inverse operation to DMLabelDistribute.
17247937d9ceSMichael Lange 
17257937d9ceSMichael Lange .seealso: DMLabelDistribute()
17267937d9ceSMichael Lange @*/
17277937d9ceSMichael Lange PetscErrorCode DMLabelGather(DMLabel label, PetscSF sf, DMLabel *labelNew)
17287937d9ceSMichael Lange {
17297937d9ceSMichael Lange   MPI_Comm       comm;
17307937d9ceSMichael Lange   PetscSection   rootSection;
17317937d9ceSMichael Lange   PetscSF        sfLabel;
17327937d9ceSMichael Lange   PetscSFNode   *rootPoints, *leafPoints;
17337937d9ceSMichael Lange   PetscInt       p, s, d, nroots, nleaves, nmultiroots, idx, dof, offset;
17347937d9ceSMichael Lange   const PetscInt *rootDegree, *ilocal;
17357937d9ceSMichael Lange   PetscInt       *rootStrata;
1736d67d17b1SMatthew G. Knepley   const char    *lname;
17377937d9ceSMichael Lange   char          *name;
17387937d9ceSMichael Lange   PetscInt       nameSize;
17397937d9ceSMichael Lange   size_t         len = 0;
17409852e123SBarry Smith   PetscMPIInt    rank, size;
17417937d9ceSMichael Lange   PetscErrorCode ierr;
17427937d9ceSMichael Lange 
17437937d9ceSMichael Lange   PetscFunctionBegin;
1744d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1745d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
17467937d9ceSMichael Lange   ierr = PetscObjectGetComm((PetscObject)sf, &comm);CHKERRQ(ierr);
1747ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1748ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
17497937d9ceSMichael Lange   /* Bcast name */
1750dd400576SPatrick Sanan   if (rank == 0) {
1751d67d17b1SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
1752d67d17b1SMatthew G. Knepley     ierr = PetscStrlen(lname, &len);CHKERRQ(ierr);
1753d67d17b1SMatthew G. Knepley   }
17547937d9ceSMichael Lange   nameSize = len;
1755ffc4695bSBarry Smith   ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
17567937d9ceSMichael Lange   ierr = PetscMalloc1(nameSize+1, &name);CHKERRQ(ierr);
1757dd400576SPatrick Sanan   if (rank == 0) {ierr = PetscArraycpy(name, lname, nameSize+1);CHKERRQ(ierr);}
1758ffc4695bSBarry Smith   ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr);
1759d67d17b1SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, name, labelNew);CHKERRQ(ierr);
17607937d9ceSMichael Lange   ierr = PetscFree(name);CHKERRQ(ierr);
17617937d9ceSMichael Lange   /* Gather rank/index pairs of leaves into local roots to build
17627937d9ceSMichael Lange      an inverse, multi-rooted SF. Note that this ignores local leaf
17637937d9ceSMichael Lange      indexing due to the use of the multiSF in PetscSFGather. */
17647937d9ceSMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, NULL);CHKERRQ(ierr);
1765dc53bc9bSMatthew G. Knepley   ierr = PetscMalloc1(nroots, &leafPoints);CHKERRQ(ierr);
1766dc53bc9bSMatthew G. Knepley   for (p = 0; p < nroots; ++p) leafPoints[p].rank = leafPoints[p].index = -1;
17677937d9ceSMichael Lange   for (p = 0; p < nleaves; p++) {
17688212dd46SStefano Zampini     PetscInt ilp = ilocal ? ilocal[p] : p;
17698212dd46SStefano Zampini 
17708212dd46SStefano Zampini     leafPoints[ilp].index = ilp;
17718212dd46SStefano Zampini     leafPoints[ilp].rank  = rank;
17727937d9ceSMichael Lange   }
17737937d9ceSMichael Lange   ierr = PetscSFComputeDegreeBegin(sf, &rootDegree);CHKERRQ(ierr);
17747937d9ceSMichael Lange   ierr = PetscSFComputeDegreeEnd(sf, &rootDegree);CHKERRQ(ierr);
17757937d9ceSMichael Lange   for (p = 0, nmultiroots = 0; p < nroots; ++p) nmultiroots += rootDegree[p];
17767937d9ceSMichael Lange   ierr = PetscMalloc1(nmultiroots, &rootPoints);CHKERRQ(ierr);
17777937d9ceSMichael Lange   ierr = PetscSFGatherBegin(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
17787937d9ceSMichael Lange   ierr = PetscSFGatherEnd(sf, MPIU_2INT, leafPoints, rootPoints);CHKERRQ(ierr);
17797937d9ceSMichael Lange   ierr = PetscSFCreate(comm,& sfLabel);CHKERRQ(ierr);
17807937d9ceSMichael Lange   ierr = PetscSFSetGraph(sfLabel, nroots, nmultiroots, NULL, PETSC_OWN_POINTER, rootPoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
17817937d9ceSMichael Lange   /* Migrate label over inverted SF to pull stratum values at leaves into roots. */
17827937d9ceSMichael Lange   ierr = DMLabelDistribute_Internal(label, sfLabel, &rootSection, &rootStrata);CHKERRQ(ierr);
17837937d9ceSMichael Lange   /* Rebuild the point strata on the receiver */
17847937d9ceSMichael Lange   for (p = 0, idx = 0; p < nroots; p++) {
17857937d9ceSMichael Lange     for (d = 0; d < rootDegree[p]; d++) {
17867937d9ceSMichael Lange       ierr = PetscSectionGetDof(rootSection, idx+d, &dof);CHKERRQ(ierr);
17877937d9ceSMichael Lange       ierr = PetscSectionGetOffset(rootSection, idx+d, &offset);CHKERRQ(ierr);
17887937d9ceSMichael Lange       for (s = 0; s < dof; s++) {ierr = DMLabelSetValue(*labelNew, p, rootStrata[offset+s]);CHKERRQ(ierr);}
17897937d9ceSMichael Lange     }
17907937d9ceSMichael Lange     idx += rootDegree[p];
17917937d9ceSMichael Lange   }
179277e0c0e7SMichael Lange   ierr = PetscFree(leafPoints);CHKERRQ(ierr);
179377e0c0e7SMichael Lange   ierr = PetscFree(rootStrata);CHKERRQ(ierr);
179477e0c0e7SMichael Lange   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
179577e0c0e7SMichael Lange   ierr = PetscSFDestroy(&sfLabel);CHKERRQ(ierr);
17967937d9ceSMichael Lange   PetscFunctionReturn(0);
17977937d9ceSMichael Lange }
17987937d9ceSMichael Lange 
179984f0b6dfSMatthew G. Knepley /*@
180084f0b6dfSMatthew G. Knepley   DMLabelConvertToSection - Make a PetscSection/IS pair that encodes the label
180184f0b6dfSMatthew G. Knepley 
18025b5e7992SMatthew G. Knepley   Not collective
18035b5e7992SMatthew G. Knepley 
180484f0b6dfSMatthew G. Knepley   Input Parameter:
180584f0b6dfSMatthew G. Knepley . label - the DMLabel
180684f0b6dfSMatthew G. Knepley 
180784f0b6dfSMatthew G. Knepley   Output Parameters:
180884f0b6dfSMatthew G. Knepley + section - the section giving offsets for each stratum
180984f0b6dfSMatthew G. Knepley - is - An IS containing all the label points
181084f0b6dfSMatthew G. Knepley 
181184f0b6dfSMatthew G. Knepley   Level: developer
181284f0b6dfSMatthew G. Knepley 
181384f0b6dfSMatthew G. Knepley .seealso: DMLabelDistribute()
181484f0b6dfSMatthew G. Knepley @*/
1815c58f1c22SToby Isaac PetscErrorCode DMLabelConvertToSection(DMLabel label, PetscSection *section, IS *is)
1816c58f1c22SToby Isaac {
1817c58f1c22SToby Isaac   IS              vIS;
1818c58f1c22SToby Isaac   const PetscInt *values;
1819c58f1c22SToby Isaac   PetscInt       *points;
1820c58f1c22SToby Isaac   PetscInt        nV, vS = 0, vE = 0, v, N;
1821c58f1c22SToby Isaac   PetscErrorCode  ierr;
1822c58f1c22SToby Isaac 
1823c58f1c22SToby Isaac   PetscFunctionBegin;
1824d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 1);
1825c58f1c22SToby Isaac   ierr = DMLabelGetNumValues(label, &nV);CHKERRQ(ierr);
1826c58f1c22SToby Isaac   ierr = DMLabelGetValueIS(label, &vIS);CHKERRQ(ierr);
1827c58f1c22SToby Isaac   ierr = ISGetIndices(vIS, &values);CHKERRQ(ierr);
1828c58f1c22SToby Isaac   if (nV) {vS = values[0]; vE = values[0]+1;}
1829c58f1c22SToby Isaac   for (v = 1; v < nV; ++v) {
1830c58f1c22SToby Isaac     vS = PetscMin(vS, values[v]);
1831c58f1c22SToby Isaac     vE = PetscMax(vE, values[v]+1);
1832c58f1c22SToby Isaac   }
1833c58f1c22SToby Isaac   ierr = PetscSectionCreate(PETSC_COMM_SELF, section);CHKERRQ(ierr);
1834c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*section, vS, vE);CHKERRQ(ierr);
1835c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1836c58f1c22SToby Isaac     PetscInt n;
1837c58f1c22SToby Isaac 
1838c58f1c22SToby Isaac     ierr = DMLabelGetStratumSize(label, values[v], &n);CHKERRQ(ierr);
1839c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*section, values[v], n);CHKERRQ(ierr);
1840c58f1c22SToby Isaac   }
1841c58f1c22SToby Isaac   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
1842c58f1c22SToby Isaac   ierr = PetscSectionGetStorageSize(*section, &N);CHKERRQ(ierr);
1843c58f1c22SToby Isaac   ierr = PetscMalloc1(N, &points);CHKERRQ(ierr);
1844c58f1c22SToby Isaac   for (v = 0; v < nV; ++v) {
1845c58f1c22SToby Isaac     IS              is;
1846c58f1c22SToby Isaac     const PetscInt *spoints;
1847c58f1c22SToby Isaac     PetscInt        dof, off, p;
1848c58f1c22SToby Isaac 
1849c58f1c22SToby Isaac     ierr = PetscSectionGetDof(*section, values[v], &dof);CHKERRQ(ierr);
1850c58f1c22SToby Isaac     ierr = PetscSectionGetOffset(*section, values[v], &off);CHKERRQ(ierr);
1851c58f1c22SToby Isaac     ierr = DMLabelGetStratumIS(label, values[v], &is);CHKERRQ(ierr);
1852c58f1c22SToby Isaac     ierr = ISGetIndices(is, &spoints);CHKERRQ(ierr);
1853c58f1c22SToby Isaac     for (p = 0; p < dof; ++p) points[off+p] = spoints[p];
1854c58f1c22SToby Isaac     ierr = ISRestoreIndices(is, &spoints);CHKERRQ(ierr);
1855c58f1c22SToby Isaac     ierr = ISDestroy(&is);CHKERRQ(ierr);
1856c58f1c22SToby Isaac   }
1857c58f1c22SToby Isaac   ierr = ISRestoreIndices(vIS, &values);CHKERRQ(ierr);
1858c58f1c22SToby Isaac   ierr = ISDestroy(&vIS);CHKERRQ(ierr);
1859c58f1c22SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF, N, points, PETSC_OWN_POINTER, is);CHKERRQ(ierr);
1860c58f1c22SToby Isaac   PetscFunctionReturn(0);
1861c58f1c22SToby Isaac }
1862c58f1c22SToby Isaac 
186384f0b6dfSMatthew G. Knepley /*@
1864c58f1c22SToby Isaac   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
1865c58f1c22SToby Isaac   the local section and an SF describing the section point overlap.
1866c58f1c22SToby Isaac 
18675b5e7992SMatthew G. Knepley   Collective on sf
18685b5e7992SMatthew G. Knepley 
1869c58f1c22SToby Isaac   Input Parameters:
1870c58f1c22SToby Isaac   + s - The PetscSection for the local field layout
1871c58f1c22SToby Isaac   . sf - The SF describing parallel layout of the section points
1872c58f1c22SToby Isaac   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1873c58f1c22SToby Isaac   . label - The label specifying the points
1874c58f1c22SToby Isaac   - labelValue - The label stratum specifying the points
1875c58f1c22SToby Isaac 
1876c58f1c22SToby Isaac   Output Parameter:
1877c58f1c22SToby Isaac   . gsection - The PetscSection for the global field layout
1878c58f1c22SToby Isaac 
1879c58f1c22SToby Isaac   Note: This gives negative sizes and offsets to points not owned by this process
1880c58f1c22SToby Isaac 
1881c58f1c22SToby Isaac   Level: developer
1882c58f1c22SToby Isaac 
1883c58f1c22SToby Isaac .seealso: PetscSectionCreate()
1884c58f1c22SToby Isaac @*/
1885c58f1c22SToby Isaac PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
1886c58f1c22SToby Isaac {
1887c58f1c22SToby Isaac   PetscInt      *neg = NULL, *tmpOff = NULL;
1888c58f1c22SToby Isaac   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
1889c58f1c22SToby Isaac   PetscErrorCode ierr;
1890c58f1c22SToby Isaac 
1891c58f1c22SToby Isaac   PetscFunctionBegin;
1892d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1893d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1894d67d17b1SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
1895c58f1c22SToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
1896c58f1c22SToby Isaac   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1897c58f1c22SToby Isaac   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
1898c58f1c22SToby Isaac   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
1899c58f1c22SToby Isaac   if (nroots >= 0) {
1900c58f1c22SToby Isaac     if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
1901c58f1c22SToby Isaac     ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr);
1902c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1903c58f1c22SToby Isaac       ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr);
1904c58f1c22SToby Isaac     } else {
1905c58f1c22SToby Isaac       tmpOff = &(*gsection)->atlasDof[-pStart];
1906c58f1c22SToby Isaac     }
1907c58f1c22SToby Isaac   }
1908c58f1c22SToby Isaac   /* Mark ghost points with negative dof */
1909c58f1c22SToby Isaac   for (p = pStart; p < pEnd; ++p) {
1910c58f1c22SToby Isaac     PetscInt value;
1911c58f1c22SToby Isaac 
1912c58f1c22SToby Isaac     ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr);
1913c58f1c22SToby Isaac     if (value != labelValue) continue;
1914c58f1c22SToby Isaac     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1915c58f1c22SToby Isaac     ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr);
1916c58f1c22SToby Isaac     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1917c58f1c22SToby Isaac     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);}
1918c58f1c22SToby Isaac     if (neg) neg[p] = -(dof+1);
1919c58f1c22SToby Isaac   }
1920c58f1c22SToby Isaac   ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr);
1921c58f1c22SToby Isaac   if (nroots >= 0) {
1922ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1923ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1924c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1925c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
1926c58f1c22SToby Isaac     }
1927c58f1c22SToby Isaac   }
1928c58f1c22SToby Isaac   /* Calculate new sizes, get proccess offset, and calculate point offsets */
1929c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1930c58f1c22SToby Isaac     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
1931c58f1c22SToby Isaac     (*gsection)->atlasOff[p] = off;
1932c58f1c22SToby Isaac     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
1933c58f1c22SToby Isaac   }
193455b25c41SPierre Jolivet   ierr       = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRMPI(ierr);
1935c58f1c22SToby Isaac   globalOff -= off;
1936c58f1c22SToby Isaac   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1937c58f1c22SToby Isaac     (*gsection)->atlasOff[p] += globalOff;
1938c58f1c22SToby Isaac     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
1939c58f1c22SToby Isaac   }
1940c58f1c22SToby Isaac   /* Put in negative offsets for ghost points */
1941c58f1c22SToby Isaac   if (nroots >= 0) {
1942ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1943ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff,MPI_REPLACE);CHKERRQ(ierr);
1944c58f1c22SToby Isaac     if (nroots > pEnd-pStart) {
1945c58f1c22SToby Isaac       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
1946c58f1c22SToby Isaac     }
1947c58f1c22SToby Isaac   }
1948c58f1c22SToby Isaac   if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);}
1949c58f1c22SToby Isaac   ierr = PetscFree(neg);CHKERRQ(ierr);
1950c58f1c22SToby Isaac   PetscFunctionReturn(0);
1951c58f1c22SToby Isaac }
1952c58f1c22SToby Isaac 
19535fdea053SToby Isaac typedef struct _n_PetscSectionSym_Label
19545fdea053SToby Isaac {
19555fdea053SToby Isaac   DMLabel           label;
19565fdea053SToby Isaac   PetscCopyMode     *modes;
19575fdea053SToby Isaac   PetscInt          *sizes;
19585fdea053SToby Isaac   const PetscInt    ***perms;
19595fdea053SToby Isaac   const PetscScalar ***rots;
19605fdea053SToby Isaac   PetscInt          (*minMaxOrients)[2];
19615fdea053SToby Isaac   PetscInt          numStrata; /* numStrata is only increasing, functions as a state */
19625fdea053SToby Isaac } PetscSectionSym_Label;
19635fdea053SToby Isaac 
19645fdea053SToby Isaac static PetscErrorCode PetscSectionSymLabelReset(PetscSectionSym sym)
19655fdea053SToby Isaac {
19665fdea053SToby Isaac   PetscInt              i, j;
19675fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
19685fdea053SToby Isaac   PetscErrorCode        ierr;
19695fdea053SToby Isaac 
19705fdea053SToby Isaac   PetscFunctionBegin;
19715fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
19725fdea053SToby Isaac     if (sl->modes[i] == PETSC_OWN_POINTER || sl->modes[i] == PETSC_COPY_VALUES) {
19735fdea053SToby Isaac       for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
19745fdea053SToby Isaac         if (sl->perms[i]) {ierr = PetscFree(sl->perms[i][j]);CHKERRQ(ierr);}
19755fdea053SToby Isaac         if (sl->rots[i]) {ierr = PetscFree(sl->rots[i][j]);CHKERRQ(ierr);}
19765fdea053SToby Isaac       }
19775fdea053SToby Isaac       if (sl->perms[i]) {
19785fdea053SToby Isaac         const PetscInt **perms = &sl->perms[i][sl->minMaxOrients[i][0]];
19795fdea053SToby Isaac 
19805fdea053SToby Isaac         ierr = PetscFree(perms);CHKERRQ(ierr);
19815fdea053SToby Isaac       }
19825fdea053SToby Isaac       if (sl->rots[i]) {
19835fdea053SToby Isaac         const PetscScalar **rots = &sl->rots[i][sl->minMaxOrients[i][0]];
19845fdea053SToby Isaac 
19855fdea053SToby Isaac         ierr = PetscFree(rots);CHKERRQ(ierr);
19865fdea053SToby Isaac       }
19875fdea053SToby Isaac     }
19885fdea053SToby Isaac   }
19895fdea053SToby Isaac   ierr = PetscFree5(sl->modes,sl->sizes,sl->perms,sl->rots,sl->minMaxOrients);CHKERRQ(ierr);
19905fdea053SToby Isaac   ierr = DMLabelDestroy(&sl->label);CHKERRQ(ierr);
19915fdea053SToby Isaac   sl->numStrata = 0;
19925fdea053SToby Isaac   PetscFunctionReturn(0);
19935fdea053SToby Isaac }
19945fdea053SToby Isaac 
19955fdea053SToby Isaac static PetscErrorCode PetscSectionSymDestroy_Label(PetscSectionSym sym)
19965fdea053SToby Isaac {
19975fdea053SToby Isaac   PetscErrorCode ierr;
19985fdea053SToby Isaac 
19995fdea053SToby Isaac   PetscFunctionBegin;
20005fdea053SToby Isaac   ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);
20015fdea053SToby Isaac   ierr = PetscFree(sym->data);CHKERRQ(ierr);
20025fdea053SToby Isaac   PetscFunctionReturn(0);
20035fdea053SToby Isaac }
20045fdea053SToby Isaac 
20055fdea053SToby Isaac static PetscErrorCode PetscSectionSymView_Label(PetscSectionSym sym, PetscViewer viewer)
20065fdea053SToby Isaac {
20075fdea053SToby Isaac   PetscSectionSym_Label *sl = (PetscSectionSym_Label *) sym->data;
20085fdea053SToby Isaac   PetscBool             isAscii;
20095fdea053SToby Isaac   DMLabel               label = sl->label;
2010d67d17b1SMatthew G. Knepley   const char           *name;
20115fdea053SToby Isaac   PetscErrorCode        ierr;
20125fdea053SToby Isaac 
20135fdea053SToby Isaac   PetscFunctionBegin;
20145fdea053SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isAscii);CHKERRQ(ierr);
20155fdea053SToby Isaac   if (isAscii) {
20165fdea053SToby Isaac     PetscInt          i, j, k;
20175fdea053SToby Isaac     PetscViewerFormat format;
20185fdea053SToby Isaac 
20195fdea053SToby Isaac     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
20205fdea053SToby Isaac     if (label) {
20215fdea053SToby Isaac       ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
20225fdea053SToby Isaac       if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
20235fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
20245fdea053SToby Isaac         ierr = DMLabelView(label, viewer);CHKERRQ(ierr);
20255fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20265fdea053SToby Isaac       } else {
2027d67d17b1SMatthew G. Knepley         ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
2028d67d17b1SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"  Label '%s'\n",name);CHKERRQ(ierr);
20295fdea053SToby Isaac       }
20305fdea053SToby Isaac     } else {
20315fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "No label given\n");CHKERRQ(ierr);
20325fdea053SToby Isaac     }
20335fdea053SToby Isaac     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
20345fdea053SToby Isaac     for (i = 0; i <= sl->numStrata; i++) {
20355fdea053SToby Isaac       PetscInt value = i < sl->numStrata ? label->stratumValues[i] : label->defaultValue;
20365fdea053SToby Isaac 
20375fdea053SToby Isaac       if (!(sl->perms[i] || sl->rots[i])) {
20385fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point): no symmetries\n", value, sl->sizes[i]);CHKERRQ(ierr);
20395fdea053SToby Isaac       } else {
20405fdea053SToby Isaac       ierr = PetscViewerASCIIPrintf(viewer, "Symmetry for stratum value %D (%D dofs per point):\n", value, sl->sizes[i]);CHKERRQ(ierr);
20415fdea053SToby Isaac         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
20425fdea053SToby Isaac         ierr = PetscViewerASCIIPrintf(viewer, "Orientation range: [%D, %D)\n", sl->minMaxOrients[i][0], sl->minMaxOrients[i][1]);CHKERRQ(ierr);
20435fdea053SToby Isaac         if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
20445fdea053SToby Isaac           ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
20455fdea053SToby Isaac           for (j = sl->minMaxOrients[i][0]; j < sl->minMaxOrients[i][1]; j++) {
20465fdea053SToby Isaac             if (!((sl->perms[i] && sl->perms[i][j]) || (sl->rots[i] && sl->rots[i][j]))) {
20475fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D: identity\n",j);CHKERRQ(ierr);
20485fdea053SToby Isaac             } else {
20495fdea053SToby Isaac               PetscInt tab;
20505fdea053SToby Isaac 
20515fdea053SToby Isaac               ierr = PetscViewerASCIIPrintf(viewer, "Orientation %D:\n",j);CHKERRQ(ierr);
20525fdea053SToby Isaac               ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
20535fdea053SToby Isaac               ierr = PetscViewerASCIIGetTab(viewer,&tab);CHKERRQ(ierr);
20545fdea053SToby Isaac               if (sl->perms[i] && sl->perms[i][j]) {
20555fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Permutation:");CHKERRQ(ierr);
20565fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
20575fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %D",sl->perms[i][j][k]);CHKERRQ(ierr);}
20585fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
20595fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
20605fdea053SToby Isaac               }
20615fdea053SToby Isaac               if (sl->rots[i] && sl->rots[i][j]) {
20625fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"Rotations:  ");CHKERRQ(ierr);
20635fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,0);CHKERRQ(ierr);
20645fdea053SToby Isaac #if defined(PETSC_USE_COMPLEX)
20655fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f+i*%+f",PetscRealPart(sl->rots[i][j][k]),PetscImaginaryPart(sl->rots[i][j][k]));CHKERRQ(ierr);}
20665fdea053SToby Isaac #else
20675fdea053SToby Isaac                 for (k = 0; k < sl->sizes[i]; k++) {ierr = PetscViewerASCIIPrintf(viewer," %+f",sl->rots[i][j][k]);CHKERRQ(ierr);}
20685fdea053SToby Isaac #endif
20695fdea053SToby Isaac                 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
20705fdea053SToby Isaac                 ierr = PetscViewerASCIISetTab(viewer,tab);CHKERRQ(ierr);
20715fdea053SToby Isaac               }
20725fdea053SToby Isaac               ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20735fdea053SToby Isaac             }
20745fdea053SToby Isaac           }
20755fdea053SToby Isaac           ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20765fdea053SToby Isaac         }
20775fdea053SToby Isaac         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20785fdea053SToby Isaac       }
20795fdea053SToby Isaac     }
20805fdea053SToby Isaac     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
20815fdea053SToby Isaac   }
20825fdea053SToby Isaac   PetscFunctionReturn(0);
20835fdea053SToby Isaac }
20845fdea053SToby Isaac 
20855fdea053SToby Isaac /*@
20865fdea053SToby Isaac   PetscSectionSymLabelSetLabel - set the label whose strata will define the points that receive symmetries
20875fdea053SToby Isaac 
20885fdea053SToby Isaac   Logically collective on sym
20895fdea053SToby Isaac 
20905fdea053SToby Isaac   Input parameters:
20915fdea053SToby Isaac + sym - the section symmetries
20925fdea053SToby Isaac - label - the DMLabel describing the types of points
20935fdea053SToby Isaac 
20945fdea053SToby Isaac   Level: developer:
20955fdea053SToby Isaac 
20965fdea053SToby Isaac .seealso: PetscSectionSymLabelSetStratum(), PetscSectionSymCreateLabel(), PetscSectionGetPointSyms()
20975fdea053SToby Isaac @*/
20985fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetLabel(PetscSectionSym sym, DMLabel label)
20995fdea053SToby Isaac {
21005fdea053SToby Isaac   PetscSectionSym_Label *sl;
21015fdea053SToby Isaac   PetscErrorCode        ierr;
21025fdea053SToby Isaac 
21035fdea053SToby Isaac   PetscFunctionBegin;
21045fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
21055fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
21065fdea053SToby Isaac   if (sl->label && sl->label != label) {ierr = PetscSectionSymLabelReset(sym);CHKERRQ(ierr);}
21075fdea053SToby Isaac   if (label) {
21085fdea053SToby Isaac     sl->label = label;
2109d67d17b1SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr);
21105fdea053SToby Isaac     ierr = DMLabelGetNumValues(label,&sl->numStrata);CHKERRQ(ierr);
21111a834cf9SToby Isaac     ierr = PetscMalloc5(sl->numStrata+1,&sl->modes,sl->numStrata+1,&sl->sizes,sl->numStrata+1,&sl->perms,sl->numStrata+1,&sl->rots,sl->numStrata+1,&sl->minMaxOrients);CHKERRQ(ierr);
21121a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->modes,(sl->numStrata+1)*sizeof(PetscCopyMode));CHKERRQ(ierr);
21131a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->sizes,(sl->numStrata+1)*sizeof(PetscInt));CHKERRQ(ierr);
21141a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->perms,(sl->numStrata+1)*sizeof(const PetscInt **));CHKERRQ(ierr);
21151a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->rots,(sl->numStrata+1)*sizeof(const PetscScalar **));CHKERRQ(ierr);
21161a834cf9SToby Isaac     ierr = PetscMemzero((void *) sl->minMaxOrients,(sl->numStrata+1)*sizeof(PetscInt[2]));CHKERRQ(ierr);
21175fdea053SToby Isaac   }
21185fdea053SToby Isaac   PetscFunctionReturn(0);
21195fdea053SToby Isaac }
21205fdea053SToby Isaac 
21215fdea053SToby Isaac /*@C
21225fdea053SToby Isaac   PetscSectionSymLabelSetStratum - set the symmetries for the orientations of a stratum
21235fdea053SToby Isaac 
21245b5e7992SMatthew G. Knepley   Logically collective on sym
21255fdea053SToby Isaac 
21265fdea053SToby Isaac   InputParameters:
21275b5e7992SMatthew G. Knepley + sym       - the section symmetries
21285fdea053SToby Isaac . stratum   - the stratum value in the label that we are assigning symmetries for
21295fdea053SToby Isaac . size      - the number of dofs for points in the stratum of the label
21305fdea053SToby Isaac . minOrient - the smallest orientation for a point in this stratum
21315fdea053SToby Isaac . maxOrient - one greater than the largest orientation for a ppoint in this stratum (i.e., orientations are in the range [minOrient, maxOrient))
21325fdea053SToby Isaac . mode      - how sym should copy the perms and rots arrays
21335fdea053SToby Isaac . perms     - NULL if there are no permutations, or (maxOrient - minOrient) permutations, one for each orientation.  A NULL permutation is the identity
2134a2b725a8SWilliam 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
21355fdea053SToby Isaac 
21365fdea053SToby Isaac   Level: developer
21375fdea053SToby Isaac 
21385fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetPointSyms(), PetscSectionSymCreateLabel()
21395fdea053SToby Isaac @*/
21405fdea053SToby Isaac PetscErrorCode PetscSectionSymLabelSetStratum(PetscSectionSym sym, PetscInt stratum, PetscInt size, PetscInt minOrient, PetscInt maxOrient, PetscCopyMode mode, const PetscInt **perms, const PetscScalar **rots)
21415fdea053SToby Isaac {
21425fdea053SToby Isaac   PetscSectionSym_Label *sl;
2143d67d17b1SMatthew G. Knepley   const char            *name;
2144d67d17b1SMatthew G. Knepley   PetscInt               i, j, k;
21455fdea053SToby Isaac   PetscErrorCode         ierr;
21465fdea053SToby Isaac 
21475fdea053SToby Isaac   PetscFunctionBegin;
21485fdea053SToby Isaac   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
21495fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
21505fdea053SToby Isaac   if (!sl->label) SETERRQ(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_WRONGSTATE,"No label set yet");
21515fdea053SToby Isaac   for (i = 0; i <= sl->numStrata; i++) {
21525fdea053SToby Isaac     PetscInt value = (i < sl->numStrata) ? sl->label->stratumValues[i] : sl->label->defaultValue;
21535fdea053SToby Isaac 
21545fdea053SToby Isaac     if (stratum == value) break;
21555fdea053SToby Isaac   }
2156d67d17b1SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) sl->label, &name);CHKERRQ(ierr);
2157d67d17b1SMatthew G. Knepley   if (i > sl->numStrata) SETERRQ2(PetscObjectComm((PetscObject)sym),PETSC_ERR_ARG_OUTOFRANGE,"Stratum %D not found in label %s\n",stratum,name);
21585fdea053SToby Isaac   sl->sizes[i] = size;
21595fdea053SToby Isaac   sl->modes[i] = mode;
21605fdea053SToby Isaac   sl->minMaxOrients[i][0] = minOrient;
21615fdea053SToby Isaac   sl->minMaxOrients[i][1] = maxOrient;
21625fdea053SToby Isaac   if (mode == PETSC_COPY_VALUES) {
21635fdea053SToby Isaac     if (perms) {
21645fdea053SToby Isaac       PetscInt    **ownPerms;
21655fdea053SToby Isaac 
21665fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownPerms);CHKERRQ(ierr);
21675fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
21685fdea053SToby Isaac         if (perms[j]) {
21695fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownPerms[j]);CHKERRQ(ierr);
21705fdea053SToby Isaac           for (k = 0; k < size; k++) {ownPerms[j][k] = perms[j][k];}
21715fdea053SToby Isaac         }
21725fdea053SToby Isaac       }
21735fdea053SToby Isaac       sl->perms[i] = (const PetscInt **) &ownPerms[-minOrient];
21745fdea053SToby Isaac     }
21755fdea053SToby Isaac     if (rots) {
21765fdea053SToby Isaac       PetscScalar **ownRots;
21775fdea053SToby Isaac 
21785fdea053SToby Isaac       ierr = PetscCalloc1(maxOrient - minOrient,&ownRots);CHKERRQ(ierr);
21795fdea053SToby Isaac       for (j = 0; j < maxOrient-minOrient; j++) {
21805fdea053SToby Isaac         if (rots[j]) {
21815fdea053SToby Isaac           ierr = PetscMalloc1(size,&ownRots[j]);CHKERRQ(ierr);
21825fdea053SToby Isaac           for (k = 0; k < size; k++) {ownRots[j][k] = rots[j][k];}
21835fdea053SToby Isaac         }
21845fdea053SToby Isaac       }
21855fdea053SToby Isaac       sl->rots[i] = (const PetscScalar **) &ownRots[-minOrient];
21865fdea053SToby Isaac     }
21875fdea053SToby Isaac   } else {
21885fdea053SToby Isaac     sl->perms[i] = perms ? &perms[-minOrient] : NULL;
21895fdea053SToby Isaac     sl->rots[i]  = rots ? &rots[-minOrient] : NULL;
21905fdea053SToby Isaac   }
21915fdea053SToby Isaac   PetscFunctionReturn(0);
21925fdea053SToby Isaac }
21935fdea053SToby Isaac 
21945fdea053SToby Isaac static PetscErrorCode PetscSectionSymGetPoints_Label(PetscSectionSym sym, PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt **perms, const PetscScalar **rots)
21955fdea053SToby Isaac {
21965fdea053SToby Isaac   PetscInt              i, j, numStrata;
21975fdea053SToby Isaac   PetscSectionSym_Label *sl;
21985fdea053SToby Isaac   DMLabel               label;
21995fdea053SToby Isaac   PetscErrorCode        ierr;
22005fdea053SToby Isaac 
22015fdea053SToby Isaac   PetscFunctionBegin;
22025fdea053SToby Isaac   sl = (PetscSectionSym_Label *) sym->data;
22035fdea053SToby Isaac   numStrata = sl->numStrata;
22045fdea053SToby Isaac   label     = sl->label;
22055fdea053SToby Isaac   for (i = 0; i < numPoints; i++) {
22065fdea053SToby Isaac     PetscInt point = points[2*i];
22075fdea053SToby Isaac     PetscInt ornt  = points[2*i+1];
22085fdea053SToby Isaac 
22095fdea053SToby Isaac     for (j = 0; j < numStrata; j++) {
22105fdea053SToby Isaac       if (label->validIS[j]) {
22115fdea053SToby Isaac         PetscInt k;
22125fdea053SToby Isaac 
22135fdea053SToby Isaac         ierr = ISLocate(label->points[j],point,&k);CHKERRQ(ierr);
22145fdea053SToby Isaac         if (k >= 0) break;
22155fdea053SToby Isaac       } else {
22165fdea053SToby Isaac         PetscBool has;
22175fdea053SToby Isaac 
2218b9907514SLisandro Dalcin         ierr = PetscHSetIHas(label->ht[j], point, &has);CHKERRQ(ierr);
22195fdea053SToby Isaac         if (has) break;
22205fdea053SToby Isaac       }
22215fdea053SToby Isaac     }
22225fdea053SToby Isaac     if ((sl->minMaxOrients[j][1] > sl->minMaxOrients[j][0]) && (ornt < sl->minMaxOrients[j][0] || ornt >= sl->minMaxOrients[j][1])) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"point %D orientation %D not in range [%D, %D) for stratum %D",point,ornt,sl->minMaxOrients[j][0],sl->minMaxOrients[j][1],j < numStrata ? label->stratumValues[j] : label->defaultValue);
22235fdea053SToby Isaac     if (perms) {perms[i] = sl->perms[j] ? sl->perms[j][ornt] : NULL;}
22245fdea053SToby Isaac     if (rots) {rots[i]  = sl->rots[j] ? sl->rots[j][ornt] : NULL;}
22255fdea053SToby Isaac   }
22265fdea053SToby Isaac   PetscFunctionReturn(0);
22275fdea053SToby Isaac }
22285fdea053SToby Isaac 
22295fdea053SToby Isaac PetscErrorCode PetscSectionSymCreate_Label(PetscSectionSym sym)
22305fdea053SToby Isaac {
22315fdea053SToby Isaac   PetscSectionSym_Label *sl;
22325fdea053SToby Isaac   PetscErrorCode        ierr;
22335fdea053SToby Isaac 
22345fdea053SToby Isaac   PetscFunctionBegin;
22355fdea053SToby Isaac   ierr = PetscNewLog(sym,&sl);CHKERRQ(ierr);
22365fdea053SToby Isaac   sym->ops->getpoints = PetscSectionSymGetPoints_Label;
22375fdea053SToby Isaac   sym->ops->view      = PetscSectionSymView_Label;
22385fdea053SToby Isaac   sym->ops->destroy   = PetscSectionSymDestroy_Label;
22395fdea053SToby Isaac   sym->data           = (void *) sl;
22405fdea053SToby Isaac   PetscFunctionReturn(0);
22415fdea053SToby Isaac }
22425fdea053SToby Isaac 
22435fdea053SToby Isaac /*@
22445fdea053SToby Isaac   PetscSectionSymCreateLabel - Create a section symmetry that assigns one symmetry to each stratum of a label
22455fdea053SToby Isaac 
22465fdea053SToby Isaac   Collective
22475fdea053SToby Isaac 
22485fdea053SToby Isaac   Input Parameters:
22495fdea053SToby Isaac + comm - the MPI communicator for the new symmetry
22505fdea053SToby Isaac - label - the label defining the strata
22515fdea053SToby Isaac 
22525fdea053SToby Isaac   Output Parameters:
22535fdea053SToby Isaac . sym - the section symmetries
22545fdea053SToby Isaac 
22555fdea053SToby Isaac   Level: developer
22565fdea053SToby Isaac 
22575fdea053SToby Isaac .seealso: PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym(), PetscSectionSymLabelSetStratum(), PetscSectionGetPointSyms()
22585fdea053SToby Isaac @*/
22595fdea053SToby Isaac PetscErrorCode PetscSectionSymCreateLabel(MPI_Comm comm, DMLabel label, PetscSectionSym *sym)
22605fdea053SToby Isaac {
22615fdea053SToby Isaac   PetscErrorCode        ierr;
22625fdea053SToby Isaac 
22635fdea053SToby Isaac   PetscFunctionBegin;
22645fdea053SToby Isaac   ierr = DMInitializePackage();CHKERRQ(ierr);
22655fdea053SToby Isaac   ierr = PetscSectionSymCreate(comm,sym);CHKERRQ(ierr);
22665fdea053SToby Isaac   ierr = PetscSectionSymSetType(*sym,PETSCSECTIONSYMLABEL);CHKERRQ(ierr);
22675fdea053SToby Isaac   ierr = PetscSectionSymLabelSetLabel(*sym,label);CHKERRQ(ierr);
22685fdea053SToby Isaac   PetscFunctionReturn(0);
22695fdea053SToby Isaac }
2270