xref: /petsc/src/vec/is/section/interface/section.c (revision ea844a1adba28e307898a6e94a1f422fd7d2db48)
1*ea844a1aSMatthew Knepley /*
2*ea844a1aSMatthew Knepley    This file contains routines for basic section object implementation.
3*ea844a1aSMatthew Knepley */
4*ea844a1aSMatthew Knepley 
5*ea844a1aSMatthew Knepley #include <petsc/private/sectionimpl.h>   /*I  "petscsection.h"   I*/
6*ea844a1aSMatthew Knepley #include <petscsection.h>
7*ea844a1aSMatthew Knepley #include <petscsf.h>
8*ea844a1aSMatthew Knepley #include <petscviewer.h>
9*ea844a1aSMatthew Knepley 
10*ea844a1aSMatthew Knepley PetscClassId PETSC_SECTION_CLASSID;
11*ea844a1aSMatthew Knepley 
12*ea844a1aSMatthew Knepley /*@
13*ea844a1aSMatthew Knepley   PetscSectionCreate - Allocates PetscSection space and sets the map contents to the default.
14*ea844a1aSMatthew Knepley 
15*ea844a1aSMatthew Knepley   Collective
16*ea844a1aSMatthew Knepley 
17*ea844a1aSMatthew Knepley   Input Parameters:
18*ea844a1aSMatthew Knepley + comm - the MPI communicator
19*ea844a1aSMatthew Knepley - s    - pointer to the section
20*ea844a1aSMatthew Knepley 
21*ea844a1aSMatthew Knepley   Level: beginner
22*ea844a1aSMatthew Knepley 
23*ea844a1aSMatthew Knepley   Notes:
24*ea844a1aSMatthew Knepley   Typical calling sequence
25*ea844a1aSMatthew Knepley $       PetscSectionCreate(MPI_Comm,PetscSection *);
26*ea844a1aSMatthew Knepley $       PetscSectionSetNumFields(PetscSection, numFields);
27*ea844a1aSMatthew Knepley $       PetscSectionSetChart(PetscSection,low,high);
28*ea844a1aSMatthew Knepley $       PetscSectionSetDof(PetscSection,point,numdof);
29*ea844a1aSMatthew Knepley $       PetscSectionSetUp(PetscSection);
30*ea844a1aSMatthew Knepley $       PetscSectionGetOffset(PetscSection,point,PetscInt *);
31*ea844a1aSMatthew Knepley $       PetscSectionDestroy(PetscSection);
32*ea844a1aSMatthew Knepley 
33*ea844a1aSMatthew Knepley   The PetscSection object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
34*ea844a1aSMatthew Knepley   recommended they not be used in user codes unless you really gain something in their use.
35*ea844a1aSMatthew Knepley 
36*ea844a1aSMatthew Knepley .seealso: PetscSection, PetscSectionDestroy()
37*ea844a1aSMatthew Knepley @*/
38*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCreate(MPI_Comm comm, PetscSection *s)
39*ea844a1aSMatthew Knepley {
40*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
41*ea844a1aSMatthew Knepley 
42*ea844a1aSMatthew Knepley   PetscFunctionBegin;
43*ea844a1aSMatthew Knepley   PetscValidPointer(s,2);
44*ea844a1aSMatthew Knepley   ierr = ISInitializePackage();CHKERRQ(ierr);
45*ea844a1aSMatthew Knepley 
46*ea844a1aSMatthew Knepley   ierr = PetscHeaderCreate(*s,PETSC_SECTION_CLASSID,"PetscSection","Section","IS",comm,PetscSectionDestroy,PetscSectionView);CHKERRQ(ierr);
47*ea844a1aSMatthew Knepley 
48*ea844a1aSMatthew Knepley   (*s)->pStart             = -1;
49*ea844a1aSMatthew Knepley   (*s)->pEnd               = -1;
50*ea844a1aSMatthew Knepley   (*s)->perm               = NULL;
51*ea844a1aSMatthew Knepley   (*s)->pointMajor         = PETSC_TRUE;
52*ea844a1aSMatthew Knepley   (*s)->maxDof             = 0;
53*ea844a1aSMatthew Knepley   (*s)->atlasDof           = NULL;
54*ea844a1aSMatthew Knepley   (*s)->atlasOff           = NULL;
55*ea844a1aSMatthew Knepley   (*s)->bc                 = NULL;
56*ea844a1aSMatthew Knepley   (*s)->bcIndices          = NULL;
57*ea844a1aSMatthew Knepley   (*s)->setup              = PETSC_FALSE;
58*ea844a1aSMatthew Knepley   (*s)->numFields          = 0;
59*ea844a1aSMatthew Knepley   (*s)->fieldNames         = NULL;
60*ea844a1aSMatthew Knepley   (*s)->field              = NULL;
61*ea844a1aSMatthew Knepley   (*s)->useFieldOff        = PETSC_FALSE;
62*ea844a1aSMatthew Knepley   (*s)->clObj              = NULL;
63*ea844a1aSMatthew Knepley   (*s)->clSection          = NULL;
64*ea844a1aSMatthew Knepley   (*s)->clPoints           = NULL;
65*ea844a1aSMatthew Knepley   (*s)->clSize             = 0;
66*ea844a1aSMatthew Knepley   (*s)->clPerm             = NULL;
67*ea844a1aSMatthew Knepley   (*s)->clInvPerm          = NULL;
68*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
69*ea844a1aSMatthew Knepley }
70*ea844a1aSMatthew Knepley 
71*ea844a1aSMatthew Knepley /*@
72*ea844a1aSMatthew Knepley   PetscSectionCopy - Creates a shallow (if possible) copy of the PetscSection
73*ea844a1aSMatthew Knepley 
74*ea844a1aSMatthew Knepley   Collective
75*ea844a1aSMatthew Knepley 
76*ea844a1aSMatthew Knepley   Input Parameter:
77*ea844a1aSMatthew Knepley . section - the PetscSection
78*ea844a1aSMatthew Knepley 
79*ea844a1aSMatthew Knepley   Output Parameter:
80*ea844a1aSMatthew Knepley . newSection - the copy
81*ea844a1aSMatthew Knepley 
82*ea844a1aSMatthew Knepley   Level: intermediate
83*ea844a1aSMatthew Knepley 
84*ea844a1aSMatthew Knepley .seealso: PetscSection, PetscSectionCreate(), PetscSectionDestroy()
85*ea844a1aSMatthew Knepley @*/
86*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCopy(PetscSection section, PetscSection newSection)
87*ea844a1aSMatthew Knepley {
88*ea844a1aSMatthew Knepley   PetscSectionSym sym;
89*ea844a1aSMatthew Knepley   IS              perm;
90*ea844a1aSMatthew Knepley   PetscInt        numFields, f, pStart, pEnd, p;
91*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
92*ea844a1aSMatthew Knepley 
93*ea844a1aSMatthew Knepley   PetscFunctionBegin;
94*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
95*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(newSection, PETSC_SECTION_CLASSID, 2);
96*ea844a1aSMatthew Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
97*ea844a1aSMatthew Knepley   if (numFields) {ierr = PetscSectionSetNumFields(newSection, numFields);CHKERRQ(ierr);}
98*ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
99*ea844a1aSMatthew Knepley     const char *name   = NULL;
100*ea844a1aSMatthew Knepley     PetscInt   numComp = 0;
101*ea844a1aSMatthew Knepley 
102*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldName(section, f, &name);CHKERRQ(ierr);
103*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldName(newSection, f, name);CHKERRQ(ierr);
104*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldComponents(section, f, &numComp);CHKERRQ(ierr);
105*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldComponents(newSection, f, numComp);CHKERRQ(ierr);
106*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldSym(section, f, &sym);CHKERRQ(ierr);
107*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldSym(newSection, f, sym);CHKERRQ(ierr);
108*ea844a1aSMatthew Knepley   }
109*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
110*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(newSection, pStart, pEnd);CHKERRQ(ierr);
111*ea844a1aSMatthew Knepley   ierr = PetscSectionGetPermutation(section, &perm);CHKERRQ(ierr);
112*ea844a1aSMatthew Knepley   ierr = PetscSectionSetPermutation(newSection, perm);CHKERRQ(ierr);
113*ea844a1aSMatthew Knepley   ierr = PetscSectionGetSym(section, &sym);CHKERRQ(ierr);
114*ea844a1aSMatthew Knepley   ierr = PetscSectionSetSym(newSection, sym);CHKERRQ(ierr);
115*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
116*ea844a1aSMatthew Knepley     PetscInt dof, cdof, fcdof = 0;
117*ea844a1aSMatthew Knepley 
118*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
119*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(newSection, p, dof);CHKERRQ(ierr);
120*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
121*ea844a1aSMatthew Knepley     if (cdof) {ierr = PetscSectionSetConstraintDof(newSection, p, cdof);CHKERRQ(ierr);}
122*ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
123*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldDof(section, p, f, &dof);CHKERRQ(ierr);
124*ea844a1aSMatthew Knepley       ierr = PetscSectionSetFieldDof(newSection, p, f, dof);CHKERRQ(ierr);
125*ea844a1aSMatthew Knepley       if (cdof) {
126*ea844a1aSMatthew Knepley         ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
127*ea844a1aSMatthew Knepley         if (fcdof) {ierr = PetscSectionSetFieldConstraintDof(newSection, p, f, fcdof);CHKERRQ(ierr);}
128*ea844a1aSMatthew Knepley       }
129*ea844a1aSMatthew Knepley     }
130*ea844a1aSMatthew Knepley   }
131*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUp(newSection);CHKERRQ(ierr);
132*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
133*ea844a1aSMatthew Knepley     PetscInt       off, cdof, fcdof = 0;
134*ea844a1aSMatthew Knepley     const PetscInt *cInd;
135*ea844a1aSMatthew Knepley 
136*ea844a1aSMatthew Knepley     /* Must set offsets in case they do not agree with the prefix sums */
137*ea844a1aSMatthew Knepley     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
138*ea844a1aSMatthew Knepley     ierr = PetscSectionSetOffset(newSection, p, off);CHKERRQ(ierr);
139*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
140*ea844a1aSMatthew Knepley     if (cdof) {
141*ea844a1aSMatthew Knepley       ierr = PetscSectionGetConstraintIndices(section, p, &cInd);CHKERRQ(ierr);
142*ea844a1aSMatthew Knepley       ierr = PetscSectionSetConstraintIndices(newSection, p, cInd);CHKERRQ(ierr);
143*ea844a1aSMatthew Knepley       for (f = 0; f < numFields; ++f) {
144*ea844a1aSMatthew Knepley         ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
145*ea844a1aSMatthew Knepley         if (fcdof) {
146*ea844a1aSMatthew Knepley           ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &cInd);CHKERRQ(ierr);
147*ea844a1aSMatthew Knepley           ierr = PetscSectionSetFieldConstraintIndices(newSection, p, f, cInd);CHKERRQ(ierr);
148*ea844a1aSMatthew Knepley         }
149*ea844a1aSMatthew Knepley       }
150*ea844a1aSMatthew Knepley     }
151*ea844a1aSMatthew Knepley   }
152*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
153*ea844a1aSMatthew Knepley }
154*ea844a1aSMatthew Knepley 
155*ea844a1aSMatthew Knepley /*@
156*ea844a1aSMatthew Knepley   PetscSectionClone - Creates a shallow (if possible) copy of the PetscSection
157*ea844a1aSMatthew Knepley 
158*ea844a1aSMatthew Knepley   Collective
159*ea844a1aSMatthew Knepley 
160*ea844a1aSMatthew Knepley   Input Parameter:
161*ea844a1aSMatthew Knepley . section - the PetscSection
162*ea844a1aSMatthew Knepley 
163*ea844a1aSMatthew Knepley   Output Parameter:
164*ea844a1aSMatthew Knepley . newSection - the copy
165*ea844a1aSMatthew Knepley 
166*ea844a1aSMatthew Knepley   Level: beginner
167*ea844a1aSMatthew Knepley 
168*ea844a1aSMatthew Knepley .seealso: PetscSection, PetscSectionCreate(), PetscSectionDestroy()
169*ea844a1aSMatthew Knepley @*/
170*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionClone(PetscSection section, PetscSection *newSection)
171*ea844a1aSMatthew Knepley {
172*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
173*ea844a1aSMatthew Knepley 
174*ea844a1aSMatthew Knepley   PetscFunctionBegin;
175*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
176*ea844a1aSMatthew Knepley   PetscValidPointer(newSection, 2);
177*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) section), newSection);CHKERRQ(ierr);
178*ea844a1aSMatthew Knepley   ierr = PetscSectionCopy(section, *newSection);CHKERRQ(ierr);
179*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
180*ea844a1aSMatthew Knepley }
181*ea844a1aSMatthew Knepley 
182*ea844a1aSMatthew Knepley /*@
183*ea844a1aSMatthew Knepley   PetscSectionSetFromOptions - sets parameters in a PetscSection from the options database
184*ea844a1aSMatthew Knepley 
185*ea844a1aSMatthew Knepley   Collective on PetscSection
186*ea844a1aSMatthew Knepley 
187*ea844a1aSMatthew Knepley   Input Parameter:
188*ea844a1aSMatthew Knepley . section - the PetscSection
189*ea844a1aSMatthew Knepley 
190*ea844a1aSMatthew Knepley   Options Database:
191*ea844a1aSMatthew Knepley . -petscsection_point_major the dof order
192*ea844a1aSMatthew Knepley 
193*ea844a1aSMatthew Knepley   Level: intermediate
194*ea844a1aSMatthew Knepley 
195*ea844a1aSMatthew Knepley .seealso: PetscSection, PetscSectionCreate(), PetscSectionDestroy()
196*ea844a1aSMatthew Knepley @*/
197*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFromOptions(PetscSection s)
198*ea844a1aSMatthew Knepley {
199*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
200*ea844a1aSMatthew Knepley 
201*ea844a1aSMatthew Knepley   PetscFunctionBegin;
202*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
203*ea844a1aSMatthew Knepley   ierr = PetscObjectOptionsBegin((PetscObject) s);CHKERRQ(ierr);
204*ea844a1aSMatthew Knepley   ierr = PetscOptionsBool("-petscsection_point_major", "The for ordering, either point major or field major", "PetscSectionSetPointMajor", s->pointMajor, &s->pointMajor, NULL);CHKERRQ(ierr);
205*ea844a1aSMatthew Knepley   /* process any options handlers added with PetscObjectAddOptionsHandler() */
206*ea844a1aSMatthew Knepley   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) s);CHKERRQ(ierr);
207*ea844a1aSMatthew Knepley   ierr = PetscOptionsEnd();CHKERRQ(ierr);
208*ea844a1aSMatthew Knepley   ierr = PetscObjectViewFromOptions((PetscObject) s, NULL, "-petscsection_view");CHKERRQ(ierr);
209*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
210*ea844a1aSMatthew Knepley }
211*ea844a1aSMatthew Knepley 
212*ea844a1aSMatthew Knepley /*@
213*ea844a1aSMatthew Knepley   PetscSectionCompare - Compares two sections
214*ea844a1aSMatthew Knepley 
215*ea844a1aSMatthew Knepley   Collective on PetscSection
216*ea844a1aSMatthew Knepley 
217*ea844a1aSMatthew Knepley   Input Parameterss:
218*ea844a1aSMatthew Knepley + s1 - the first PetscSection
219*ea844a1aSMatthew Knepley - s2 - the second PetscSection
220*ea844a1aSMatthew Knepley 
221*ea844a1aSMatthew Knepley   Output Parameter:
222*ea844a1aSMatthew Knepley . congruent - PETSC_TRUE if the two sections are congruent, PETSC_FALSE otherwise
223*ea844a1aSMatthew Knepley 
224*ea844a1aSMatthew Knepley   Level: intermediate
225*ea844a1aSMatthew Knepley 
226*ea844a1aSMatthew Knepley   Notes:
227*ea844a1aSMatthew Knepley   Field names are disregarded.
228*ea844a1aSMatthew Knepley 
229*ea844a1aSMatthew Knepley .seealso: PetscSection, PetscSectionCreate(), PetscSectionCopy(), PetscSectionClone()
230*ea844a1aSMatthew Knepley @*/
231*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCompare(PetscSection s1, PetscSection s2, PetscBool *congruent)
232*ea844a1aSMatthew Knepley {
233*ea844a1aSMatthew Knepley   PetscInt pStart, pEnd, nfields, ncdof, nfcdof, p, f, n1, n2;
234*ea844a1aSMatthew Knepley   const PetscInt *idx1, *idx2;
235*ea844a1aSMatthew Knepley   IS perm1, perm2;
236*ea844a1aSMatthew Knepley   PetscBool flg;
237*ea844a1aSMatthew Knepley   PetscMPIInt mflg;
238*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
239*ea844a1aSMatthew Knepley 
240*ea844a1aSMatthew Knepley   PetscFunctionBegin;
241*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s1, PETSC_SECTION_CLASSID, 1);
242*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s2, PETSC_SECTION_CLASSID, 2);
243*ea844a1aSMatthew Knepley   PetscValidIntPointer(congruent,3);
244*ea844a1aSMatthew Knepley   flg = PETSC_FALSE;
245*ea844a1aSMatthew Knepley 
246*ea844a1aSMatthew Knepley   ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)s1),PetscObjectComm((PetscObject)s2),&mflg);CHKERRQ(ierr);
247*ea844a1aSMatthew Knepley   if (mflg != MPI_CONGRUENT && mflg != MPI_IDENT) {
248*ea844a1aSMatthew Knepley     *congruent = PETSC_FALSE;
249*ea844a1aSMatthew Knepley     PetscFunctionReturn(0);
250*ea844a1aSMatthew Knepley   }
251*ea844a1aSMatthew Knepley 
252*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s1, &pStart, &pEnd);CHKERRQ(ierr);
253*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s2, &n1, &n2);CHKERRQ(ierr);
254*ea844a1aSMatthew Knepley   if (pStart != n1 || pEnd != n2) goto not_congruent;
255*ea844a1aSMatthew Knepley 
256*ea844a1aSMatthew Knepley   ierr = PetscSectionGetPermutation(s1, &perm1);CHKERRQ(ierr);
257*ea844a1aSMatthew Knepley   ierr = PetscSectionGetPermutation(s2, &perm2);CHKERRQ(ierr);
258*ea844a1aSMatthew Knepley   if (perm1 && perm2) {
259*ea844a1aSMatthew Knepley     ierr = ISEqual(perm1, perm2, congruent);CHKERRQ(ierr);
260*ea844a1aSMatthew Knepley     if (!(*congruent)) goto not_congruent;
261*ea844a1aSMatthew Knepley   } else if (perm1 != perm2) goto not_congruent;
262*ea844a1aSMatthew Knepley 
263*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
264*ea844a1aSMatthew Knepley     ierr = PetscSectionGetOffset(s1, p, &n1);CHKERRQ(ierr);
265*ea844a1aSMatthew Knepley     ierr = PetscSectionGetOffset(s2, p, &n2);CHKERRQ(ierr);
266*ea844a1aSMatthew Knepley     if (n1 != n2) goto not_congruent;
267*ea844a1aSMatthew Knepley 
268*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s1, p, &n1);CHKERRQ(ierr);
269*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s2, p, &n2);CHKERRQ(ierr);
270*ea844a1aSMatthew Knepley     if (n1 != n2) goto not_congruent;
271*ea844a1aSMatthew Knepley 
272*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s1, p, &ncdof);CHKERRQ(ierr);
273*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s2, p, &n2);CHKERRQ(ierr);
274*ea844a1aSMatthew Knepley     if (ncdof != n2) goto not_congruent;
275*ea844a1aSMatthew Knepley 
276*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintIndices(s1, p, &idx1);CHKERRQ(ierr);
277*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintIndices(s2, p, &idx2);CHKERRQ(ierr);
278*ea844a1aSMatthew Knepley     ierr = PetscArraycmp(idx1, idx2, ncdof, congruent);CHKERRQ(ierr);
279*ea844a1aSMatthew Knepley     if (!(*congruent)) goto not_congruent;
280*ea844a1aSMatthew Knepley   }
281*ea844a1aSMatthew Knepley 
282*ea844a1aSMatthew Knepley   ierr = PetscSectionGetNumFields(s1, &nfields);CHKERRQ(ierr);
283*ea844a1aSMatthew Knepley   ierr = PetscSectionGetNumFields(s2, &n2);CHKERRQ(ierr);
284*ea844a1aSMatthew Knepley   if (nfields != n2) goto not_congruent;
285*ea844a1aSMatthew Knepley 
286*ea844a1aSMatthew Knepley   for (f = 0; f < nfields; ++f) {
287*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldComponents(s1, f, &n1);CHKERRQ(ierr);
288*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldComponents(s2, f, &n2);CHKERRQ(ierr);
289*ea844a1aSMatthew Knepley     if (n1 != n2) goto not_congruent;
290*ea844a1aSMatthew Knepley 
291*ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
292*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldOffset(s1, p, f, &n1);CHKERRQ(ierr);
293*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldOffset(s2, p, f, &n2);CHKERRQ(ierr);
294*ea844a1aSMatthew Knepley       if (n1 != n2) goto not_congruent;
295*ea844a1aSMatthew Knepley 
296*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldDof(s1, p, f, &n1);CHKERRQ(ierr);
297*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldDof(s2, p, f, &n2);CHKERRQ(ierr);
298*ea844a1aSMatthew Knepley       if (n1 != n2) goto not_congruent;
299*ea844a1aSMatthew Knepley 
300*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintDof(s1, p, f, &nfcdof);CHKERRQ(ierr);
301*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintDof(s2, p, f, &n2);CHKERRQ(ierr);
302*ea844a1aSMatthew Knepley       if (nfcdof != n2) goto not_congruent;
303*ea844a1aSMatthew Knepley 
304*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintIndices(s1, p, f, &idx1);CHKERRQ(ierr);
305*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintIndices(s2, p, f, &idx2);CHKERRQ(ierr);
306*ea844a1aSMatthew Knepley       ierr = PetscArraycmp(idx1, idx2, nfcdof, congruent);CHKERRQ(ierr);
307*ea844a1aSMatthew Knepley       if (!(*congruent)) goto not_congruent;
308*ea844a1aSMatthew Knepley     }
309*ea844a1aSMatthew Knepley   }
310*ea844a1aSMatthew Knepley 
311*ea844a1aSMatthew Knepley   flg = PETSC_TRUE;
312*ea844a1aSMatthew Knepley not_congruent:
313*ea844a1aSMatthew Knepley   ierr = MPIU_Allreduce(&flg,congruent,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)s1));CHKERRQ(ierr);
314*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
315*ea844a1aSMatthew Knepley }
316*ea844a1aSMatthew Knepley 
317*ea844a1aSMatthew Knepley /*@
318*ea844a1aSMatthew Knepley   PetscSectionGetNumFields - Returns the number of fields, or 0 if no fields were defined.
319*ea844a1aSMatthew Knepley 
320*ea844a1aSMatthew Knepley   Not collective
321*ea844a1aSMatthew Knepley 
322*ea844a1aSMatthew Knepley   Input Parameter:
323*ea844a1aSMatthew Knepley . s - the PetscSection
324*ea844a1aSMatthew Knepley 
325*ea844a1aSMatthew Knepley   Output Parameter:
326*ea844a1aSMatthew Knepley . numFields - the number of fields defined, or 0 if none were defined
327*ea844a1aSMatthew Knepley 
328*ea844a1aSMatthew Knepley   Level: intermediate
329*ea844a1aSMatthew Knepley 
330*ea844a1aSMatthew Knepley .seealso: PetscSectionSetNumFields()
331*ea844a1aSMatthew Knepley @*/
332*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetNumFields(PetscSection s, PetscInt *numFields)
333*ea844a1aSMatthew Knepley {
334*ea844a1aSMatthew Knepley   PetscFunctionBegin;
335*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
336*ea844a1aSMatthew Knepley   PetscValidPointer(numFields,2);
337*ea844a1aSMatthew Knepley   *numFields = s->numFields;
338*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
339*ea844a1aSMatthew Knepley }
340*ea844a1aSMatthew Knepley 
341*ea844a1aSMatthew Knepley /*@
342*ea844a1aSMatthew Knepley   PetscSectionSetNumFields - Sets the number of fields.
343*ea844a1aSMatthew Knepley 
344*ea844a1aSMatthew Knepley   Not collective
345*ea844a1aSMatthew Knepley 
346*ea844a1aSMatthew Knepley   Input Parameters:
347*ea844a1aSMatthew Knepley + s - the PetscSection
348*ea844a1aSMatthew Knepley - numFields - the number of fields
349*ea844a1aSMatthew Knepley 
350*ea844a1aSMatthew Knepley   Level: intermediate
351*ea844a1aSMatthew Knepley 
352*ea844a1aSMatthew Knepley .seealso: PetscSectionGetNumFields()
353*ea844a1aSMatthew Knepley @*/
354*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetNumFields(PetscSection s, PetscInt numFields)
355*ea844a1aSMatthew Knepley {
356*ea844a1aSMatthew Knepley   PetscInt       f;
357*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
358*ea844a1aSMatthew Knepley 
359*ea844a1aSMatthew Knepley   PetscFunctionBegin;
360*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
361*ea844a1aSMatthew Knepley   if (numFields <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "The number of fields %D must be positive", numFields);
362*ea844a1aSMatthew Knepley   ierr = PetscSectionReset(s);CHKERRQ(ierr);
363*ea844a1aSMatthew Knepley 
364*ea844a1aSMatthew Knepley   s->numFields = numFields;
365*ea844a1aSMatthew Knepley   ierr = PetscMalloc1(s->numFields, &s->numFieldComponents);CHKERRQ(ierr);
366*ea844a1aSMatthew Knepley   ierr = PetscMalloc1(s->numFields, &s->fieldNames);CHKERRQ(ierr);
367*ea844a1aSMatthew Knepley   ierr = PetscMalloc1(s->numFields, &s->field);CHKERRQ(ierr);
368*ea844a1aSMatthew Knepley   for (f = 0; f < s->numFields; ++f) {
369*ea844a1aSMatthew Knepley     char name[64];
370*ea844a1aSMatthew Knepley 
371*ea844a1aSMatthew Knepley     s->numFieldComponents[f] = 1;
372*ea844a1aSMatthew Knepley 
373*ea844a1aSMatthew Knepley     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), &s->field[f]);CHKERRQ(ierr);
374*ea844a1aSMatthew Knepley     ierr = PetscSNPrintf(name, 64, "Field_%D", f);CHKERRQ(ierr);
375*ea844a1aSMatthew Knepley     ierr = PetscStrallocpy(name, (char **) &s->fieldNames[f]);CHKERRQ(ierr);
376*ea844a1aSMatthew Knepley   }
377*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
378*ea844a1aSMatthew Knepley }
379*ea844a1aSMatthew Knepley 
380*ea844a1aSMatthew Knepley /*@C
381*ea844a1aSMatthew Knepley   PetscSectionGetFieldName - Returns the name of a field in the PetscSection
382*ea844a1aSMatthew Knepley 
383*ea844a1aSMatthew Knepley   Not Collective
384*ea844a1aSMatthew Knepley 
385*ea844a1aSMatthew Knepley   Input Parameters:
386*ea844a1aSMatthew Knepley + s     - the PetscSection
387*ea844a1aSMatthew Knepley - field - the field number
388*ea844a1aSMatthew Knepley 
389*ea844a1aSMatthew Knepley   Output Parameter:
390*ea844a1aSMatthew Knepley . fieldName - the field name
391*ea844a1aSMatthew Knepley 
392*ea844a1aSMatthew Knepley   Level: intermediate
393*ea844a1aSMatthew Knepley 
394*ea844a1aSMatthew Knepley .seealso: PetscSectionSetFieldName()
395*ea844a1aSMatthew Knepley @*/
396*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldName(PetscSection s, PetscInt field, const char *fieldName[])
397*ea844a1aSMatthew Knepley {
398*ea844a1aSMatthew Knepley   PetscFunctionBegin;
399*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
400*ea844a1aSMatthew Knepley   PetscValidPointer(fieldName,3);
401*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
402*ea844a1aSMatthew Knepley   *fieldName = s->fieldNames[field];
403*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
404*ea844a1aSMatthew Knepley }
405*ea844a1aSMatthew Knepley 
406*ea844a1aSMatthew Knepley /*@C
407*ea844a1aSMatthew Knepley   PetscSectionSetFieldName - Sets the name of a field in the PetscSection
408*ea844a1aSMatthew Knepley 
409*ea844a1aSMatthew Knepley   Not Collective
410*ea844a1aSMatthew Knepley 
411*ea844a1aSMatthew Knepley   Input Parameters:
412*ea844a1aSMatthew Knepley + s     - the PetscSection
413*ea844a1aSMatthew Knepley . field - the field number
414*ea844a1aSMatthew Knepley - fieldName - the field name
415*ea844a1aSMatthew Knepley 
416*ea844a1aSMatthew Knepley   Level: intermediate
417*ea844a1aSMatthew Knepley 
418*ea844a1aSMatthew Knepley .seealso: PetscSectionGetFieldName()
419*ea844a1aSMatthew Knepley @*/
420*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFieldName(PetscSection s, PetscInt field, const char fieldName[])
421*ea844a1aSMatthew Knepley {
422*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
423*ea844a1aSMatthew Knepley 
424*ea844a1aSMatthew Knepley   PetscFunctionBegin;
425*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
426*ea844a1aSMatthew Knepley   if (fieldName) PetscValidCharPointer(fieldName,3);
427*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
428*ea844a1aSMatthew Knepley   ierr = PetscFree(s->fieldNames[field]);CHKERRQ(ierr);
429*ea844a1aSMatthew Knepley   ierr = PetscStrallocpy(fieldName, (char**) &s->fieldNames[field]);CHKERRQ(ierr);
430*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
431*ea844a1aSMatthew Knepley }
432*ea844a1aSMatthew Knepley 
433*ea844a1aSMatthew Knepley /*@
434*ea844a1aSMatthew Knepley   PetscSectionGetFieldComponents - Returns the number of field components for the given field.
435*ea844a1aSMatthew Knepley 
436*ea844a1aSMatthew Knepley   Not collective
437*ea844a1aSMatthew Knepley 
438*ea844a1aSMatthew Knepley   Input Parameters:
439*ea844a1aSMatthew Knepley + s - the PetscSection
440*ea844a1aSMatthew Knepley - field - the field number
441*ea844a1aSMatthew Knepley 
442*ea844a1aSMatthew Knepley   Output Parameter:
443*ea844a1aSMatthew Knepley . numComp - the number of field components
444*ea844a1aSMatthew Knepley 
445*ea844a1aSMatthew Knepley   Level: intermediate
446*ea844a1aSMatthew Knepley 
447*ea844a1aSMatthew Knepley .seealso: PetscSectionSetFieldComponents(), PetscSectionGetNumFields()
448*ea844a1aSMatthew Knepley @*/
449*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldComponents(PetscSection s, PetscInt field, PetscInt *numComp)
450*ea844a1aSMatthew Knepley {
451*ea844a1aSMatthew Knepley   PetscFunctionBegin;
452*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
453*ea844a1aSMatthew Knepley   PetscValidPointer(numComp, 3);
454*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
455*ea844a1aSMatthew Knepley   *numComp = s->numFieldComponents[field];
456*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
457*ea844a1aSMatthew Knepley }
458*ea844a1aSMatthew Knepley 
459*ea844a1aSMatthew Knepley /*@
460*ea844a1aSMatthew Knepley   PetscSectionSetFieldComponents - Sets the number of field components for the given field.
461*ea844a1aSMatthew Knepley 
462*ea844a1aSMatthew Knepley   Not collective
463*ea844a1aSMatthew Knepley 
464*ea844a1aSMatthew Knepley   Input Parameters:
465*ea844a1aSMatthew Knepley + s - the PetscSection
466*ea844a1aSMatthew Knepley . field - the field number
467*ea844a1aSMatthew Knepley - numComp - the number of field components
468*ea844a1aSMatthew Knepley 
469*ea844a1aSMatthew Knepley   Level: intermediate
470*ea844a1aSMatthew Knepley 
471*ea844a1aSMatthew Knepley .seealso: PetscSectionGetNumFieldComponents(), PetscSectionGetNumFields()
472*ea844a1aSMatthew Knepley @*/
473*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFieldComponents(PetscSection s, PetscInt field, PetscInt numComp)
474*ea844a1aSMatthew Knepley {
475*ea844a1aSMatthew Knepley   PetscFunctionBegin;
476*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
477*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
478*ea844a1aSMatthew Knepley   s->numFieldComponents[field] = numComp;
479*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
480*ea844a1aSMatthew Knepley }
481*ea844a1aSMatthew Knepley 
482*ea844a1aSMatthew Knepley static PetscErrorCode PetscSectionCheckConstraints_Static(PetscSection s)
483*ea844a1aSMatthew Knepley {
484*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
485*ea844a1aSMatthew Knepley 
486*ea844a1aSMatthew Knepley   PetscFunctionBegin;
487*ea844a1aSMatthew Knepley   if (!s->bc) {
488*ea844a1aSMatthew Knepley     ierr = PetscSectionCreate(PETSC_COMM_SELF, &s->bc);CHKERRQ(ierr);
489*ea844a1aSMatthew Knepley     ierr = PetscSectionSetChart(s->bc, s->pStart, s->pEnd);CHKERRQ(ierr);
490*ea844a1aSMatthew Knepley   }
491*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
492*ea844a1aSMatthew Knepley }
493*ea844a1aSMatthew Knepley 
494*ea844a1aSMatthew Knepley /*@
495*ea844a1aSMatthew Knepley   PetscSectionGetChart - Returns the range [pStart, pEnd) in which points lie.
496*ea844a1aSMatthew Knepley 
497*ea844a1aSMatthew Knepley   Not collective
498*ea844a1aSMatthew Knepley 
499*ea844a1aSMatthew Knepley   Input Parameter:
500*ea844a1aSMatthew Knepley . s - the PetscSection
501*ea844a1aSMatthew Knepley 
502*ea844a1aSMatthew Knepley   Output Parameters:
503*ea844a1aSMatthew Knepley + pStart - the first point
504*ea844a1aSMatthew Knepley - pEnd - one past the last point
505*ea844a1aSMatthew Knepley 
506*ea844a1aSMatthew Knepley   Level: intermediate
507*ea844a1aSMatthew Knepley 
508*ea844a1aSMatthew Knepley .seealso: PetscSectionSetChart(), PetscSectionCreate()
509*ea844a1aSMatthew Knepley @*/
510*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetChart(PetscSection s, PetscInt *pStart, PetscInt *pEnd)
511*ea844a1aSMatthew Knepley {
512*ea844a1aSMatthew Knepley   PetscFunctionBegin;
513*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
514*ea844a1aSMatthew Knepley   if (pStart) *pStart = s->pStart;
515*ea844a1aSMatthew Knepley   if (pEnd)   *pEnd   = s->pEnd;
516*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
517*ea844a1aSMatthew Knepley }
518*ea844a1aSMatthew Knepley 
519*ea844a1aSMatthew Knepley /*@
520*ea844a1aSMatthew Knepley   PetscSectionSetChart - Sets the range [pStart, pEnd) in which points lie.
521*ea844a1aSMatthew Knepley 
522*ea844a1aSMatthew Knepley   Not collective
523*ea844a1aSMatthew Knepley 
524*ea844a1aSMatthew Knepley   Input Parameters:
525*ea844a1aSMatthew Knepley + s - the PetscSection
526*ea844a1aSMatthew Knepley . pStart - the first point
527*ea844a1aSMatthew Knepley - pEnd - one past the last point
528*ea844a1aSMatthew Knepley 
529*ea844a1aSMatthew Knepley   Level: intermediate
530*ea844a1aSMatthew Knepley 
531*ea844a1aSMatthew Knepley .seealso: PetscSectionGetChart(), PetscSectionCreate()
532*ea844a1aSMatthew Knepley @*/
533*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetChart(PetscSection s, PetscInt pStart, PetscInt pEnd)
534*ea844a1aSMatthew Knepley {
535*ea844a1aSMatthew Knepley   PetscInt       f;
536*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
537*ea844a1aSMatthew Knepley 
538*ea844a1aSMatthew Knepley   PetscFunctionBegin;
539*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
540*ea844a1aSMatthew Knepley   /* Cannot Reset() because it destroys field information */
541*ea844a1aSMatthew Knepley   s->setup = PETSC_FALSE;
542*ea844a1aSMatthew Knepley   ierr = PetscSectionDestroy(&s->bc);CHKERRQ(ierr);
543*ea844a1aSMatthew Knepley   ierr = PetscFree(s->bcIndices);CHKERRQ(ierr);
544*ea844a1aSMatthew Knepley   ierr = PetscFree2(s->atlasDof, s->atlasOff);CHKERRQ(ierr);
545*ea844a1aSMatthew Knepley 
546*ea844a1aSMatthew Knepley   s->pStart = pStart;
547*ea844a1aSMatthew Knepley   s->pEnd   = pEnd;
548*ea844a1aSMatthew Knepley   ierr = PetscMalloc2((pEnd - pStart), &s->atlasDof, (pEnd - pStart), &s->atlasOff);CHKERRQ(ierr);
549*ea844a1aSMatthew Knepley   ierr = PetscArrayzero(s->atlasDof, pEnd - pStart);CHKERRQ(ierr);
550*ea844a1aSMatthew Knepley   for (f = 0; f < s->numFields; ++f) {
551*ea844a1aSMatthew Knepley     ierr = PetscSectionSetChart(s->field[f], pStart, pEnd);CHKERRQ(ierr);
552*ea844a1aSMatthew Knepley   }
553*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
554*ea844a1aSMatthew Knepley }
555*ea844a1aSMatthew Knepley 
556*ea844a1aSMatthew Knepley /*@
557*ea844a1aSMatthew Knepley   PetscSectionGetPermutation - Returns the permutation of [0, pEnd-pStart) or NULL
558*ea844a1aSMatthew Knepley 
559*ea844a1aSMatthew Knepley   Not collective
560*ea844a1aSMatthew Knepley 
561*ea844a1aSMatthew Knepley   Input Parameter:
562*ea844a1aSMatthew Knepley . s - the PetscSection
563*ea844a1aSMatthew Knepley 
564*ea844a1aSMatthew Knepley   Output Parameters:
565*ea844a1aSMatthew Knepley . perm - The permutation as an IS
566*ea844a1aSMatthew Knepley 
567*ea844a1aSMatthew Knepley   Level: intermediate
568*ea844a1aSMatthew Knepley 
569*ea844a1aSMatthew Knepley .seealso: PetscSectionSetPermutation(), PetscSectionCreate()
570*ea844a1aSMatthew Knepley @*/
571*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetPermutation(PetscSection s, IS *perm)
572*ea844a1aSMatthew Knepley {
573*ea844a1aSMatthew Knepley   PetscFunctionBegin;
574*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
575*ea844a1aSMatthew Knepley   if (perm) {PetscValidPointer(perm, 2); *perm = s->perm;}
576*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
577*ea844a1aSMatthew Knepley }
578*ea844a1aSMatthew Knepley 
579*ea844a1aSMatthew Knepley /*@
580*ea844a1aSMatthew Knepley   PetscSectionSetPermutation - Sets the permutation for [0, pEnd-pStart)
581*ea844a1aSMatthew Knepley 
582*ea844a1aSMatthew Knepley   Not collective
583*ea844a1aSMatthew Knepley 
584*ea844a1aSMatthew Knepley   Input Parameters:
585*ea844a1aSMatthew Knepley + s - the PetscSection
586*ea844a1aSMatthew Knepley - perm - the permutation of points
587*ea844a1aSMatthew Knepley 
588*ea844a1aSMatthew Knepley   Level: intermediate
589*ea844a1aSMatthew Knepley 
590*ea844a1aSMatthew Knepley .seealso: PetscSectionGetPermutation(), PetscSectionCreate()
591*ea844a1aSMatthew Knepley @*/
592*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetPermutation(PetscSection s, IS perm)
593*ea844a1aSMatthew Knepley {
594*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
595*ea844a1aSMatthew Knepley 
596*ea844a1aSMatthew Knepley   PetscFunctionBegin;
597*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
598*ea844a1aSMatthew Knepley   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
599*ea844a1aSMatthew Knepley   if (s->setup) SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set a permutation after the section is setup");
600*ea844a1aSMatthew Knepley   if (s->perm != perm) {
601*ea844a1aSMatthew Knepley     ierr = ISDestroy(&s->perm);CHKERRQ(ierr);
602*ea844a1aSMatthew Knepley     if (perm) {
603*ea844a1aSMatthew Knepley       s->perm = perm;
604*ea844a1aSMatthew Knepley       ierr = PetscObjectReference((PetscObject) s->perm);CHKERRQ(ierr);
605*ea844a1aSMatthew Knepley     }
606*ea844a1aSMatthew Knepley   }
607*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
608*ea844a1aSMatthew Knepley }
609*ea844a1aSMatthew Knepley 
610*ea844a1aSMatthew Knepley /*@
611*ea844a1aSMatthew Knepley   PetscSectionGetPointMajor - Returns the flag for dof ordering, true if it is point major, otherwise field major
612*ea844a1aSMatthew Knepley 
613*ea844a1aSMatthew Knepley   Not collective
614*ea844a1aSMatthew Knepley 
615*ea844a1aSMatthew Knepley   Input Parameter:
616*ea844a1aSMatthew Knepley . s - the PetscSection
617*ea844a1aSMatthew Knepley 
618*ea844a1aSMatthew Knepley   Output Parameter:
619*ea844a1aSMatthew Knepley . pm - the flag for point major ordering
620*ea844a1aSMatthew Knepley 
621*ea844a1aSMatthew Knepley   Level: intermediate
622*ea844a1aSMatthew Knepley 
623*ea844a1aSMatthew Knepley .seealso: PetscSectionSetPointMajor()
624*ea844a1aSMatthew Knepley @*/
625*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetPointMajor(PetscSection s, PetscBool *pm)
626*ea844a1aSMatthew Knepley {
627*ea844a1aSMatthew Knepley   PetscFunctionBegin;
628*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
629*ea844a1aSMatthew Knepley   PetscValidPointer(pm,2);
630*ea844a1aSMatthew Knepley   *pm = s->pointMajor;
631*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
632*ea844a1aSMatthew Knepley }
633*ea844a1aSMatthew Knepley 
634*ea844a1aSMatthew Knepley /*@
635*ea844a1aSMatthew Knepley   PetscSectionSetPointMajor - Sets the flag for dof ordering, true if it is point major, otherwise field major
636*ea844a1aSMatthew Knepley 
637*ea844a1aSMatthew Knepley   Not collective
638*ea844a1aSMatthew Knepley 
639*ea844a1aSMatthew Knepley   Input Parameters:
640*ea844a1aSMatthew Knepley + s  - the PetscSection
641*ea844a1aSMatthew Knepley - pm - the flag for point major ordering
642*ea844a1aSMatthew Knepley 
643*ea844a1aSMatthew Knepley   Not collective
644*ea844a1aSMatthew Knepley 
645*ea844a1aSMatthew Knepley   Level: intermediate
646*ea844a1aSMatthew Knepley 
647*ea844a1aSMatthew Knepley .seealso: PetscSectionGetPointMajor()
648*ea844a1aSMatthew Knepley @*/
649*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetPointMajor(PetscSection s, PetscBool pm)
650*ea844a1aSMatthew Knepley {
651*ea844a1aSMatthew Knepley   PetscFunctionBegin;
652*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
653*ea844a1aSMatthew Knepley   if (s->setup) SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set the dof ordering after the section is setup");
654*ea844a1aSMatthew Knepley   s->pointMajor = pm;
655*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
656*ea844a1aSMatthew Knepley }
657*ea844a1aSMatthew Knepley 
658*ea844a1aSMatthew Knepley /*@
659*ea844a1aSMatthew Knepley   PetscSectionGetDof - Return the number of degrees of freedom associated with a given point.
660*ea844a1aSMatthew Knepley 
661*ea844a1aSMatthew Knepley   Not collective
662*ea844a1aSMatthew Knepley 
663*ea844a1aSMatthew Knepley   Input Parameters:
664*ea844a1aSMatthew Knepley + s - the PetscSection
665*ea844a1aSMatthew Knepley - point - the point
666*ea844a1aSMatthew Knepley 
667*ea844a1aSMatthew Knepley   Output Parameter:
668*ea844a1aSMatthew Knepley . numDof - the number of dof
669*ea844a1aSMatthew Knepley 
670*ea844a1aSMatthew Knepley   Level: intermediate
671*ea844a1aSMatthew Knepley 
672*ea844a1aSMatthew Knepley .seealso: PetscSectionSetDof(), PetscSectionCreate()
673*ea844a1aSMatthew Knepley @*/
674*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetDof(PetscSection s, PetscInt point, PetscInt *numDof)
675*ea844a1aSMatthew Knepley {
676*ea844a1aSMatthew Knepley   PetscFunctionBegin;
677*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
678*ea844a1aSMatthew Knepley   PetscValidPointer(numDof, 3);
679*ea844a1aSMatthew Knepley #if defined(PETSC_USE_DEBUG)
680*ea844a1aSMatthew Knepley   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %D should be in [%D, %D)", point, s->pStart, s->pEnd);
681*ea844a1aSMatthew Knepley #endif
682*ea844a1aSMatthew Knepley   *numDof = s->atlasDof[point - s->pStart];
683*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
684*ea844a1aSMatthew Knepley }
685*ea844a1aSMatthew Knepley 
686*ea844a1aSMatthew Knepley /*@
687*ea844a1aSMatthew Knepley   PetscSectionSetDof - Sets the number of degrees of freedom associated with a given point.
688*ea844a1aSMatthew Knepley 
689*ea844a1aSMatthew Knepley   Not collective
690*ea844a1aSMatthew Knepley 
691*ea844a1aSMatthew Knepley   Input Parameters:
692*ea844a1aSMatthew Knepley + s - the PetscSection
693*ea844a1aSMatthew Knepley . point - the point
694*ea844a1aSMatthew Knepley - numDof - the number of dof
695*ea844a1aSMatthew Knepley 
696*ea844a1aSMatthew Knepley   Level: intermediate
697*ea844a1aSMatthew Knepley 
698*ea844a1aSMatthew Knepley .seealso: PetscSectionGetDof(), PetscSectionAddDof(), PetscSectionCreate()
699*ea844a1aSMatthew Knepley @*/
700*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof)
701*ea844a1aSMatthew Knepley {
702*ea844a1aSMatthew Knepley   PetscFunctionBegin;
703*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
704*ea844a1aSMatthew Knepley   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %D should be in [%D, %D)", point, s->pStart, s->pEnd);
705*ea844a1aSMatthew Knepley   s->atlasDof[point - s->pStart] = numDof;
706*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
707*ea844a1aSMatthew Knepley }
708*ea844a1aSMatthew Knepley 
709*ea844a1aSMatthew Knepley /*@
710*ea844a1aSMatthew Knepley   PetscSectionAddDof - Adds to the number of degrees of freedom associated with a given point.
711*ea844a1aSMatthew Knepley 
712*ea844a1aSMatthew Knepley   Not collective
713*ea844a1aSMatthew Knepley 
714*ea844a1aSMatthew Knepley   Input Parameters:
715*ea844a1aSMatthew Knepley + s - the PetscSection
716*ea844a1aSMatthew Knepley . point - the point
717*ea844a1aSMatthew Knepley - numDof - the number of additional dof
718*ea844a1aSMatthew Knepley 
719*ea844a1aSMatthew Knepley   Level: intermediate
720*ea844a1aSMatthew Knepley 
721*ea844a1aSMatthew Knepley .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate()
722*ea844a1aSMatthew Knepley @*/
723*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof)
724*ea844a1aSMatthew Knepley {
725*ea844a1aSMatthew Knepley   PetscFunctionBegin;
726*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
727*ea844a1aSMatthew Knepley #if defined(PETSC_USE_DEBUG)
728*ea844a1aSMatthew Knepley   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %D should be in [%D, %D)", point, s->pStart, s->pEnd);
729*ea844a1aSMatthew Knepley #endif
730*ea844a1aSMatthew Knepley   s->atlasDof[point - s->pStart] += numDof;
731*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
732*ea844a1aSMatthew Knepley }
733*ea844a1aSMatthew Knepley 
734*ea844a1aSMatthew Knepley /*@
735*ea844a1aSMatthew Knepley   PetscSectionGetFieldDof - Return the number of degrees of freedom associated with a field on a given point.
736*ea844a1aSMatthew Knepley 
737*ea844a1aSMatthew Knepley   Not collective
738*ea844a1aSMatthew Knepley 
739*ea844a1aSMatthew Knepley   Input Parameters:
740*ea844a1aSMatthew Knepley + s - the PetscSection
741*ea844a1aSMatthew Knepley . point - the point
742*ea844a1aSMatthew Knepley - field - the field
743*ea844a1aSMatthew Knepley 
744*ea844a1aSMatthew Knepley   Output Parameter:
745*ea844a1aSMatthew Knepley . numDof - the number of dof
746*ea844a1aSMatthew Knepley 
747*ea844a1aSMatthew Knepley   Level: intermediate
748*ea844a1aSMatthew Knepley 
749*ea844a1aSMatthew Knepley .seealso: PetscSectionSetFieldDof(), PetscSectionCreate()
750*ea844a1aSMatthew Knepley @*/
751*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
752*ea844a1aSMatthew Knepley {
753*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
754*ea844a1aSMatthew Knepley 
755*ea844a1aSMatthew Knepley   PetscFunctionBegin;
756*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
757*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
758*ea844a1aSMatthew Knepley   ierr = PetscSectionGetDof(s->field[field], point, numDof);CHKERRQ(ierr);
759*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
760*ea844a1aSMatthew Knepley }
761*ea844a1aSMatthew Knepley 
762*ea844a1aSMatthew Knepley /*@
763*ea844a1aSMatthew Knepley   PetscSectionSetFieldDof - Sets the number of degrees of freedom associated with a field on a given point.
764*ea844a1aSMatthew Knepley 
765*ea844a1aSMatthew Knepley   Not collective
766*ea844a1aSMatthew Knepley 
767*ea844a1aSMatthew Knepley   Input Parameters:
768*ea844a1aSMatthew Knepley + s - the PetscSection
769*ea844a1aSMatthew Knepley . point - the point
770*ea844a1aSMatthew Knepley . field - the field
771*ea844a1aSMatthew Knepley - numDof - the number of dof
772*ea844a1aSMatthew Knepley 
773*ea844a1aSMatthew Knepley   Level: intermediate
774*ea844a1aSMatthew Knepley 
775*ea844a1aSMatthew Knepley .seealso: PetscSectionGetFieldDof(), PetscSectionCreate()
776*ea844a1aSMatthew Knepley @*/
777*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
778*ea844a1aSMatthew Knepley {
779*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
780*ea844a1aSMatthew Knepley 
781*ea844a1aSMatthew Knepley   PetscFunctionBegin;
782*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
783*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
784*ea844a1aSMatthew Knepley   ierr = PetscSectionSetDof(s->field[field], point, numDof);CHKERRQ(ierr);
785*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
786*ea844a1aSMatthew Knepley }
787*ea844a1aSMatthew Knepley 
788*ea844a1aSMatthew Knepley /*@
789*ea844a1aSMatthew Knepley   PetscSectionAddFieldDof - Adds a number of degrees of freedom associated with a field on a given point.
790*ea844a1aSMatthew Knepley 
791*ea844a1aSMatthew Knepley   Not collective
792*ea844a1aSMatthew Knepley 
793*ea844a1aSMatthew Knepley   Input Parameters:
794*ea844a1aSMatthew Knepley + s - the PetscSection
795*ea844a1aSMatthew Knepley . point - the point
796*ea844a1aSMatthew Knepley . field - the field
797*ea844a1aSMatthew Knepley - numDof - the number of dof
798*ea844a1aSMatthew Knepley 
799*ea844a1aSMatthew Knepley   Level: intermediate
800*ea844a1aSMatthew Knepley 
801*ea844a1aSMatthew Knepley .seealso: PetscSectionSetFieldDof(), PetscSectionGetFieldDof(), PetscSectionCreate()
802*ea844a1aSMatthew Knepley @*/
803*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionAddFieldDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
804*ea844a1aSMatthew Knepley {
805*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
806*ea844a1aSMatthew Knepley 
807*ea844a1aSMatthew Knepley   PetscFunctionBegin;
808*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
809*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
810*ea844a1aSMatthew Knepley   ierr = PetscSectionAddDof(s->field[field], point, numDof);CHKERRQ(ierr);
811*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
812*ea844a1aSMatthew Knepley }
813*ea844a1aSMatthew Knepley 
814*ea844a1aSMatthew Knepley /*@
815*ea844a1aSMatthew Knepley   PetscSectionGetConstraintDof - Return the number of constrained degrees of freedom associated with a given point.
816*ea844a1aSMatthew Knepley 
817*ea844a1aSMatthew Knepley   Not collective
818*ea844a1aSMatthew Knepley 
819*ea844a1aSMatthew Knepley   Input Parameters:
820*ea844a1aSMatthew Knepley + s - the PetscSection
821*ea844a1aSMatthew Knepley - point - the point
822*ea844a1aSMatthew Knepley 
823*ea844a1aSMatthew Knepley   Output Parameter:
824*ea844a1aSMatthew Knepley . numDof - the number of dof which are fixed by constraints
825*ea844a1aSMatthew Knepley 
826*ea844a1aSMatthew Knepley   Level: intermediate
827*ea844a1aSMatthew Knepley 
828*ea844a1aSMatthew Knepley .seealso: PetscSectionGetDof(), PetscSectionSetConstraintDof(), PetscSectionCreate()
829*ea844a1aSMatthew Knepley @*/
830*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetConstraintDof(PetscSection s, PetscInt point, PetscInt *numDof)
831*ea844a1aSMatthew Knepley {
832*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
833*ea844a1aSMatthew Knepley 
834*ea844a1aSMatthew Knepley   PetscFunctionBegin;
835*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
836*ea844a1aSMatthew Knepley   PetscValidPointer(numDof, 3);
837*ea844a1aSMatthew Knepley   if (s->bc) {
838*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s->bc, point, numDof);CHKERRQ(ierr);
839*ea844a1aSMatthew Knepley   } else *numDof = 0;
840*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
841*ea844a1aSMatthew Knepley }
842*ea844a1aSMatthew Knepley 
843*ea844a1aSMatthew Knepley /*@
844*ea844a1aSMatthew Knepley   PetscSectionSetConstraintDof - Set the number of constrained degrees of freedom associated with a given point.
845*ea844a1aSMatthew Knepley 
846*ea844a1aSMatthew Knepley   Not collective
847*ea844a1aSMatthew Knepley 
848*ea844a1aSMatthew Knepley   Input Parameters:
849*ea844a1aSMatthew Knepley + s - the PetscSection
850*ea844a1aSMatthew Knepley . point - the point
851*ea844a1aSMatthew Knepley - numDof - the number of dof which are fixed by constraints
852*ea844a1aSMatthew Knepley 
853*ea844a1aSMatthew Knepley   Level: intermediate
854*ea844a1aSMatthew Knepley 
855*ea844a1aSMatthew Knepley .seealso: PetscSectionSetDof(), PetscSectionGetConstraintDof(), PetscSectionCreate()
856*ea844a1aSMatthew Knepley @*/
857*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
858*ea844a1aSMatthew Knepley {
859*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
860*ea844a1aSMatthew Knepley 
861*ea844a1aSMatthew Knepley   PetscFunctionBegin;
862*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
863*ea844a1aSMatthew Knepley   if (numDof) {
864*ea844a1aSMatthew Knepley     ierr = PetscSectionCheckConstraints_Static(s);CHKERRQ(ierr);
865*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(s->bc, point, numDof);CHKERRQ(ierr);
866*ea844a1aSMatthew Knepley   }
867*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
868*ea844a1aSMatthew Knepley }
869*ea844a1aSMatthew Knepley 
870*ea844a1aSMatthew Knepley /*@
871*ea844a1aSMatthew Knepley   PetscSectionAddConstraintDof - Increment the number of constrained degrees of freedom associated with a given point.
872*ea844a1aSMatthew Knepley 
873*ea844a1aSMatthew Knepley   Not collective
874*ea844a1aSMatthew Knepley 
875*ea844a1aSMatthew Knepley   Input Parameters:
876*ea844a1aSMatthew Knepley + s - the PetscSection
877*ea844a1aSMatthew Knepley . point - the point
878*ea844a1aSMatthew Knepley - numDof - the number of additional dof which are fixed by constraints
879*ea844a1aSMatthew Knepley 
880*ea844a1aSMatthew Knepley   Level: intermediate
881*ea844a1aSMatthew Knepley 
882*ea844a1aSMatthew Knepley .seealso: PetscSectionAddDof(), PetscSectionGetConstraintDof(), PetscSectionCreate()
883*ea844a1aSMatthew Knepley @*/
884*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionAddConstraintDof(PetscSection s, PetscInt point, PetscInt numDof)
885*ea844a1aSMatthew Knepley {
886*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
887*ea844a1aSMatthew Knepley 
888*ea844a1aSMatthew Knepley   PetscFunctionBegin;
889*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
890*ea844a1aSMatthew Knepley   if (numDof) {
891*ea844a1aSMatthew Knepley     ierr = PetscSectionCheckConstraints_Static(s);CHKERRQ(ierr);
892*ea844a1aSMatthew Knepley     ierr = PetscSectionAddDof(s->bc, point, numDof);CHKERRQ(ierr);
893*ea844a1aSMatthew Knepley   }
894*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
895*ea844a1aSMatthew Knepley }
896*ea844a1aSMatthew Knepley 
897*ea844a1aSMatthew Knepley /*@
898*ea844a1aSMatthew Knepley   PetscSectionGetFieldConstraintDof - Return the number of constrained degrees of freedom associated with a given field on a point.
899*ea844a1aSMatthew Knepley 
900*ea844a1aSMatthew Knepley   Not collective
901*ea844a1aSMatthew Knepley 
902*ea844a1aSMatthew Knepley   Input Parameters:
903*ea844a1aSMatthew Knepley + s - the PetscSection
904*ea844a1aSMatthew Knepley . point - the point
905*ea844a1aSMatthew Knepley - field - the field
906*ea844a1aSMatthew Knepley 
907*ea844a1aSMatthew Knepley   Output Parameter:
908*ea844a1aSMatthew Knepley . numDof - the number of dof which are fixed by constraints
909*ea844a1aSMatthew Knepley 
910*ea844a1aSMatthew Knepley   Level: intermediate
911*ea844a1aSMatthew Knepley 
912*ea844a1aSMatthew Knepley .seealso: PetscSectionGetDof(), PetscSectionSetFieldConstraintDof(), PetscSectionCreate()
913*ea844a1aSMatthew Knepley @*/
914*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt *numDof)
915*ea844a1aSMatthew Knepley {
916*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
917*ea844a1aSMatthew Knepley 
918*ea844a1aSMatthew Knepley   PetscFunctionBegin;
919*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
920*ea844a1aSMatthew Knepley   PetscValidPointer(numDof, 4);
921*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
922*ea844a1aSMatthew Knepley   ierr = PetscSectionGetConstraintDof(s->field[field], point, numDof);CHKERRQ(ierr);
923*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
924*ea844a1aSMatthew Knepley }
925*ea844a1aSMatthew Knepley 
926*ea844a1aSMatthew Knepley /*@
927*ea844a1aSMatthew Knepley   PetscSectionSetFieldConstraintDof - Set the number of constrained degrees of freedom associated with a given field on a point.
928*ea844a1aSMatthew Knepley 
929*ea844a1aSMatthew Knepley   Not collective
930*ea844a1aSMatthew Knepley 
931*ea844a1aSMatthew Knepley   Input Parameters:
932*ea844a1aSMatthew Knepley + s - the PetscSection
933*ea844a1aSMatthew Knepley . point - the point
934*ea844a1aSMatthew Knepley . field - the field
935*ea844a1aSMatthew Knepley - numDof - the number of dof which are fixed by constraints
936*ea844a1aSMatthew Knepley 
937*ea844a1aSMatthew Knepley   Level: intermediate
938*ea844a1aSMatthew Knepley 
939*ea844a1aSMatthew Knepley .seealso: PetscSectionSetDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate()
940*ea844a1aSMatthew Knepley @*/
941*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
942*ea844a1aSMatthew Knepley {
943*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
944*ea844a1aSMatthew Knepley 
945*ea844a1aSMatthew Knepley   PetscFunctionBegin;
946*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
947*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
948*ea844a1aSMatthew Knepley   ierr = PetscSectionSetConstraintDof(s->field[field], point, numDof);CHKERRQ(ierr);
949*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
950*ea844a1aSMatthew Knepley }
951*ea844a1aSMatthew Knepley 
952*ea844a1aSMatthew Knepley /*@
953*ea844a1aSMatthew Knepley   PetscSectionAddFieldConstraintDof - Increment the number of constrained degrees of freedom associated with a given field on a point.
954*ea844a1aSMatthew Knepley 
955*ea844a1aSMatthew Knepley   Not collective
956*ea844a1aSMatthew Knepley 
957*ea844a1aSMatthew Knepley   Input Parameters:
958*ea844a1aSMatthew Knepley + s - the PetscSection
959*ea844a1aSMatthew Knepley . point - the point
960*ea844a1aSMatthew Knepley . field - the field
961*ea844a1aSMatthew Knepley - numDof - the number of additional dof which are fixed by constraints
962*ea844a1aSMatthew Knepley 
963*ea844a1aSMatthew Knepley   Level: intermediate
964*ea844a1aSMatthew Knepley 
965*ea844a1aSMatthew Knepley .seealso: PetscSectionAddDof(), PetscSectionGetFieldConstraintDof(), PetscSectionCreate()
966*ea844a1aSMatthew Knepley @*/
967*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionAddFieldConstraintDof(PetscSection s, PetscInt point, PetscInt field, PetscInt numDof)
968*ea844a1aSMatthew Knepley {
969*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
970*ea844a1aSMatthew Knepley 
971*ea844a1aSMatthew Knepley   PetscFunctionBegin;
972*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
973*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
974*ea844a1aSMatthew Knepley   ierr = PetscSectionAddConstraintDof(s->field[field], point, numDof);CHKERRQ(ierr);
975*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
976*ea844a1aSMatthew Knepley }
977*ea844a1aSMatthew Knepley 
978*ea844a1aSMatthew Knepley /*@
979*ea844a1aSMatthew Knepley   PetscSectionSetUpBC - Setup the subsections describing boundary conditions.
980*ea844a1aSMatthew Knepley 
981*ea844a1aSMatthew Knepley   Not collective
982*ea844a1aSMatthew Knepley 
983*ea844a1aSMatthew Knepley   Input Parameter:
984*ea844a1aSMatthew Knepley . s - the PetscSection
985*ea844a1aSMatthew Knepley 
986*ea844a1aSMatthew Knepley   Level: advanced
987*ea844a1aSMatthew Knepley 
988*ea844a1aSMatthew Knepley .seealso: PetscSectionSetUp(), PetscSectionCreate()
989*ea844a1aSMatthew Knepley @*/
990*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetUpBC(PetscSection s)
991*ea844a1aSMatthew Knepley {
992*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
993*ea844a1aSMatthew Knepley 
994*ea844a1aSMatthew Knepley   PetscFunctionBegin;
995*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
996*ea844a1aSMatthew Knepley   if (s->bc) {
997*ea844a1aSMatthew Knepley     const PetscInt last = (s->bc->pEnd-s->bc->pStart) - 1;
998*ea844a1aSMatthew Knepley 
999*ea844a1aSMatthew Knepley     ierr = PetscSectionSetUp(s->bc);CHKERRQ(ierr);
1000*ea844a1aSMatthew Knepley     ierr = PetscMalloc1(s->bc->atlasOff[last] + s->bc->atlasDof[last], &s->bcIndices);CHKERRQ(ierr);
1001*ea844a1aSMatthew Knepley   }
1002*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1003*ea844a1aSMatthew Knepley }
1004*ea844a1aSMatthew Knepley 
1005*ea844a1aSMatthew Knepley /*@
1006*ea844a1aSMatthew Knepley   PetscSectionSetUp - Calculate offsets based upon the number of degrees of freedom for each point.
1007*ea844a1aSMatthew Knepley 
1008*ea844a1aSMatthew Knepley   Not collective
1009*ea844a1aSMatthew Knepley 
1010*ea844a1aSMatthew Knepley   Input Parameter:
1011*ea844a1aSMatthew Knepley . s - the PetscSection
1012*ea844a1aSMatthew Knepley 
1013*ea844a1aSMatthew Knepley   Level: intermediate
1014*ea844a1aSMatthew Knepley 
1015*ea844a1aSMatthew Knepley .seealso: PetscSectionCreate()
1016*ea844a1aSMatthew Knepley @*/
1017*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetUp(PetscSection s)
1018*ea844a1aSMatthew Knepley {
1019*ea844a1aSMatthew Knepley   const PetscInt *pind   = NULL;
1020*ea844a1aSMatthew Knepley   PetscInt        offset = 0, foff, p, f;
1021*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
1022*ea844a1aSMatthew Knepley 
1023*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1024*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1025*ea844a1aSMatthew Knepley   if (s->setup) PetscFunctionReturn(0);
1026*ea844a1aSMatthew Knepley   s->setup = PETSC_TRUE;
1027*ea844a1aSMatthew Knepley   /* Set offsets and field offsets for all points */
1028*ea844a1aSMatthew Knepley   /*   Assume that all fields have the same chart */
1029*ea844a1aSMatthew Knepley   if (s->perm) {ierr = ISGetIndices(s->perm, &pind);CHKERRQ(ierr);}
1030*ea844a1aSMatthew Knepley   if (s->pointMajor) {
1031*ea844a1aSMatthew Knepley     for (p = 0; p < s->pEnd - s->pStart; ++p) {
1032*ea844a1aSMatthew Knepley       const PetscInt q = pind ? pind[p] : p;
1033*ea844a1aSMatthew Knepley 
1034*ea844a1aSMatthew Knepley       /* Set point offset */
1035*ea844a1aSMatthew Knepley       s->atlasOff[q] = offset;
1036*ea844a1aSMatthew Knepley       offset        += s->atlasDof[q];
1037*ea844a1aSMatthew Knepley       s->maxDof      = PetscMax(s->maxDof, s->atlasDof[q]);
1038*ea844a1aSMatthew Knepley       /* Set field offset */
1039*ea844a1aSMatthew Knepley       for (f = 0, foff = s->atlasOff[q]; f < s->numFields; ++f) {
1040*ea844a1aSMatthew Knepley         PetscSection sf = s->field[f];
1041*ea844a1aSMatthew Knepley 
1042*ea844a1aSMatthew Knepley         sf->atlasOff[q] = foff;
1043*ea844a1aSMatthew Knepley         foff += sf->atlasDof[q];
1044*ea844a1aSMatthew Knepley       }
1045*ea844a1aSMatthew Knepley     }
1046*ea844a1aSMatthew Knepley   } else {
1047*ea844a1aSMatthew Knepley     /* Set field offsets for all points */
1048*ea844a1aSMatthew Knepley     for (f = 0; f < s->numFields; ++f) {
1049*ea844a1aSMatthew Knepley       PetscSection sf = s->field[f];
1050*ea844a1aSMatthew Knepley 
1051*ea844a1aSMatthew Knepley       for (p = 0; p < s->pEnd - s->pStart; ++p) {
1052*ea844a1aSMatthew Knepley         const PetscInt q = pind ? pind[p] : p;
1053*ea844a1aSMatthew Knepley 
1054*ea844a1aSMatthew Knepley         sf->atlasOff[q] = offset;
1055*ea844a1aSMatthew Knepley         offset += sf->atlasDof[q];
1056*ea844a1aSMatthew Knepley       }
1057*ea844a1aSMatthew Knepley     }
1058*ea844a1aSMatthew Knepley     /* Disable point offsets since these are unused */
1059*ea844a1aSMatthew Knepley     for (p = 0; p < s->pEnd - s->pStart; ++p) {
1060*ea844a1aSMatthew Knepley       s->atlasOff[p] = -1;
1061*ea844a1aSMatthew Knepley       s->maxDof      = PetscMax(s->maxDof, s->atlasDof[p]);
1062*ea844a1aSMatthew Knepley     }
1063*ea844a1aSMatthew Knepley   }
1064*ea844a1aSMatthew Knepley   if (s->perm) {ierr = ISRestoreIndices(s->perm, &pind);CHKERRQ(ierr);}
1065*ea844a1aSMatthew Knepley   /* Setup BC sections */
1066*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUpBC(s);CHKERRQ(ierr);
1067*ea844a1aSMatthew Knepley   for (f = 0; f < s->numFields; ++f) {ierr = PetscSectionSetUpBC(s->field[f]);CHKERRQ(ierr);}
1068*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1069*ea844a1aSMatthew Knepley }
1070*ea844a1aSMatthew Knepley 
1071*ea844a1aSMatthew Knepley /*@
1072*ea844a1aSMatthew Knepley   PetscSectionGetMaxDof - Return the maximum number of degrees of freedom on any point in the chart
1073*ea844a1aSMatthew Knepley 
1074*ea844a1aSMatthew Knepley   Not collective
1075*ea844a1aSMatthew Knepley 
1076*ea844a1aSMatthew Knepley   Input Parameters:
1077*ea844a1aSMatthew Knepley . s - the PetscSection
1078*ea844a1aSMatthew Knepley 
1079*ea844a1aSMatthew Knepley   Output Parameter:
1080*ea844a1aSMatthew Knepley . maxDof - the maximum dof
1081*ea844a1aSMatthew Knepley 
1082*ea844a1aSMatthew Knepley   Level: intermediate
1083*ea844a1aSMatthew Knepley 
1084*ea844a1aSMatthew Knepley .seealso: PetscSectionGetDof(), PetscSectionSetDof(), PetscSectionCreate()
1085*ea844a1aSMatthew Knepley @*/
1086*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetMaxDof(PetscSection s, PetscInt *maxDof)
1087*ea844a1aSMatthew Knepley {
1088*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1089*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1090*ea844a1aSMatthew Knepley   PetscValidPointer(maxDof, 2);
1091*ea844a1aSMatthew Knepley   *maxDof = s->maxDof;
1092*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1093*ea844a1aSMatthew Knepley }
1094*ea844a1aSMatthew Knepley 
1095*ea844a1aSMatthew Knepley /*@
1096*ea844a1aSMatthew Knepley   PetscSectionGetStorageSize - Return the size of an array or local Vec capable of holding all the degrees of freedom.
1097*ea844a1aSMatthew Knepley 
1098*ea844a1aSMatthew Knepley   Not collective
1099*ea844a1aSMatthew Knepley 
1100*ea844a1aSMatthew Knepley   Input Parameter:
1101*ea844a1aSMatthew Knepley . s - the PetscSection
1102*ea844a1aSMatthew Knepley 
1103*ea844a1aSMatthew Knepley   Output Parameter:
1104*ea844a1aSMatthew Knepley . size - the size of an array which can hold all the dofs
1105*ea844a1aSMatthew Knepley 
1106*ea844a1aSMatthew Knepley   Level: intermediate
1107*ea844a1aSMatthew Knepley 
1108*ea844a1aSMatthew Knepley .seealso: PetscSectionGetOffset(), PetscSectionGetConstrainedStorageSize(), PetscSectionCreate()
1109*ea844a1aSMatthew Knepley @*/
1110*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size)
1111*ea844a1aSMatthew Knepley {
1112*ea844a1aSMatthew Knepley   PetscInt p, n = 0;
1113*ea844a1aSMatthew Knepley 
1114*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1115*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1116*ea844a1aSMatthew Knepley   PetscValidPointer(size, 2);
1117*ea844a1aSMatthew Knepley   for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0;
1118*ea844a1aSMatthew Knepley   *size = n;
1119*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1120*ea844a1aSMatthew Knepley }
1121*ea844a1aSMatthew Knepley 
1122*ea844a1aSMatthew Knepley /*@
1123*ea844a1aSMatthew Knepley   PetscSectionGetConstrainedStorageSize - Return the size of an array or local Vec capable of holding all unconstrained degrees of freedom.
1124*ea844a1aSMatthew Knepley 
1125*ea844a1aSMatthew Knepley   Not collective
1126*ea844a1aSMatthew Knepley 
1127*ea844a1aSMatthew Knepley   Input Parameters:
1128*ea844a1aSMatthew Knepley + s - the PetscSection
1129*ea844a1aSMatthew Knepley - point - the point
1130*ea844a1aSMatthew Knepley 
1131*ea844a1aSMatthew Knepley   Output Parameter:
1132*ea844a1aSMatthew Knepley . size - the size of an array which can hold all unconstrained dofs
1133*ea844a1aSMatthew Knepley 
1134*ea844a1aSMatthew Knepley   Level: intermediate
1135*ea844a1aSMatthew Knepley 
1136*ea844a1aSMatthew Knepley .seealso: PetscSectionGetStorageSize(), PetscSectionGetOffset(), PetscSectionCreate()
1137*ea844a1aSMatthew Knepley @*/
1138*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size)
1139*ea844a1aSMatthew Knepley {
1140*ea844a1aSMatthew Knepley   PetscInt p, n = 0;
1141*ea844a1aSMatthew Knepley 
1142*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1143*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1144*ea844a1aSMatthew Knepley   PetscValidPointer(size, 2);
1145*ea844a1aSMatthew Knepley   for (p = 0; p < s->pEnd - s->pStart; ++p) {
1146*ea844a1aSMatthew Knepley     const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0;
1147*ea844a1aSMatthew Knepley     n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0;
1148*ea844a1aSMatthew Knepley   }
1149*ea844a1aSMatthew Knepley   *size = n;
1150*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1151*ea844a1aSMatthew Knepley }
1152*ea844a1aSMatthew Knepley 
1153*ea844a1aSMatthew Knepley /*@
1154*ea844a1aSMatthew Knepley   PetscSectionCreateGlobalSection - Create a section describing the global field layout using
1155*ea844a1aSMatthew Knepley   the local section and an SF describing the section point overlap.
1156*ea844a1aSMatthew Knepley 
1157*ea844a1aSMatthew Knepley   Input Parameters:
1158*ea844a1aSMatthew Knepley   + s - The PetscSection for the local field layout
1159*ea844a1aSMatthew Knepley   . sf - The SF describing parallel layout of the section points (leaves are unowned local points)
1160*ea844a1aSMatthew Knepley   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1161*ea844a1aSMatthew Knepley   - localOffsets - If PETSC_TRUE, use local rather than global offsets for the points
1162*ea844a1aSMatthew Knepley 
1163*ea844a1aSMatthew Knepley   Output Parameter:
1164*ea844a1aSMatthew Knepley   . gsection - The PetscSection for the global field layout
1165*ea844a1aSMatthew Knepley 
1166*ea844a1aSMatthew Knepley   Note: This gives negative sizes and offsets to points not owned by this process
1167*ea844a1aSMatthew Knepley 
1168*ea844a1aSMatthew Knepley   Level: intermediate
1169*ea844a1aSMatthew Knepley 
1170*ea844a1aSMatthew Knepley .seealso: PetscSectionCreate()
1171*ea844a1aSMatthew Knepley @*/
1172*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscBool localOffsets, PetscSection *gsection)
1173*ea844a1aSMatthew Knepley {
1174*ea844a1aSMatthew Knepley   PetscSection    gs;
1175*ea844a1aSMatthew Knepley   const PetscInt *pind = NULL;
1176*ea844a1aSMatthew Knepley   PetscInt       *recv = NULL, *neg = NULL;
1177*ea844a1aSMatthew Knepley   PetscInt        pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots, nlocal, maxleaf;
1178*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
1179*ea844a1aSMatthew Knepley 
1180*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1181*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1182*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1183*ea844a1aSMatthew Knepley   PetscValidLogicalCollectiveBool(s, includeConstraints, 3);
1184*ea844a1aSMatthew Knepley   PetscValidLogicalCollectiveBool(s, localOffsets, 4);
1185*ea844a1aSMatthew Knepley   PetscValidPointer(gsection, 5);
1186*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), &gs);CHKERRQ(ierr);
1187*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1188*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(gs, pStart, pEnd);CHKERRQ(ierr);
1189*ea844a1aSMatthew Knepley   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
1190*ea844a1aSMatthew Knepley   nlocal = nroots;              /* The local/leaf space matches global/root space */
1191*ea844a1aSMatthew Knepley   /* Must allocate for all points visible to SF, which may be more than this section */
1192*ea844a1aSMatthew Knepley   if (nroots >= 0) {             /* nroots < 0 means that the graph has not been set, only happens in serial */
1193*ea844a1aSMatthew Knepley     ierr = PetscSFGetLeafRange(sf, NULL, &maxleaf);CHKERRQ(ierr);
1194*ea844a1aSMatthew Knepley     if (nroots < pEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "SF roots %D < pEnd %D", nroots, pEnd);
1195*ea844a1aSMatthew Knepley     if (maxleaf >= nroots) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Max local leaf %D >= nroots %D", maxleaf, nroots);
1196*ea844a1aSMatthew Knepley     ierr = PetscMalloc2(nroots,&neg,nlocal,&recv);CHKERRQ(ierr);
1197*ea844a1aSMatthew Knepley     ierr = PetscArrayzero(neg,nroots);CHKERRQ(ierr);
1198*ea844a1aSMatthew Knepley   }
1199*ea844a1aSMatthew Knepley   /* Mark all local points with negative dof */
1200*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1201*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1202*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(gs, p, dof);CHKERRQ(ierr);
1203*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1204*ea844a1aSMatthew Knepley     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(gs, p, cdof);CHKERRQ(ierr);}
1205*ea844a1aSMatthew Knepley     if (neg) neg[p] = -(dof+1);
1206*ea844a1aSMatthew Knepley   }
1207*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUpBC(gs);CHKERRQ(ierr);
1208*ea844a1aSMatthew Knepley   if (gs->bcIndices) {ierr = PetscArraycpy(gs->bcIndices, s->bcIndices,gs->bc->atlasOff[gs->bc->pEnd-gs->bc->pStart-1] + gs->bc->atlasDof[gs->bc->pEnd-gs->bc->pStart-1]);CHKERRQ(ierr);}
1209*ea844a1aSMatthew Knepley   if (nroots >= 0) {
1210*ea844a1aSMatthew Knepley     ierr = PetscArrayzero(recv,nlocal);CHKERRQ(ierr);
1211*ea844a1aSMatthew Knepley     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, recv);CHKERRQ(ierr);
1212*ea844a1aSMatthew Knepley     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, recv);CHKERRQ(ierr);
1213*ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
1214*ea844a1aSMatthew Knepley       if (recv[p] < 0) {
1215*ea844a1aSMatthew Knepley         gs->atlasDof[p-pStart] = recv[p];
1216*ea844a1aSMatthew Knepley         ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1217*ea844a1aSMatthew Knepley         if (-(recv[p]+1) != dof) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global dof %D for point %D is not the unconstrained %D", -(recv[p]+1), p, dof);
1218*ea844a1aSMatthew Knepley       }
1219*ea844a1aSMatthew Knepley     }
1220*ea844a1aSMatthew Knepley   }
1221*ea844a1aSMatthew Knepley   /* Calculate new sizes, get process offset, and calculate point offsets */
1222*ea844a1aSMatthew Knepley   if (s->perm) {ierr = ISGetIndices(s->perm, &pind);CHKERRQ(ierr);}
1223*ea844a1aSMatthew Knepley   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1224*ea844a1aSMatthew Knepley     const PetscInt q = pind ? pind[p] : p;
1225*ea844a1aSMatthew Knepley 
1226*ea844a1aSMatthew Knepley     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1227*ea844a1aSMatthew Knepley     gs->atlasOff[q] = off;
1228*ea844a1aSMatthew Knepley     off += gs->atlasDof[q] > 0 ? gs->atlasDof[q]-cdof : 0;
1229*ea844a1aSMatthew Knepley   }
1230*ea844a1aSMatthew Knepley   if (!localOffsets) {
1231*ea844a1aSMatthew Knepley     ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr);
1232*ea844a1aSMatthew Knepley     globalOff -= off;
1233*ea844a1aSMatthew Knepley   }
1234*ea844a1aSMatthew Knepley   for (p = pStart, off = 0; p < pEnd; ++p) {
1235*ea844a1aSMatthew Knepley     gs->atlasOff[p-pStart] += globalOff;
1236*ea844a1aSMatthew Knepley     if (neg) neg[p] = -(gs->atlasOff[p-pStart]+1);
1237*ea844a1aSMatthew Knepley   }
1238*ea844a1aSMatthew Knepley   if (s->perm) {ierr = ISRestoreIndices(s->perm, &pind);CHKERRQ(ierr);}
1239*ea844a1aSMatthew Knepley   /* Put in negative offsets for ghost points */
1240*ea844a1aSMatthew Knepley   if (nroots >= 0) {
1241*ea844a1aSMatthew Knepley     ierr = PetscArrayzero(recv,nlocal);CHKERRQ(ierr);
1242*ea844a1aSMatthew Knepley     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, recv);CHKERRQ(ierr);
1243*ea844a1aSMatthew Knepley     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, recv);CHKERRQ(ierr);
1244*ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
1245*ea844a1aSMatthew Knepley       if (recv[p] < 0) gs->atlasOff[p-pStart] = recv[p];
1246*ea844a1aSMatthew Knepley     }
1247*ea844a1aSMatthew Knepley   }
1248*ea844a1aSMatthew Knepley   ierr = PetscFree2(neg,recv);CHKERRQ(ierr);
1249*ea844a1aSMatthew Knepley   ierr = PetscSectionViewFromOptions(gs, NULL, "-global_section_view");CHKERRQ(ierr);
1250*ea844a1aSMatthew Knepley   *gsection = gs;
1251*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1252*ea844a1aSMatthew Knepley }
1253*ea844a1aSMatthew Knepley 
1254*ea844a1aSMatthew Knepley /*@
1255*ea844a1aSMatthew Knepley   PetscSectionCreateGlobalSectionCensored - Create a section describing the global field layout using
1256*ea844a1aSMatthew Knepley   the local section and an SF describing the section point overlap.
1257*ea844a1aSMatthew Knepley 
1258*ea844a1aSMatthew Knepley   Input Parameters:
1259*ea844a1aSMatthew Knepley   + s - The PetscSection for the local field layout
1260*ea844a1aSMatthew Knepley   . sf - The SF describing parallel layout of the section points
1261*ea844a1aSMatthew Knepley   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
1262*ea844a1aSMatthew Knepley   . numExcludes - The number of exclusion ranges
1263*ea844a1aSMatthew Knepley   - excludes - An array [start_0, end_0, start_1, end_1, ...] where there are numExcludes pairs
1264*ea844a1aSMatthew Knepley 
1265*ea844a1aSMatthew Knepley   Output Parameter:
1266*ea844a1aSMatthew Knepley   . gsection - The PetscSection for the global field layout
1267*ea844a1aSMatthew Knepley 
1268*ea844a1aSMatthew Knepley   Note: This gives negative sizes and offsets to points not owned by this process
1269*ea844a1aSMatthew Knepley 
1270*ea844a1aSMatthew Knepley   Level: advanced
1271*ea844a1aSMatthew Knepley 
1272*ea844a1aSMatthew Knepley .seealso: PetscSectionCreate()
1273*ea844a1aSMatthew Knepley @*/
1274*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection)
1275*ea844a1aSMatthew Knepley {
1276*ea844a1aSMatthew Knepley   const PetscInt *pind = NULL;
1277*ea844a1aSMatthew Knepley   PetscInt       *neg  = NULL, *tmpOff = NULL;
1278*ea844a1aSMatthew Knepley   PetscInt        pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots;
1279*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
1280*ea844a1aSMatthew Knepley 
1281*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1282*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1283*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
1284*ea844a1aSMatthew Knepley   PetscValidPointer(gsection, 6);
1285*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
1286*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1287*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
1288*ea844a1aSMatthew Knepley   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
1289*ea844a1aSMatthew Knepley   if (nroots >= 0) {
1290*ea844a1aSMatthew Knepley     if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %D < %D section size", nroots, pEnd-pStart);
1291*ea844a1aSMatthew Knepley     ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr);
1292*ea844a1aSMatthew Knepley     if (nroots > pEnd-pStart) {
1293*ea844a1aSMatthew Knepley       ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr);
1294*ea844a1aSMatthew Knepley     } else {
1295*ea844a1aSMatthew Knepley       tmpOff = &(*gsection)->atlasDof[-pStart];
1296*ea844a1aSMatthew Knepley     }
1297*ea844a1aSMatthew Knepley   }
1298*ea844a1aSMatthew Knepley   /* Mark ghost points with negative dof */
1299*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1300*ea844a1aSMatthew Knepley     for (e = 0; e < numExcludes; ++e) {
1301*ea844a1aSMatthew Knepley       if ((p >= excludes[e*2+0]) && (p < excludes[e*2+1])) {
1302*ea844a1aSMatthew Knepley         ierr = PetscSectionSetDof(*gsection, p, 0);CHKERRQ(ierr);
1303*ea844a1aSMatthew Knepley         break;
1304*ea844a1aSMatthew Knepley       }
1305*ea844a1aSMatthew Knepley     }
1306*ea844a1aSMatthew Knepley     if (e < numExcludes) continue;
1307*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1308*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr);
1309*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1310*ea844a1aSMatthew Knepley     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);}
1311*ea844a1aSMatthew Knepley     if (neg) neg[p] = -(dof+1);
1312*ea844a1aSMatthew Knepley   }
1313*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr);
1314*ea844a1aSMatthew Knepley   if (nroots >= 0) {
1315*ea844a1aSMatthew Knepley     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1316*ea844a1aSMatthew Knepley     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1317*ea844a1aSMatthew Knepley     if (nroots > pEnd - pStart) {
1318*ea844a1aSMatthew Knepley       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
1319*ea844a1aSMatthew Knepley     }
1320*ea844a1aSMatthew Knepley   }
1321*ea844a1aSMatthew Knepley   /* Calculate new sizes, get proccess offset, and calculate point offsets */
1322*ea844a1aSMatthew Knepley   if (s->perm) {ierr = ISGetIndices(s->perm, &pind);CHKERRQ(ierr);}
1323*ea844a1aSMatthew Knepley   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1324*ea844a1aSMatthew Knepley     const PetscInt q = pind ? pind[p] : p;
1325*ea844a1aSMatthew Knepley 
1326*ea844a1aSMatthew Knepley     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
1327*ea844a1aSMatthew Knepley     (*gsection)->atlasOff[q] = off;
1328*ea844a1aSMatthew Knepley     off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0;
1329*ea844a1aSMatthew Knepley   }
1330*ea844a1aSMatthew Knepley   ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr);
1331*ea844a1aSMatthew Knepley   globalOff -= off;
1332*ea844a1aSMatthew Knepley   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
1333*ea844a1aSMatthew Knepley     (*gsection)->atlasOff[p] += globalOff;
1334*ea844a1aSMatthew Knepley     if (neg) neg[p+pStart] = -((*gsection)->atlasOff[p]+1);
1335*ea844a1aSMatthew Knepley   }
1336*ea844a1aSMatthew Knepley   if (s->perm) {ierr = ISRestoreIndices(s->perm, &pind);CHKERRQ(ierr);}
1337*ea844a1aSMatthew Knepley   /* Put in negative offsets for ghost points */
1338*ea844a1aSMatthew Knepley   if (nroots >= 0) {
1339*ea844a1aSMatthew Knepley     if (nroots == pEnd-pStart) tmpOff = &(*gsection)->atlasOff[-pStart];
1340*ea844a1aSMatthew Knepley     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1341*ea844a1aSMatthew Knepley     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
1342*ea844a1aSMatthew Knepley     if (nroots > pEnd - pStart) {
1343*ea844a1aSMatthew Knepley       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
1344*ea844a1aSMatthew Knepley     }
1345*ea844a1aSMatthew Knepley   }
1346*ea844a1aSMatthew Knepley   if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);}
1347*ea844a1aSMatthew Knepley   ierr = PetscFree(neg);CHKERRQ(ierr);
1348*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1349*ea844a1aSMatthew Knepley }
1350*ea844a1aSMatthew Knepley 
1351*ea844a1aSMatthew Knepley /*@
1352*ea844a1aSMatthew Knepley   PetscSectionGetPointLayout - Get the PetscLayout associated with the section points
1353*ea844a1aSMatthew Knepley 
1354*ea844a1aSMatthew Knepley   Collective on comm
1355*ea844a1aSMatthew Knepley 
1356*ea844a1aSMatthew Knepley   Input Parameters:
1357*ea844a1aSMatthew Knepley + comm - The MPI_Comm
1358*ea844a1aSMatthew Knepley - s    - The PetscSection
1359*ea844a1aSMatthew Knepley 
1360*ea844a1aSMatthew Knepley   Output Parameter:
1361*ea844a1aSMatthew Knepley . layout - The point layout for the section
1362*ea844a1aSMatthew Knepley 
1363*ea844a1aSMatthew Knepley   Note: This is usually caleld for the default global section.
1364*ea844a1aSMatthew Knepley 
1365*ea844a1aSMatthew Knepley   Level: advanced
1366*ea844a1aSMatthew Knepley 
1367*ea844a1aSMatthew Knepley .seealso: PetscSectionGetValueLayout(), PetscSectionCreate()
1368*ea844a1aSMatthew Knepley @*/
1369*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetPointLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1370*ea844a1aSMatthew Knepley {
1371*ea844a1aSMatthew Knepley   PetscInt       pStart, pEnd, p, localSize = 0;
1372*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1373*ea844a1aSMatthew Knepley 
1374*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1375*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1376*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1377*ea844a1aSMatthew Knepley     PetscInt dof;
1378*ea844a1aSMatthew Knepley 
1379*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1380*ea844a1aSMatthew Knepley     if (dof > 0) ++localSize;
1381*ea844a1aSMatthew Knepley   }
1382*ea844a1aSMatthew Knepley   ierr = PetscLayoutCreate(comm, layout);CHKERRQ(ierr);
1383*ea844a1aSMatthew Knepley   ierr = PetscLayoutSetLocalSize(*layout, localSize);CHKERRQ(ierr);
1384*ea844a1aSMatthew Knepley   ierr = PetscLayoutSetBlockSize(*layout, 1);CHKERRQ(ierr);
1385*ea844a1aSMatthew Knepley   ierr = PetscLayoutSetUp(*layout);CHKERRQ(ierr);
1386*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1387*ea844a1aSMatthew Knepley }
1388*ea844a1aSMatthew Knepley 
1389*ea844a1aSMatthew Knepley /*@
1390*ea844a1aSMatthew Knepley   PetscSectionGetValueLayout - Get the PetscLayout associated with the section dofs.
1391*ea844a1aSMatthew Knepley 
1392*ea844a1aSMatthew Knepley   Collective on comm
1393*ea844a1aSMatthew Knepley 
1394*ea844a1aSMatthew Knepley   Input Parameters:
1395*ea844a1aSMatthew Knepley + comm - The MPI_Comm
1396*ea844a1aSMatthew Knepley - s    - The PetscSection
1397*ea844a1aSMatthew Knepley 
1398*ea844a1aSMatthew Knepley   Output Parameter:
1399*ea844a1aSMatthew Knepley . layout - The dof layout for the section
1400*ea844a1aSMatthew Knepley 
1401*ea844a1aSMatthew Knepley   Note: This is usually called for the default global section.
1402*ea844a1aSMatthew Knepley 
1403*ea844a1aSMatthew Knepley   Level: advanced
1404*ea844a1aSMatthew Knepley 
1405*ea844a1aSMatthew Knepley .seealso: PetscSectionGetPointLayout(), PetscSectionCreate()
1406*ea844a1aSMatthew Knepley @*/
1407*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetValueLayout(MPI_Comm comm, PetscSection s, PetscLayout *layout)
1408*ea844a1aSMatthew Knepley {
1409*ea844a1aSMatthew Knepley   PetscInt       pStart, pEnd, p, localSize = 0;
1410*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1411*ea844a1aSMatthew Knepley 
1412*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1413*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2);
1414*ea844a1aSMatthew Knepley   PetscValidPointer(layout, 3);
1415*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1416*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1417*ea844a1aSMatthew Knepley     PetscInt dof,cdof;
1418*ea844a1aSMatthew Knepley 
1419*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1420*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1421*ea844a1aSMatthew Knepley     if (dof-cdof > 0) localSize += dof-cdof;
1422*ea844a1aSMatthew Knepley   }
1423*ea844a1aSMatthew Knepley   ierr = PetscLayoutCreate(comm, layout);CHKERRQ(ierr);
1424*ea844a1aSMatthew Knepley   ierr = PetscLayoutSetLocalSize(*layout, localSize);CHKERRQ(ierr);
1425*ea844a1aSMatthew Knepley   ierr = PetscLayoutSetBlockSize(*layout, 1);CHKERRQ(ierr);
1426*ea844a1aSMatthew Knepley   ierr = PetscLayoutSetUp(*layout);CHKERRQ(ierr);
1427*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1428*ea844a1aSMatthew Knepley }
1429*ea844a1aSMatthew Knepley 
1430*ea844a1aSMatthew Knepley /*@
1431*ea844a1aSMatthew Knepley   PetscSectionGetOffset - Return the offset into an array or local Vec for the dof associated with the given point.
1432*ea844a1aSMatthew Knepley 
1433*ea844a1aSMatthew Knepley   Not collective
1434*ea844a1aSMatthew Knepley 
1435*ea844a1aSMatthew Knepley   Input Parameters:
1436*ea844a1aSMatthew Knepley + s - the PetscSection
1437*ea844a1aSMatthew Knepley - point - the point
1438*ea844a1aSMatthew Knepley 
1439*ea844a1aSMatthew Knepley   Output Parameter:
1440*ea844a1aSMatthew Knepley . offset - the offset
1441*ea844a1aSMatthew Knepley 
1442*ea844a1aSMatthew Knepley   Level: intermediate
1443*ea844a1aSMatthew Knepley 
1444*ea844a1aSMatthew Knepley .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate()
1445*ea844a1aSMatthew Knepley @*/
1446*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetOffset(PetscSection s, PetscInt point, PetscInt *offset)
1447*ea844a1aSMatthew Knepley {
1448*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1449*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1450*ea844a1aSMatthew Knepley   PetscValidPointer(offset, 3);
1451*ea844a1aSMatthew Knepley #if defined(PETSC_USE_DEBUG)
1452*ea844a1aSMatthew Knepley   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %D should be in [%D, %D)", point, s->pStart, s->pEnd);
1453*ea844a1aSMatthew Knepley #endif
1454*ea844a1aSMatthew Knepley   *offset = s->atlasOff[point - s->pStart];
1455*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1456*ea844a1aSMatthew Knepley }
1457*ea844a1aSMatthew Knepley 
1458*ea844a1aSMatthew Knepley /*@
1459*ea844a1aSMatthew Knepley   PetscSectionSetOffset - Set the offset into an array or local Vec for the dof associated with the given point.
1460*ea844a1aSMatthew Knepley 
1461*ea844a1aSMatthew Knepley   Not collective
1462*ea844a1aSMatthew Knepley 
1463*ea844a1aSMatthew Knepley   Input Parameters:
1464*ea844a1aSMatthew Knepley + s - the PetscSection
1465*ea844a1aSMatthew Knepley . point - the point
1466*ea844a1aSMatthew Knepley - offset - the offset
1467*ea844a1aSMatthew Knepley 
1468*ea844a1aSMatthew Knepley   Note: The user usually does not call this function, but uses PetscSectionSetUp()
1469*ea844a1aSMatthew Knepley 
1470*ea844a1aSMatthew Knepley   Level: intermediate
1471*ea844a1aSMatthew Knepley 
1472*ea844a1aSMatthew Knepley .seealso: PetscSectionGetFieldOffset(), PetscSectionCreate(), PetscSectionSetUp()
1473*ea844a1aSMatthew Knepley @*/
1474*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset)
1475*ea844a1aSMatthew Knepley {
1476*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1477*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1478*ea844a1aSMatthew Knepley   if ((point < s->pStart) || (point >= s->pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %D should be in [%D, %D)", point, s->pStart, s->pEnd);
1479*ea844a1aSMatthew Knepley   s->atlasOff[point - s->pStart] = offset;
1480*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1481*ea844a1aSMatthew Knepley }
1482*ea844a1aSMatthew Knepley 
1483*ea844a1aSMatthew Knepley /*@
1484*ea844a1aSMatthew Knepley   PetscSectionGetFieldOffset - Return the offset into an array or local Vec for the dof associated with the given point.
1485*ea844a1aSMatthew Knepley 
1486*ea844a1aSMatthew Knepley   Not collective
1487*ea844a1aSMatthew Knepley 
1488*ea844a1aSMatthew Knepley   Input Parameters:
1489*ea844a1aSMatthew Knepley + s - the PetscSection
1490*ea844a1aSMatthew Knepley . point - the point
1491*ea844a1aSMatthew Knepley - field - the field
1492*ea844a1aSMatthew Knepley 
1493*ea844a1aSMatthew Knepley   Output Parameter:
1494*ea844a1aSMatthew Knepley . offset - the offset
1495*ea844a1aSMatthew Knepley 
1496*ea844a1aSMatthew Knepley   Level: intermediate
1497*ea844a1aSMatthew Knepley 
1498*ea844a1aSMatthew Knepley .seealso: PetscSectionGetOffset(), PetscSectionCreate()
1499*ea844a1aSMatthew Knepley @*/
1500*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1501*ea844a1aSMatthew Knepley {
1502*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1503*ea844a1aSMatthew Knepley 
1504*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1505*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1506*ea844a1aSMatthew Knepley   PetscValidPointer(offset, 4);
1507*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
1508*ea844a1aSMatthew Knepley   ierr = PetscSectionGetOffset(s->field[field], point, offset);CHKERRQ(ierr);
1509*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1510*ea844a1aSMatthew Knepley }
1511*ea844a1aSMatthew Knepley 
1512*ea844a1aSMatthew Knepley /*@
1513*ea844a1aSMatthew Knepley   PetscSectionSetFieldOffset - Set the offset into an array or local Vec for the dof associated with the given point.
1514*ea844a1aSMatthew Knepley 
1515*ea844a1aSMatthew Knepley   Not collective
1516*ea844a1aSMatthew Knepley 
1517*ea844a1aSMatthew Knepley   Input Parameters:
1518*ea844a1aSMatthew Knepley + s - the PetscSection
1519*ea844a1aSMatthew Knepley . point - the point
1520*ea844a1aSMatthew Knepley . field - the field
1521*ea844a1aSMatthew Knepley - offset - the offset
1522*ea844a1aSMatthew Knepley 
1523*ea844a1aSMatthew Knepley   Note: The user usually does not call this function, but uses PetscSectionSetUp()
1524*ea844a1aSMatthew Knepley 
1525*ea844a1aSMatthew Knepley   Level: intermediate
1526*ea844a1aSMatthew Knepley 
1527*ea844a1aSMatthew Knepley .seealso: PetscSectionGetOffset(), PetscSectionCreate(), PetscSectionSetUp()
1528*ea844a1aSMatthew Knepley @*/
1529*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFieldOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt offset)
1530*ea844a1aSMatthew Knepley {
1531*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1532*ea844a1aSMatthew Knepley 
1533*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1534*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1535*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
1536*ea844a1aSMatthew Knepley   ierr = PetscSectionSetOffset(s->field[field], point, offset);CHKERRQ(ierr);
1537*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1538*ea844a1aSMatthew Knepley }
1539*ea844a1aSMatthew Knepley 
1540*ea844a1aSMatthew Knepley /*@
1541*ea844a1aSMatthew Knepley   PetscSectionGetFieldPointOffset - Return the offset on the given point for the dof associated with the given point.
1542*ea844a1aSMatthew Knepley 
1543*ea844a1aSMatthew Knepley   Not collective
1544*ea844a1aSMatthew Knepley 
1545*ea844a1aSMatthew Knepley   Input Parameters:
1546*ea844a1aSMatthew Knepley + s - the PetscSection
1547*ea844a1aSMatthew Knepley . point - the point
1548*ea844a1aSMatthew Knepley - field - the field
1549*ea844a1aSMatthew Knepley 
1550*ea844a1aSMatthew Knepley   Output Parameter:
1551*ea844a1aSMatthew Knepley . offset - the offset
1552*ea844a1aSMatthew Knepley 
1553*ea844a1aSMatthew Knepley   Note: This gives the offset on a point of the field, ignoring constraints, meaning starting at the first dof for
1554*ea844a1aSMatthew Knepley         this point, what number is the first dof with this field.
1555*ea844a1aSMatthew Knepley 
1556*ea844a1aSMatthew Knepley   Level: advanced
1557*ea844a1aSMatthew Knepley 
1558*ea844a1aSMatthew Knepley .seealso: PetscSectionGetOffset(), PetscSectionCreate()
1559*ea844a1aSMatthew Knepley @*/
1560*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldPointOffset(PetscSection s, PetscInt point, PetscInt field, PetscInt *offset)
1561*ea844a1aSMatthew Knepley {
1562*ea844a1aSMatthew Knepley   PetscInt       off, foff;
1563*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1564*ea844a1aSMatthew Knepley 
1565*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1566*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1567*ea844a1aSMatthew Knepley   PetscValidPointer(offset, 4);
1568*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
1569*ea844a1aSMatthew Knepley   ierr = PetscSectionGetOffset(s, point, &off);CHKERRQ(ierr);
1570*ea844a1aSMatthew Knepley   ierr = PetscSectionGetOffset(s->field[field], point, &foff);CHKERRQ(ierr);
1571*ea844a1aSMatthew Knepley   *offset = foff - off;
1572*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1573*ea844a1aSMatthew Knepley }
1574*ea844a1aSMatthew Knepley 
1575*ea844a1aSMatthew Knepley /*@
1576*ea844a1aSMatthew Knepley   PetscSectionGetOffsetRange - Return the full range of offsets [start, end)
1577*ea844a1aSMatthew Knepley 
1578*ea844a1aSMatthew Knepley   Not collective
1579*ea844a1aSMatthew Knepley 
1580*ea844a1aSMatthew Knepley   Input Parameter:
1581*ea844a1aSMatthew Knepley . s - the PetscSection
1582*ea844a1aSMatthew Knepley 
1583*ea844a1aSMatthew Knepley   Output Parameters:
1584*ea844a1aSMatthew Knepley + start - the minimum offset
1585*ea844a1aSMatthew Knepley - end   - one more than the maximum offset
1586*ea844a1aSMatthew Knepley 
1587*ea844a1aSMatthew Knepley   Level: intermediate
1588*ea844a1aSMatthew Knepley 
1589*ea844a1aSMatthew Knepley .seealso: PetscSectionGetOffset(), PetscSectionCreate()
1590*ea844a1aSMatthew Knepley @*/
1591*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetOffsetRange(PetscSection s, PetscInt *start, PetscInt *end)
1592*ea844a1aSMatthew Knepley {
1593*ea844a1aSMatthew Knepley   PetscInt       os = 0, oe = 0, pStart, pEnd, p;
1594*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1595*ea844a1aSMatthew Knepley 
1596*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1597*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1598*ea844a1aSMatthew Knepley   if (s->atlasOff) {os = s->atlasOff[0]; oe = s->atlasOff[0];}
1599*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1600*ea844a1aSMatthew Knepley   for (p = 0; p < pEnd-pStart; ++p) {
1601*ea844a1aSMatthew Knepley     PetscInt dof = s->atlasDof[p], off = s->atlasOff[p];
1602*ea844a1aSMatthew Knepley 
1603*ea844a1aSMatthew Knepley     if (off >= 0) {
1604*ea844a1aSMatthew Knepley       os = PetscMin(os, off);
1605*ea844a1aSMatthew Knepley       oe = PetscMax(oe, off+dof);
1606*ea844a1aSMatthew Knepley     }
1607*ea844a1aSMatthew Knepley   }
1608*ea844a1aSMatthew Knepley   if (start) *start = os;
1609*ea844a1aSMatthew Knepley   if (end)   *end   = oe;
1610*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1611*ea844a1aSMatthew Knepley }
1612*ea844a1aSMatthew Knepley 
1613*ea844a1aSMatthew Knepley /*@
1614*ea844a1aSMatthew Knepley   PetscSectionCreateSubsection - Create a new, smaller section composed of only the selected fields
1615*ea844a1aSMatthew Knepley 
1616*ea844a1aSMatthew Knepley   Collective on s
1617*ea844a1aSMatthew Knepley 
1618*ea844a1aSMatthew Knepley   Input Parameter:
1619*ea844a1aSMatthew Knepley + s      - the PetscSection
1620*ea844a1aSMatthew Knepley . len    - the number of subfields
1621*ea844a1aSMatthew Knepley - fields - the subfield numbers
1622*ea844a1aSMatthew Knepley 
1623*ea844a1aSMatthew Knepley   Output Parameter:
1624*ea844a1aSMatthew Knepley . subs   - the subsection
1625*ea844a1aSMatthew Knepley 
1626*ea844a1aSMatthew Knepley   Note: The section offsets now refer to a new, smaller vector.
1627*ea844a1aSMatthew Knepley 
1628*ea844a1aSMatthew Knepley   Level: advanced
1629*ea844a1aSMatthew Knepley 
1630*ea844a1aSMatthew Knepley .seealso: PetscSectionCreateSupersection(), PetscSectionCreate()
1631*ea844a1aSMatthew Knepley @*/
1632*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCreateSubsection(PetscSection s, PetscInt len, const PetscInt fields[], PetscSection *subs)
1633*ea844a1aSMatthew Knepley {
1634*ea844a1aSMatthew Knepley   PetscInt       nF, f, pStart, pEnd, p, maxCdof = 0;
1635*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1636*ea844a1aSMatthew Knepley 
1637*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1638*ea844a1aSMatthew Knepley   if (!len) PetscFunctionReturn(0);
1639*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1640*ea844a1aSMatthew Knepley   PetscValidPointer(fields, 3);
1641*ea844a1aSMatthew Knepley   PetscValidPointer(subs, 4);
1642*ea844a1aSMatthew Knepley   ierr = PetscSectionGetNumFields(s, &nF);CHKERRQ(ierr);
1643*ea844a1aSMatthew Knepley   if (len > nF) SETERRQ2(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONG, "Number of requested fields %D greater than number of fields %D", len, nF);
1644*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);CHKERRQ(ierr);
1645*ea844a1aSMatthew Knepley   ierr = PetscSectionSetNumFields(*subs, len);CHKERRQ(ierr);
1646*ea844a1aSMatthew Knepley   for (f = 0; f < len; ++f) {
1647*ea844a1aSMatthew Knepley     const char *name   = NULL;
1648*ea844a1aSMatthew Knepley     PetscInt   numComp = 0;
1649*ea844a1aSMatthew Knepley 
1650*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldName(s, fields[f], &name);CHKERRQ(ierr);
1651*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldName(*subs, f, name);CHKERRQ(ierr);
1652*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldComponents(s, fields[f], &numComp);CHKERRQ(ierr);
1653*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldComponents(*subs, f, numComp);CHKERRQ(ierr);
1654*ea844a1aSMatthew Knepley   }
1655*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1656*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(*subs, pStart, pEnd);CHKERRQ(ierr);
1657*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1658*ea844a1aSMatthew Knepley     PetscInt dof = 0, cdof = 0, fdof = 0, cfdof = 0;
1659*ea844a1aSMatthew Knepley 
1660*ea844a1aSMatthew Knepley     for (f = 0; f < len; ++f) {
1661*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldDof(s, p, fields[f], &fdof);CHKERRQ(ierr);
1662*ea844a1aSMatthew Knepley       ierr = PetscSectionSetFieldDof(*subs, p, f, fdof);CHKERRQ(ierr);
1663*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof);CHKERRQ(ierr);
1664*ea844a1aSMatthew Knepley       if (cfdof) {ierr = PetscSectionSetFieldConstraintDof(*subs, p, f, cfdof);CHKERRQ(ierr);}
1665*ea844a1aSMatthew Knepley       dof  += fdof;
1666*ea844a1aSMatthew Knepley       cdof += cfdof;
1667*ea844a1aSMatthew Knepley     }
1668*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(*subs, p, dof);CHKERRQ(ierr);
1669*ea844a1aSMatthew Knepley     if (cdof) {ierr = PetscSectionSetConstraintDof(*subs, p, cdof);CHKERRQ(ierr);}
1670*ea844a1aSMatthew Knepley     maxCdof = PetscMax(cdof, maxCdof);
1671*ea844a1aSMatthew Knepley   }
1672*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUp(*subs);CHKERRQ(ierr);
1673*ea844a1aSMatthew Knepley   if (maxCdof) {
1674*ea844a1aSMatthew Knepley     PetscInt *indices;
1675*ea844a1aSMatthew Knepley 
1676*ea844a1aSMatthew Knepley     ierr = PetscMalloc1(maxCdof, &indices);CHKERRQ(ierr);
1677*ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
1678*ea844a1aSMatthew Knepley       PetscInt cdof;
1679*ea844a1aSMatthew Knepley 
1680*ea844a1aSMatthew Knepley       ierr = PetscSectionGetConstraintDof(*subs, p, &cdof);CHKERRQ(ierr);
1681*ea844a1aSMatthew Knepley       if (cdof) {
1682*ea844a1aSMatthew Knepley         const PetscInt *oldIndices = NULL;
1683*ea844a1aSMatthew Knepley         PetscInt       fdof = 0, cfdof = 0, fc, numConst = 0, fOff = 0;
1684*ea844a1aSMatthew Knepley 
1685*ea844a1aSMatthew Knepley         for (f = 0; f < len; ++f) {
1686*ea844a1aSMatthew Knepley           PetscInt oldFoff = 0, oldf;
1687*ea844a1aSMatthew Knepley 
1688*ea844a1aSMatthew Knepley           ierr = PetscSectionGetFieldDof(s, p, fields[f], &fdof);CHKERRQ(ierr);
1689*ea844a1aSMatthew Knepley           ierr = PetscSectionGetFieldConstraintDof(s, p, fields[f], &cfdof);CHKERRQ(ierr);
1690*ea844a1aSMatthew Knepley           ierr = PetscSectionGetFieldConstraintIndices(s, p, fields[f], &oldIndices);CHKERRQ(ierr);
1691*ea844a1aSMatthew Knepley           /* This can be sped up if we assume sorted fields */
1692*ea844a1aSMatthew Knepley           for (oldf = 0; oldf < fields[f]; ++oldf) {
1693*ea844a1aSMatthew Knepley             PetscInt oldfdof = 0;
1694*ea844a1aSMatthew Knepley             ierr = PetscSectionGetFieldDof(s, p, oldf, &oldfdof);CHKERRQ(ierr);
1695*ea844a1aSMatthew Knepley             oldFoff += oldfdof;
1696*ea844a1aSMatthew Knepley           }
1697*ea844a1aSMatthew Knepley           for (fc = 0; fc < cfdof; ++fc) indices[numConst+fc] = oldIndices[fc] + (fOff - oldFoff);
1698*ea844a1aSMatthew Knepley           ierr = PetscSectionSetFieldConstraintIndices(*subs, p, f, &indices[numConst]);CHKERRQ(ierr);
1699*ea844a1aSMatthew Knepley           numConst += cfdof;
1700*ea844a1aSMatthew Knepley           fOff     += fdof;
1701*ea844a1aSMatthew Knepley         }
1702*ea844a1aSMatthew Knepley         ierr = PetscSectionSetConstraintIndices(*subs, p, indices);CHKERRQ(ierr);
1703*ea844a1aSMatthew Knepley       }
1704*ea844a1aSMatthew Knepley     }
1705*ea844a1aSMatthew Knepley     ierr = PetscFree(indices);CHKERRQ(ierr);
1706*ea844a1aSMatthew Knepley   }
1707*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1708*ea844a1aSMatthew Knepley }
1709*ea844a1aSMatthew Knepley 
1710*ea844a1aSMatthew Knepley /*@
1711*ea844a1aSMatthew Knepley   PetscSectionCreateSupersection - Create a new, larger section composed of the input sections
1712*ea844a1aSMatthew Knepley 
1713*ea844a1aSMatthew Knepley   Collective on s
1714*ea844a1aSMatthew Knepley 
1715*ea844a1aSMatthew Knepley   Input Parameters:
1716*ea844a1aSMatthew Knepley + s     - the input sections
1717*ea844a1aSMatthew Knepley - len   - the number of input sections
1718*ea844a1aSMatthew Knepley 
1719*ea844a1aSMatthew Knepley   Output Parameter:
1720*ea844a1aSMatthew Knepley . supers - the supersection
1721*ea844a1aSMatthew Knepley 
1722*ea844a1aSMatthew Knepley   Note: The section offsets now refer to a new, larger vector.
1723*ea844a1aSMatthew Knepley 
1724*ea844a1aSMatthew Knepley   Level: advanced
1725*ea844a1aSMatthew Knepley 
1726*ea844a1aSMatthew Knepley .seealso: PetscSectionCreateSubsection(), PetscSectionCreate()
1727*ea844a1aSMatthew Knepley @*/
1728*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCreateSupersection(PetscSection s[], PetscInt len, PetscSection *supers)
1729*ea844a1aSMatthew Knepley {
1730*ea844a1aSMatthew Knepley   PetscInt       Nf = 0, f, pStart = PETSC_MAX_INT, pEnd = 0, p, maxCdof = 0, i;
1731*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1732*ea844a1aSMatthew Knepley 
1733*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1734*ea844a1aSMatthew Knepley   if (!len) PetscFunctionReturn(0);
1735*ea844a1aSMatthew Knepley   for (i = 0; i < len; ++i) {
1736*ea844a1aSMatthew Knepley     PetscInt nf, pStarti, pEndi;
1737*ea844a1aSMatthew Knepley 
1738*ea844a1aSMatthew Knepley     ierr = PetscSectionGetNumFields(s[i], &nf);CHKERRQ(ierr);
1739*ea844a1aSMatthew Knepley     ierr = PetscSectionGetChart(s[i], &pStarti, &pEndi);CHKERRQ(ierr);
1740*ea844a1aSMatthew Knepley     pStart = PetscMin(pStart, pStarti);
1741*ea844a1aSMatthew Knepley     pEnd   = PetscMax(pEnd,   pEndi);
1742*ea844a1aSMatthew Knepley     Nf += nf;
1743*ea844a1aSMatthew Knepley   }
1744*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s[0]), supers);CHKERRQ(ierr);
1745*ea844a1aSMatthew Knepley   ierr = PetscSectionSetNumFields(*supers, Nf);CHKERRQ(ierr);
1746*ea844a1aSMatthew Knepley   for (i = 0, f = 0; i < len; ++i) {
1747*ea844a1aSMatthew Knepley     PetscInt nf, fi;
1748*ea844a1aSMatthew Knepley 
1749*ea844a1aSMatthew Knepley     ierr = PetscSectionGetNumFields(s[i], &nf);CHKERRQ(ierr);
1750*ea844a1aSMatthew Knepley     for (fi = 0; fi < nf; ++fi, ++f) {
1751*ea844a1aSMatthew Knepley       const char *name   = NULL;
1752*ea844a1aSMatthew Knepley       PetscInt   numComp = 0;
1753*ea844a1aSMatthew Knepley 
1754*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldName(s[i], fi, &name);CHKERRQ(ierr);
1755*ea844a1aSMatthew Knepley       ierr = PetscSectionSetFieldName(*supers, f, name);CHKERRQ(ierr);
1756*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldComponents(s[i], fi, &numComp);CHKERRQ(ierr);
1757*ea844a1aSMatthew Knepley       ierr = PetscSectionSetFieldComponents(*supers, f, numComp);CHKERRQ(ierr);
1758*ea844a1aSMatthew Knepley     }
1759*ea844a1aSMatthew Knepley   }
1760*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(*supers, pStart, pEnd);CHKERRQ(ierr);
1761*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1762*ea844a1aSMatthew Knepley     PetscInt dof = 0, cdof = 0;
1763*ea844a1aSMatthew Knepley 
1764*ea844a1aSMatthew Knepley     for (i = 0, f = 0; i < len; ++i) {
1765*ea844a1aSMatthew Knepley       PetscInt nf, fi, pStarti, pEndi;
1766*ea844a1aSMatthew Knepley       PetscInt fdof = 0, cfdof = 0;
1767*ea844a1aSMatthew Knepley 
1768*ea844a1aSMatthew Knepley       ierr = PetscSectionGetNumFields(s[i], &nf);CHKERRQ(ierr);
1769*ea844a1aSMatthew Knepley       ierr = PetscSectionGetChart(s[i], &pStarti, &pEndi);CHKERRQ(ierr);
1770*ea844a1aSMatthew Knepley       if ((p < pStarti) || (p >= pEndi)) continue;
1771*ea844a1aSMatthew Knepley       for (fi = 0; fi < nf; ++fi, ++f) {
1772*ea844a1aSMatthew Knepley         ierr = PetscSectionGetFieldDof(s[i], p, fi, &fdof);CHKERRQ(ierr);
1773*ea844a1aSMatthew Knepley         ierr = PetscSectionAddFieldDof(*supers, p, f, fdof);CHKERRQ(ierr);
1774*ea844a1aSMatthew Knepley         ierr = PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof);CHKERRQ(ierr);
1775*ea844a1aSMatthew Knepley         if (cfdof) {ierr = PetscSectionAddFieldConstraintDof(*supers, p, f, cfdof);CHKERRQ(ierr);}
1776*ea844a1aSMatthew Knepley         dof  += fdof;
1777*ea844a1aSMatthew Knepley         cdof += cfdof;
1778*ea844a1aSMatthew Knepley       }
1779*ea844a1aSMatthew Knepley     }
1780*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(*supers, p, dof);CHKERRQ(ierr);
1781*ea844a1aSMatthew Knepley     if (cdof) {ierr = PetscSectionSetConstraintDof(*supers, p, cdof);CHKERRQ(ierr);}
1782*ea844a1aSMatthew Knepley     maxCdof = PetscMax(cdof, maxCdof);
1783*ea844a1aSMatthew Knepley   }
1784*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUp(*supers);CHKERRQ(ierr);
1785*ea844a1aSMatthew Knepley   if (maxCdof) {
1786*ea844a1aSMatthew Knepley     PetscInt *indices;
1787*ea844a1aSMatthew Knepley 
1788*ea844a1aSMatthew Knepley     ierr = PetscMalloc1(maxCdof, &indices);CHKERRQ(ierr);
1789*ea844a1aSMatthew Knepley     for (p = pStart; p < pEnd; ++p) {
1790*ea844a1aSMatthew Knepley       PetscInt cdof;
1791*ea844a1aSMatthew Knepley 
1792*ea844a1aSMatthew Knepley       ierr = PetscSectionGetConstraintDof(*supers, p, &cdof);CHKERRQ(ierr);
1793*ea844a1aSMatthew Knepley       if (cdof) {
1794*ea844a1aSMatthew Knepley         PetscInt dof, numConst = 0, fOff = 0;
1795*ea844a1aSMatthew Knepley 
1796*ea844a1aSMatthew Knepley         for (i = 0, f = 0; i < len; ++i) {
1797*ea844a1aSMatthew Knepley           const PetscInt *oldIndices = NULL;
1798*ea844a1aSMatthew Knepley           PetscInt        nf, fi, pStarti, pEndi, fdof, cfdof, fc;
1799*ea844a1aSMatthew Knepley 
1800*ea844a1aSMatthew Knepley           ierr = PetscSectionGetNumFields(s[i], &nf);CHKERRQ(ierr);
1801*ea844a1aSMatthew Knepley           ierr = PetscSectionGetChart(s[i], &pStarti, &pEndi);CHKERRQ(ierr);
1802*ea844a1aSMatthew Knepley           if ((p < pStarti) || (p >= pEndi)) continue;
1803*ea844a1aSMatthew Knepley           for (fi = 0; fi < nf; ++fi, ++f) {
1804*ea844a1aSMatthew Knepley             ierr = PetscSectionGetFieldDof(s[i], p, fi, &fdof);CHKERRQ(ierr);
1805*ea844a1aSMatthew Knepley             ierr = PetscSectionGetFieldConstraintDof(s[i], p, fi, &cfdof);CHKERRQ(ierr);
1806*ea844a1aSMatthew Knepley             ierr = PetscSectionGetFieldConstraintIndices(s[i], p, fi, &oldIndices);CHKERRQ(ierr);
1807*ea844a1aSMatthew Knepley             for (fc = 0; fc < cfdof; ++fc) indices[numConst+fc] = oldIndices[fc] + fOff;
1808*ea844a1aSMatthew Knepley             ierr = PetscSectionSetFieldConstraintIndices(*supers, p, f, &indices[numConst]);CHKERRQ(ierr);
1809*ea844a1aSMatthew Knepley             numConst += cfdof;
1810*ea844a1aSMatthew Knepley           }
1811*ea844a1aSMatthew Knepley           ierr = PetscSectionGetDof(s[i], p, &dof);CHKERRQ(ierr);
1812*ea844a1aSMatthew Knepley           fOff += dof;
1813*ea844a1aSMatthew Knepley         }
1814*ea844a1aSMatthew Knepley         ierr = PetscSectionSetConstraintIndices(*supers, p, indices);CHKERRQ(ierr);
1815*ea844a1aSMatthew Knepley       }
1816*ea844a1aSMatthew Knepley     }
1817*ea844a1aSMatthew Knepley     ierr = PetscFree(indices);CHKERRQ(ierr);
1818*ea844a1aSMatthew Knepley   }
1819*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1820*ea844a1aSMatthew Knepley }
1821*ea844a1aSMatthew Knepley 
1822*ea844a1aSMatthew Knepley /*@
1823*ea844a1aSMatthew Knepley   PetscSectionCreateSubmeshSection - Create a new, smaller section with support on the submesh
1824*ea844a1aSMatthew Knepley 
1825*ea844a1aSMatthew Knepley   Collective on s
1826*ea844a1aSMatthew Knepley 
1827*ea844a1aSMatthew Knepley   Input Parameters:
1828*ea844a1aSMatthew Knepley + s           - the PetscSection
1829*ea844a1aSMatthew Knepley - subpointMap - a sorted list of points in the original mesh which are in the submesh
1830*ea844a1aSMatthew Knepley 
1831*ea844a1aSMatthew Knepley   Output Parameter:
1832*ea844a1aSMatthew Knepley . subs - the subsection
1833*ea844a1aSMatthew Knepley 
1834*ea844a1aSMatthew Knepley   Note: The section offsets now refer to a new, smaller vector.
1835*ea844a1aSMatthew Knepley 
1836*ea844a1aSMatthew Knepley   Level: advanced
1837*ea844a1aSMatthew Knepley 
1838*ea844a1aSMatthew Knepley .seealso: PetscSectionCreateSubsection(), DMPlexGetSubpointMap(), PetscSectionCreate()
1839*ea844a1aSMatthew Knepley @*/
1840*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionCreateSubmeshSection(PetscSection s, IS subpointMap, PetscSection *subs)
1841*ea844a1aSMatthew Knepley {
1842*ea844a1aSMatthew Knepley   const PetscInt *points = NULL, *indices = NULL;
1843*ea844a1aSMatthew Knepley   PetscInt       numFields, f, numSubpoints = 0, pStart, pEnd, p, subp;
1844*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1845*ea844a1aSMatthew Knepley 
1846*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1847*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1848*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2);
1849*ea844a1aSMatthew Knepley   PetscValidPointer(subs, 3);
1850*ea844a1aSMatthew Knepley   ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr);
1851*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);CHKERRQ(ierr);
1852*ea844a1aSMatthew Knepley   if (numFields) {ierr = PetscSectionSetNumFields(*subs, numFields);CHKERRQ(ierr);}
1853*ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
1854*ea844a1aSMatthew Knepley     const char *name   = NULL;
1855*ea844a1aSMatthew Knepley     PetscInt   numComp = 0;
1856*ea844a1aSMatthew Knepley 
1857*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldName(s, f, &name);CHKERRQ(ierr);
1858*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldName(*subs, f, name);CHKERRQ(ierr);
1859*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldComponents(s, f, &numComp);CHKERRQ(ierr);
1860*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldComponents(*subs, f, numComp);CHKERRQ(ierr);
1861*ea844a1aSMatthew Knepley   }
1862*ea844a1aSMatthew Knepley   /* For right now, we do not try to squeeze the subchart */
1863*ea844a1aSMatthew Knepley   if (subpointMap) {
1864*ea844a1aSMatthew Knepley     ierr = ISGetSize(subpointMap, &numSubpoints);CHKERRQ(ierr);
1865*ea844a1aSMatthew Knepley     ierr = ISGetIndices(subpointMap, &points);CHKERRQ(ierr);
1866*ea844a1aSMatthew Knepley   }
1867*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1868*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(*subs, 0, numSubpoints);CHKERRQ(ierr);
1869*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1870*ea844a1aSMatthew Knepley     PetscInt dof, cdof, fdof = 0, cfdof = 0;
1871*ea844a1aSMatthew Knepley 
1872*ea844a1aSMatthew Knepley     ierr = PetscFindInt(p, numSubpoints, points, &subp);CHKERRQ(ierr);
1873*ea844a1aSMatthew Knepley     if (subp < 0) continue;
1874*ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
1875*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr);
1876*ea844a1aSMatthew Knepley       ierr = PetscSectionSetFieldDof(*subs, subp, f, fdof);CHKERRQ(ierr);
1877*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintDof(s, p, f, &cfdof);CHKERRQ(ierr);
1878*ea844a1aSMatthew Knepley       if (cfdof) {ierr = PetscSectionSetFieldConstraintDof(*subs, subp, f, cfdof);CHKERRQ(ierr);}
1879*ea844a1aSMatthew Knepley     }
1880*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
1881*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(*subs, subp, dof);CHKERRQ(ierr);
1882*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
1883*ea844a1aSMatthew Knepley     if (cdof) {ierr = PetscSectionSetConstraintDof(*subs, subp, cdof);CHKERRQ(ierr);}
1884*ea844a1aSMatthew Knepley   }
1885*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUp(*subs);CHKERRQ(ierr);
1886*ea844a1aSMatthew Knepley   /* Change offsets to original offsets */
1887*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
1888*ea844a1aSMatthew Knepley     PetscInt off, foff = 0;
1889*ea844a1aSMatthew Knepley 
1890*ea844a1aSMatthew Knepley     ierr = PetscFindInt(p, numSubpoints, points, &subp);CHKERRQ(ierr);
1891*ea844a1aSMatthew Knepley     if (subp < 0) continue;
1892*ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
1893*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr);
1894*ea844a1aSMatthew Knepley       ierr = PetscSectionSetFieldOffset(*subs, subp, f, foff);CHKERRQ(ierr);
1895*ea844a1aSMatthew Knepley     }
1896*ea844a1aSMatthew Knepley     ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
1897*ea844a1aSMatthew Knepley     ierr = PetscSectionSetOffset(*subs, subp, off);CHKERRQ(ierr);
1898*ea844a1aSMatthew Knepley   }
1899*ea844a1aSMatthew Knepley   /* Copy constraint indices */
1900*ea844a1aSMatthew Knepley   for (subp = 0; subp < numSubpoints; ++subp) {
1901*ea844a1aSMatthew Knepley     PetscInt cdof;
1902*ea844a1aSMatthew Knepley 
1903*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(*subs, subp, &cdof);CHKERRQ(ierr);
1904*ea844a1aSMatthew Knepley     if (cdof) {
1905*ea844a1aSMatthew Knepley       for (f = 0; f < numFields; ++f) {
1906*ea844a1aSMatthew Knepley         ierr = PetscSectionGetFieldConstraintIndices(s, points[subp], f, &indices);CHKERRQ(ierr);
1907*ea844a1aSMatthew Knepley         ierr = PetscSectionSetFieldConstraintIndices(*subs, subp, f, indices);CHKERRQ(ierr);
1908*ea844a1aSMatthew Knepley       }
1909*ea844a1aSMatthew Knepley       ierr = PetscSectionGetConstraintIndices(s, points[subp], &indices);CHKERRQ(ierr);
1910*ea844a1aSMatthew Knepley       ierr = PetscSectionSetConstraintIndices(*subs, subp, indices);CHKERRQ(ierr);
1911*ea844a1aSMatthew Knepley     }
1912*ea844a1aSMatthew Knepley   }
1913*ea844a1aSMatthew Knepley   if (subpointMap) {ierr = ISRestoreIndices(subpointMap, &points);CHKERRQ(ierr);}
1914*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1915*ea844a1aSMatthew Knepley }
1916*ea844a1aSMatthew Knepley 
1917*ea844a1aSMatthew Knepley static PetscErrorCode PetscSectionView_ASCII(PetscSection s, PetscViewer viewer)
1918*ea844a1aSMatthew Knepley {
1919*ea844a1aSMatthew Knepley   PetscInt       p;
1920*ea844a1aSMatthew Knepley   PetscMPIInt    rank;
1921*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1922*ea844a1aSMatthew Knepley 
1923*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1924*ea844a1aSMatthew Knepley   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr);
1925*ea844a1aSMatthew Knepley   ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
1926*ea844a1aSMatthew Knepley   ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr);
1927*ea844a1aSMatthew Knepley   for (p = 0; p < s->pEnd - s->pStart; ++p) {
1928*ea844a1aSMatthew Knepley     if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
1929*ea844a1aSMatthew Knepley       PetscInt b;
1930*ea844a1aSMatthew Knepley 
1931*ea844a1aSMatthew Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4D) dim %2D offset %3D constrained", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
1932*ea844a1aSMatthew Knepley       for (b = 0; b < s->bc->atlasDof[p]; ++b) {
1933*ea844a1aSMatthew Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %D", s->bcIndices[s->bc->atlasOff[p]+b]);CHKERRQ(ierr);
1934*ea844a1aSMatthew Knepley       }
1935*ea844a1aSMatthew Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr);
1936*ea844a1aSMatthew Knepley     } else {
1937*ea844a1aSMatthew Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4D) dim %2D offset %3D\n", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
1938*ea844a1aSMatthew Knepley     }
1939*ea844a1aSMatthew Knepley   }
1940*ea844a1aSMatthew Knepley   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1941*ea844a1aSMatthew Knepley   ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
1942*ea844a1aSMatthew Knepley   if (s->sym) {
1943*ea844a1aSMatthew Knepley     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1944*ea844a1aSMatthew Knepley     ierr = PetscSectionSymView(s->sym,viewer);CHKERRQ(ierr);
1945*ea844a1aSMatthew Knepley     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1946*ea844a1aSMatthew Knepley   }
1947*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1948*ea844a1aSMatthew Knepley }
1949*ea844a1aSMatthew Knepley 
1950*ea844a1aSMatthew Knepley /*@C
1951*ea844a1aSMatthew Knepley   PetscSectionView - Views a PetscSection
1952*ea844a1aSMatthew Knepley 
1953*ea844a1aSMatthew Knepley   Collective on PetscSection
1954*ea844a1aSMatthew Knepley 
1955*ea844a1aSMatthew Knepley   Input Parameters:
1956*ea844a1aSMatthew Knepley + s - the PetscSection object to view
1957*ea844a1aSMatthew Knepley - v - the viewer
1958*ea844a1aSMatthew Knepley 
1959*ea844a1aSMatthew Knepley   Level: beginner
1960*ea844a1aSMatthew Knepley 
1961*ea844a1aSMatthew Knepley .seealso PetscSectionCreate(), PetscSectionDestroy()
1962*ea844a1aSMatthew Knepley @*/
1963*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionView(PetscSection s, PetscViewer viewer)
1964*ea844a1aSMatthew Knepley {
1965*ea844a1aSMatthew Knepley   PetscBool      isascii;
1966*ea844a1aSMatthew Knepley   PetscInt       f;
1967*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
1968*ea844a1aSMatthew Knepley 
1969*ea844a1aSMatthew Knepley   PetscFunctionBegin;
1970*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
1971*ea844a1aSMatthew Knepley   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)s), &viewer);CHKERRQ(ierr);}
1972*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1973*ea844a1aSMatthew Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr);
1974*ea844a1aSMatthew Knepley   if (isascii) {
1975*ea844a1aSMatthew Knepley     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)s,viewer);CHKERRQ(ierr);
1976*ea844a1aSMatthew Knepley     if (s->numFields) {
1977*ea844a1aSMatthew Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%D fields\n", s->numFields);CHKERRQ(ierr);
1978*ea844a1aSMatthew Knepley       for (f = 0; f < s->numFields; ++f) {
1979*ea844a1aSMatthew Knepley         ierr = PetscViewerASCIIPrintf(viewer, "  field %D with %D components\n", f, s->numFieldComponents[f]);CHKERRQ(ierr);
1980*ea844a1aSMatthew Knepley         ierr = PetscSectionView_ASCII(s->field[f], viewer);CHKERRQ(ierr);
1981*ea844a1aSMatthew Knepley       }
1982*ea844a1aSMatthew Knepley     } else {
1983*ea844a1aSMatthew Knepley       ierr = PetscSectionView_ASCII(s, viewer);CHKERRQ(ierr);
1984*ea844a1aSMatthew Knepley     }
1985*ea844a1aSMatthew Knepley   }
1986*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
1987*ea844a1aSMatthew Knepley }
1988*ea844a1aSMatthew Knepley 
1989*ea844a1aSMatthew Knepley /*@
1990*ea844a1aSMatthew Knepley   PetscSectionReset - Frees all section data.
1991*ea844a1aSMatthew Knepley 
1992*ea844a1aSMatthew Knepley   Not collective
1993*ea844a1aSMatthew Knepley 
1994*ea844a1aSMatthew Knepley   Input Parameters:
1995*ea844a1aSMatthew Knepley . s - the PetscSection
1996*ea844a1aSMatthew Knepley 
1997*ea844a1aSMatthew Knepley   Level: beginner
1998*ea844a1aSMatthew Knepley 
1999*ea844a1aSMatthew Knepley .seealso: PetscSection, PetscSectionCreate()
2000*ea844a1aSMatthew Knepley @*/
2001*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionReset(PetscSection s)
2002*ea844a1aSMatthew Knepley {
2003*ea844a1aSMatthew Knepley   PetscInt       f;
2004*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2005*ea844a1aSMatthew Knepley 
2006*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2007*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2008*ea844a1aSMatthew Knepley   ierr = PetscFree(s->numFieldComponents);CHKERRQ(ierr);
2009*ea844a1aSMatthew Knepley   for (f = 0; f < s->numFields; ++f) {
2010*ea844a1aSMatthew Knepley     ierr = PetscSectionDestroy(&s->field[f]);CHKERRQ(ierr);
2011*ea844a1aSMatthew Knepley     ierr = PetscFree(s->fieldNames[f]);CHKERRQ(ierr);
2012*ea844a1aSMatthew Knepley   }
2013*ea844a1aSMatthew Knepley   ierr = PetscFree(s->fieldNames);CHKERRQ(ierr);
2014*ea844a1aSMatthew Knepley   ierr = PetscFree(s->field);CHKERRQ(ierr);
2015*ea844a1aSMatthew Knepley   ierr = PetscSectionDestroy(&s->bc);CHKERRQ(ierr);
2016*ea844a1aSMatthew Knepley   ierr = PetscFree(s->bcIndices);CHKERRQ(ierr);
2017*ea844a1aSMatthew Knepley   ierr = PetscFree2(s->atlasDof, s->atlasOff);CHKERRQ(ierr);
2018*ea844a1aSMatthew Knepley   ierr = PetscSectionDestroy(&s->clSection);CHKERRQ(ierr);
2019*ea844a1aSMatthew Knepley   ierr = ISDestroy(&s->clPoints);CHKERRQ(ierr);
2020*ea844a1aSMatthew Knepley   ierr = ISDestroy(&s->perm);CHKERRQ(ierr);
2021*ea844a1aSMatthew Knepley   ierr = PetscFree(s->clPerm);CHKERRQ(ierr);
2022*ea844a1aSMatthew Knepley   ierr = PetscFree(s->clInvPerm);CHKERRQ(ierr);
2023*ea844a1aSMatthew Knepley   ierr = PetscSectionSymDestroy(&s->sym);CHKERRQ(ierr);
2024*ea844a1aSMatthew Knepley 
2025*ea844a1aSMatthew Knepley   s->pStart    = -1;
2026*ea844a1aSMatthew Knepley   s->pEnd      = -1;
2027*ea844a1aSMatthew Knepley   s->maxDof    = 0;
2028*ea844a1aSMatthew Knepley   s->setup     = PETSC_FALSE;
2029*ea844a1aSMatthew Knepley   s->numFields = 0;
2030*ea844a1aSMatthew Knepley   s->clObj     = NULL;
2031*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2032*ea844a1aSMatthew Knepley }
2033*ea844a1aSMatthew Knepley 
2034*ea844a1aSMatthew Knepley /*@
2035*ea844a1aSMatthew Knepley   PetscSectionDestroy - Frees a section object and frees its range if that exists.
2036*ea844a1aSMatthew Knepley 
2037*ea844a1aSMatthew Knepley   Not collective
2038*ea844a1aSMatthew Knepley 
2039*ea844a1aSMatthew Knepley   Input Parameters:
2040*ea844a1aSMatthew Knepley . s - the PetscSection
2041*ea844a1aSMatthew Knepley 
2042*ea844a1aSMatthew Knepley   Level: beginner
2043*ea844a1aSMatthew Knepley 
2044*ea844a1aSMatthew Knepley .seealso: PetscSection, PetscSectionCreate()
2045*ea844a1aSMatthew Knepley @*/
2046*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionDestroy(PetscSection *s)
2047*ea844a1aSMatthew Knepley {
2048*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2049*ea844a1aSMatthew Knepley 
2050*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2051*ea844a1aSMatthew Knepley   if (!*s) PetscFunctionReturn(0);
2052*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific((*s),PETSC_SECTION_CLASSID,1);
2053*ea844a1aSMatthew Knepley   if (--((PetscObject)(*s))->refct > 0) {
2054*ea844a1aSMatthew Knepley     *s = NULL;
2055*ea844a1aSMatthew Knepley     PetscFunctionReturn(0);
2056*ea844a1aSMatthew Knepley   }
2057*ea844a1aSMatthew Knepley   ierr = PetscSectionReset(*s);CHKERRQ(ierr);
2058*ea844a1aSMatthew Knepley   ierr = PetscHeaderDestroy(s);CHKERRQ(ierr);
2059*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2060*ea844a1aSMatthew Knepley }
2061*ea844a1aSMatthew Knepley 
2062*ea844a1aSMatthew Knepley PetscErrorCode VecIntGetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values)
2063*ea844a1aSMatthew Knepley {
2064*ea844a1aSMatthew Knepley   const PetscInt p = point - s->pStart;
2065*ea844a1aSMatthew Knepley 
2066*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2067*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2);
2068*ea844a1aSMatthew Knepley   *values = &baseArray[s->atlasOff[p]];
2069*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2070*ea844a1aSMatthew Knepley }
2071*ea844a1aSMatthew Knepley 
2072*ea844a1aSMatthew Knepley PetscErrorCode VecIntSetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode)
2073*ea844a1aSMatthew Knepley {
2074*ea844a1aSMatthew Knepley   PetscInt       *array;
2075*ea844a1aSMatthew Knepley   const PetscInt p           = point - s->pStart;
2076*ea844a1aSMatthew Knepley   const PetscInt orientation = 0; /* Needs to be included for use in closure operations */
2077*ea844a1aSMatthew Knepley   PetscInt       cDim        = 0;
2078*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2079*ea844a1aSMatthew Knepley 
2080*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2081*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 2);
2082*ea844a1aSMatthew Knepley   ierr  = PetscSectionGetConstraintDof(s, p, &cDim);CHKERRQ(ierr);
2083*ea844a1aSMatthew Knepley   array = &baseArray[s->atlasOff[p]];
2084*ea844a1aSMatthew Knepley   if (!cDim) {
2085*ea844a1aSMatthew Knepley     if (orientation >= 0) {
2086*ea844a1aSMatthew Knepley       const PetscInt dim = s->atlasDof[p];
2087*ea844a1aSMatthew Knepley       PetscInt       i;
2088*ea844a1aSMatthew Knepley 
2089*ea844a1aSMatthew Knepley       if (mode == INSERT_VALUES) {
2090*ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) array[i] = values[i];
2091*ea844a1aSMatthew Knepley       } else {
2092*ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) array[i] += values[i];
2093*ea844a1aSMatthew Knepley       }
2094*ea844a1aSMatthew Knepley     } else {
2095*ea844a1aSMatthew Knepley       PetscInt offset = 0;
2096*ea844a1aSMatthew Knepley       PetscInt j      = -1, field, i;
2097*ea844a1aSMatthew Knepley 
2098*ea844a1aSMatthew Knepley       for (field = 0; field < s->numFields; ++field) {
2099*ea844a1aSMatthew Knepley         const PetscInt dim = s->field[field]->atlasDof[p];
2100*ea844a1aSMatthew Knepley 
2101*ea844a1aSMatthew Knepley         for (i = dim-1; i >= 0; --i) array[++j] = values[i+offset];
2102*ea844a1aSMatthew Knepley         offset += dim;
2103*ea844a1aSMatthew Knepley       }
2104*ea844a1aSMatthew Knepley     }
2105*ea844a1aSMatthew Knepley   } else {
2106*ea844a1aSMatthew Knepley     if (orientation >= 0) {
2107*ea844a1aSMatthew Knepley       const PetscInt dim  = s->atlasDof[p];
2108*ea844a1aSMatthew Knepley       PetscInt       cInd = 0, i;
2109*ea844a1aSMatthew Knepley       const PetscInt *cDof;
2110*ea844a1aSMatthew Knepley 
2111*ea844a1aSMatthew Knepley       ierr = PetscSectionGetConstraintIndices(s, point, &cDof);CHKERRQ(ierr);
2112*ea844a1aSMatthew Knepley       if (mode == INSERT_VALUES) {
2113*ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) {
2114*ea844a1aSMatthew Knepley           if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
2115*ea844a1aSMatthew Knepley           array[i] = values[i];
2116*ea844a1aSMatthew Knepley         }
2117*ea844a1aSMatthew Knepley       } else {
2118*ea844a1aSMatthew Knepley         for (i = 0; i < dim; ++i) {
2119*ea844a1aSMatthew Knepley           if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
2120*ea844a1aSMatthew Knepley           array[i] += values[i];
2121*ea844a1aSMatthew Knepley         }
2122*ea844a1aSMatthew Knepley       }
2123*ea844a1aSMatthew Knepley     } else {
2124*ea844a1aSMatthew Knepley       const PetscInt *cDof;
2125*ea844a1aSMatthew Knepley       PetscInt       offset  = 0;
2126*ea844a1aSMatthew Knepley       PetscInt       cOffset = 0;
2127*ea844a1aSMatthew Knepley       PetscInt       j       = 0, field;
2128*ea844a1aSMatthew Knepley 
2129*ea844a1aSMatthew Knepley       ierr = PetscSectionGetConstraintIndices(s, point, &cDof);CHKERRQ(ierr);
2130*ea844a1aSMatthew Knepley       for (field = 0; field < s->numFields; ++field) {
2131*ea844a1aSMatthew Knepley         const PetscInt dim  = s->field[field]->atlasDof[p];     /* PetscSectionGetFieldDof() */
2132*ea844a1aSMatthew Knepley         const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */
2133*ea844a1aSMatthew Knepley         const PetscInt sDim = dim - tDim;
2134*ea844a1aSMatthew Knepley         PetscInt       cInd = 0, i,k;
2135*ea844a1aSMatthew Knepley 
2136*ea844a1aSMatthew Knepley         for (i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
2137*ea844a1aSMatthew Knepley           if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
2138*ea844a1aSMatthew Knepley           array[j] = values[k];
2139*ea844a1aSMatthew Knepley         }
2140*ea844a1aSMatthew Knepley         offset  += dim;
2141*ea844a1aSMatthew Knepley         cOffset += dim - tDim;
2142*ea844a1aSMatthew Knepley       }
2143*ea844a1aSMatthew Knepley     }
2144*ea844a1aSMatthew Knepley   }
2145*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2146*ea844a1aSMatthew Knepley }
2147*ea844a1aSMatthew Knepley 
2148*ea844a1aSMatthew Knepley /*@C
2149*ea844a1aSMatthew Knepley   PetscSectionHasConstraints - Determine whether a section has constrained dofs
2150*ea844a1aSMatthew Knepley 
2151*ea844a1aSMatthew Knepley   Not collective
2152*ea844a1aSMatthew Knepley 
2153*ea844a1aSMatthew Knepley   Input Parameter:
2154*ea844a1aSMatthew Knepley . s - The PetscSection
2155*ea844a1aSMatthew Knepley 
2156*ea844a1aSMatthew Knepley   Output Parameter:
2157*ea844a1aSMatthew Knepley . hasConstraints - flag indicating that the section has constrained dofs
2158*ea844a1aSMatthew Knepley 
2159*ea844a1aSMatthew Knepley   Level: intermediate
2160*ea844a1aSMatthew Knepley 
2161*ea844a1aSMatthew Knepley .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
2162*ea844a1aSMatthew Knepley @*/
2163*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionHasConstraints(PetscSection s, PetscBool *hasConstraints)
2164*ea844a1aSMatthew Knepley {
2165*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2166*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2167*ea844a1aSMatthew Knepley   PetscValidPointer(hasConstraints, 2);
2168*ea844a1aSMatthew Knepley   *hasConstraints = s->bc ? PETSC_TRUE : PETSC_FALSE;
2169*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2170*ea844a1aSMatthew Knepley }
2171*ea844a1aSMatthew Knepley 
2172*ea844a1aSMatthew Knepley /*@C
2173*ea844a1aSMatthew Knepley   PetscSectionGetConstraintIndices - Get the point dof numbers, in [0, dof), which are constrained
2174*ea844a1aSMatthew Knepley 
2175*ea844a1aSMatthew Knepley   Not collective
2176*ea844a1aSMatthew Knepley 
2177*ea844a1aSMatthew Knepley   Input Parameters:
2178*ea844a1aSMatthew Knepley + s     - The PetscSection
2179*ea844a1aSMatthew Knepley - point - The point
2180*ea844a1aSMatthew Knepley 
2181*ea844a1aSMatthew Knepley   Output Parameter:
2182*ea844a1aSMatthew Knepley . indices - The constrained dofs
2183*ea844a1aSMatthew Knepley 
2184*ea844a1aSMatthew Knepley   Note: In Fortran, you call PetscSectionGetConstraintIndicesF90() and PetscSectionRestoreConstraintIndicesF90()
2185*ea844a1aSMatthew Knepley 
2186*ea844a1aSMatthew Knepley   Level: intermediate
2187*ea844a1aSMatthew Knepley 
2188*ea844a1aSMatthew Knepley .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
2189*ea844a1aSMatthew Knepley @*/
2190*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetConstraintIndices(PetscSection s, PetscInt point, const PetscInt **indices)
2191*ea844a1aSMatthew Knepley {
2192*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2193*ea844a1aSMatthew Knepley 
2194*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2195*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2196*ea844a1aSMatthew Knepley   if (s->bc) {
2197*ea844a1aSMatthew Knepley     ierr = VecIntGetValuesSection(s->bcIndices, s->bc, point, indices);CHKERRQ(ierr);
2198*ea844a1aSMatthew Knepley   } else *indices = NULL;
2199*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2200*ea844a1aSMatthew Knepley }
2201*ea844a1aSMatthew Knepley 
2202*ea844a1aSMatthew Knepley /*@C
2203*ea844a1aSMatthew Knepley   PetscSectionSetConstraintIndices - Set the point dof numbers, in [0, dof), which are constrained
2204*ea844a1aSMatthew Knepley 
2205*ea844a1aSMatthew Knepley   Not collective
2206*ea844a1aSMatthew Knepley 
2207*ea844a1aSMatthew Knepley   Input Parameters:
2208*ea844a1aSMatthew Knepley + s     - The PetscSection
2209*ea844a1aSMatthew Knepley . point - The point
2210*ea844a1aSMatthew Knepley - indices - The constrained dofs
2211*ea844a1aSMatthew Knepley 
2212*ea844a1aSMatthew Knepley   Note: The Fortran is PetscSectionSetConstraintIndicesF90()
2213*ea844a1aSMatthew Knepley 
2214*ea844a1aSMatthew Knepley   Level: intermediate
2215*ea844a1aSMatthew Knepley 
2216*ea844a1aSMatthew Knepley .seealso: PetscSectionGetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
2217*ea844a1aSMatthew Knepley @*/
2218*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetConstraintIndices(PetscSection s, PetscInt point, const PetscInt indices[])
2219*ea844a1aSMatthew Knepley {
2220*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2221*ea844a1aSMatthew Knepley 
2222*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2223*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2224*ea844a1aSMatthew Knepley   if (s->bc) {
2225*ea844a1aSMatthew Knepley     ierr = VecIntSetValuesSection(s->bcIndices, s->bc, point, indices, INSERT_VALUES);CHKERRQ(ierr);
2226*ea844a1aSMatthew Knepley   }
2227*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2228*ea844a1aSMatthew Knepley }
2229*ea844a1aSMatthew Knepley 
2230*ea844a1aSMatthew Knepley /*@C
2231*ea844a1aSMatthew Knepley   PetscSectionGetFieldConstraintIndices - Get the field dof numbers, in [0, fdof), which are constrained
2232*ea844a1aSMatthew Knepley 
2233*ea844a1aSMatthew Knepley   Not collective
2234*ea844a1aSMatthew Knepley 
2235*ea844a1aSMatthew Knepley   Input Parameters:
2236*ea844a1aSMatthew Knepley + s     - The PetscSection
2237*ea844a1aSMatthew Knepley .field  - The field number
2238*ea844a1aSMatthew Knepley - point - The point
2239*ea844a1aSMatthew Knepley 
2240*ea844a1aSMatthew Knepley   Output Parameter:
2241*ea844a1aSMatthew Knepley . indices - The constrained dofs
2242*ea844a1aSMatthew Knepley 
2243*ea844a1aSMatthew Knepley   Note: In Fortran, you call PetscSectionGetFieldConstraintIndicesF90() and PetscSectionRestoreFieldConstraintIndicesF90()
2244*ea844a1aSMatthew Knepley 
2245*ea844a1aSMatthew Knepley   Level: intermediate
2246*ea844a1aSMatthew Knepley 
2247*ea844a1aSMatthew Knepley .seealso: PetscSectionSetFieldConstraintIndices(), PetscSectionGetConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
2248*ea844a1aSMatthew Knepley @*/
2249*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt **indices)
2250*ea844a1aSMatthew Knepley {
2251*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2252*ea844a1aSMatthew Knepley 
2253*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2254*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2255*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
2256*ea844a1aSMatthew Knepley   ierr = PetscSectionGetConstraintIndices(s->field[field], point, indices);CHKERRQ(ierr);
2257*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2258*ea844a1aSMatthew Knepley }
2259*ea844a1aSMatthew Knepley 
2260*ea844a1aSMatthew Knepley /*@C
2261*ea844a1aSMatthew Knepley   PetscSectionSetFieldConstraintIndices - Set the field dof numbers, in [0, fdof), which are constrained
2262*ea844a1aSMatthew Knepley 
2263*ea844a1aSMatthew Knepley   Not collective
2264*ea844a1aSMatthew Knepley 
2265*ea844a1aSMatthew Knepley   Input Parameters:
2266*ea844a1aSMatthew Knepley + s       - The PetscSection
2267*ea844a1aSMatthew Knepley . point   - The point
2268*ea844a1aSMatthew Knepley . field   - The field number
2269*ea844a1aSMatthew Knepley - indices - The constrained dofs
2270*ea844a1aSMatthew Knepley 
2271*ea844a1aSMatthew Knepley   Note: The Fortran is PetscSectionSetFieldConstraintIndicesF90()
2272*ea844a1aSMatthew Knepley 
2273*ea844a1aSMatthew Knepley   Level: intermediate
2274*ea844a1aSMatthew Knepley 
2275*ea844a1aSMatthew Knepley .seealso: PetscSectionSetConstraintIndices(), PetscSectionGetFieldConstraintIndices(), PetscSectionGetConstraintDof(), PetscSection
2276*ea844a1aSMatthew Knepley @*/
2277*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFieldConstraintIndices(PetscSection s, PetscInt point, PetscInt field, const PetscInt indices[])
2278*ea844a1aSMatthew Knepley {
2279*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2280*ea844a1aSMatthew Knepley 
2281*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2282*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
2283*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
2284*ea844a1aSMatthew Knepley   ierr = PetscSectionSetConstraintIndices(s->field[field], point, indices);CHKERRQ(ierr);
2285*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2286*ea844a1aSMatthew Knepley }
2287*ea844a1aSMatthew Knepley 
2288*ea844a1aSMatthew Knepley /*@
2289*ea844a1aSMatthew Knepley   PetscSectionPermute - Reorder the section according to the input point permutation
2290*ea844a1aSMatthew Knepley 
2291*ea844a1aSMatthew Knepley   Collective on PetscSection
2292*ea844a1aSMatthew Knepley 
2293*ea844a1aSMatthew Knepley   Input Parameter:
2294*ea844a1aSMatthew Knepley + section - The PetscSection object
2295*ea844a1aSMatthew Knepley - perm - The point permutation, old point p becomes new point perm[p]
2296*ea844a1aSMatthew Knepley 
2297*ea844a1aSMatthew Knepley   Output Parameter:
2298*ea844a1aSMatthew Knepley . sectionNew - The permuted PetscSection
2299*ea844a1aSMatthew Knepley 
2300*ea844a1aSMatthew Knepley   Level: intermediate
2301*ea844a1aSMatthew Knepley 
2302*ea844a1aSMatthew Knepley .seealso: MatPermute()
2303*ea844a1aSMatthew Knepley @*/
2304*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionPermute(PetscSection section, IS permutation, PetscSection *sectionNew)
2305*ea844a1aSMatthew Knepley {
2306*ea844a1aSMatthew Knepley   PetscSection    s = section, sNew;
2307*ea844a1aSMatthew Knepley   const PetscInt *perm;
2308*ea844a1aSMatthew Knepley   PetscInt        numFields, f, numPoints, pStart, pEnd, p;
2309*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
2310*ea844a1aSMatthew Knepley 
2311*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2312*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 1);
2313*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(permutation, IS_CLASSID, 2);
2314*ea844a1aSMatthew Knepley   PetscValidPointer(sectionNew, 3);
2315*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), &sNew);CHKERRQ(ierr);
2316*ea844a1aSMatthew Knepley   ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr);
2317*ea844a1aSMatthew Knepley   if (numFields) {ierr = PetscSectionSetNumFields(sNew, numFields);CHKERRQ(ierr);}
2318*ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
2319*ea844a1aSMatthew Knepley     const char *name;
2320*ea844a1aSMatthew Knepley     PetscInt    numComp;
2321*ea844a1aSMatthew Knepley 
2322*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldName(s, f, &name);CHKERRQ(ierr);
2323*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldName(sNew, f, name);CHKERRQ(ierr);
2324*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldComponents(s, f, &numComp);CHKERRQ(ierr);
2325*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldComponents(sNew, f, numComp);CHKERRQ(ierr);
2326*ea844a1aSMatthew Knepley   }
2327*ea844a1aSMatthew Knepley   ierr = ISGetLocalSize(permutation, &numPoints);CHKERRQ(ierr);
2328*ea844a1aSMatthew Knepley   ierr = ISGetIndices(permutation, &perm);CHKERRQ(ierr);
2329*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
2330*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(sNew, pStart, pEnd);CHKERRQ(ierr);
2331*ea844a1aSMatthew Knepley   if (numPoints < pEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Permutation size %D is less than largest Section point %D", numPoints, pEnd);
2332*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2333*ea844a1aSMatthew Knepley     PetscInt dof, cdof;
2334*ea844a1aSMatthew Knepley 
2335*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
2336*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(sNew, perm[p], dof);CHKERRQ(ierr);
2337*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
2338*ea844a1aSMatthew Knepley     if (cdof) {ierr = PetscSectionSetConstraintDof(sNew, perm[p], cdof);CHKERRQ(ierr);}
2339*ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
2340*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldDof(s, p, f, &dof);CHKERRQ(ierr);
2341*ea844a1aSMatthew Knepley       ierr = PetscSectionSetFieldDof(sNew, perm[p], f, dof);CHKERRQ(ierr);
2342*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintDof(s, p, f, &cdof);CHKERRQ(ierr);
2343*ea844a1aSMatthew Knepley       if (cdof) {ierr = PetscSectionSetFieldConstraintDof(sNew, perm[p], f, cdof);CHKERRQ(ierr);}
2344*ea844a1aSMatthew Knepley     }
2345*ea844a1aSMatthew Knepley   }
2346*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUp(sNew);CHKERRQ(ierr);
2347*ea844a1aSMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
2348*ea844a1aSMatthew Knepley     const PetscInt *cind;
2349*ea844a1aSMatthew Knepley     PetscInt        cdof;
2350*ea844a1aSMatthew Knepley 
2351*ea844a1aSMatthew Knepley     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
2352*ea844a1aSMatthew Knepley     if (cdof) {
2353*ea844a1aSMatthew Knepley       ierr = PetscSectionGetConstraintIndices(s, p, &cind);CHKERRQ(ierr);
2354*ea844a1aSMatthew Knepley       ierr = PetscSectionSetConstraintIndices(sNew, perm[p], cind);CHKERRQ(ierr);
2355*ea844a1aSMatthew Knepley     }
2356*ea844a1aSMatthew Knepley     for (f = 0; f < numFields; ++f) {
2357*ea844a1aSMatthew Knepley       ierr = PetscSectionGetFieldConstraintDof(s, p, f, &cdof);CHKERRQ(ierr);
2358*ea844a1aSMatthew Knepley       if (cdof) {
2359*ea844a1aSMatthew Knepley         ierr = PetscSectionGetFieldConstraintIndices(s, p, f, &cind);CHKERRQ(ierr);
2360*ea844a1aSMatthew Knepley         ierr = PetscSectionSetFieldConstraintIndices(sNew, perm[p], f, cind);CHKERRQ(ierr);
2361*ea844a1aSMatthew Knepley       }
2362*ea844a1aSMatthew Knepley     }
2363*ea844a1aSMatthew Knepley   }
2364*ea844a1aSMatthew Knepley   ierr = ISRestoreIndices(permutation, &perm);CHKERRQ(ierr);
2365*ea844a1aSMatthew Knepley   *sectionNew = sNew;
2366*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2367*ea844a1aSMatthew Knepley }
2368*ea844a1aSMatthew Knepley 
2369*ea844a1aSMatthew Knepley /* TODO: the next three functions should be moved to sf/utils */
2370*ea844a1aSMatthew Knepley #include <petsc/private/sfimpl.h>
2371*ea844a1aSMatthew Knepley 
2372*ea844a1aSMatthew Knepley /*@C
2373*ea844a1aSMatthew Knepley   PetscSFDistributeSection - Create a new PetscSection reorganized, moving from the root to the leaves of the SF
2374*ea844a1aSMatthew Knepley 
2375*ea844a1aSMatthew Knepley   Collective on sf
2376*ea844a1aSMatthew Knepley 
2377*ea844a1aSMatthew Knepley   Input Parameters:
2378*ea844a1aSMatthew Knepley + sf - The SF
2379*ea844a1aSMatthew Knepley - rootSection - Section defined on root space
2380*ea844a1aSMatthew Knepley 
2381*ea844a1aSMatthew Knepley   Output Parameters:
2382*ea844a1aSMatthew Knepley + remoteOffsets - root offsets in leaf storage, or NULL
2383*ea844a1aSMatthew Knepley - leafSection - Section defined on the leaf space
2384*ea844a1aSMatthew Knepley 
2385*ea844a1aSMatthew Knepley   Level: advanced
2386*ea844a1aSMatthew Knepley 
2387*ea844a1aSMatthew Knepley .seealso: PetscSFCreate()
2388*ea844a1aSMatthew Knepley @*/
2389*ea844a1aSMatthew Knepley PetscErrorCode PetscSFDistributeSection(PetscSF sf, PetscSection rootSection, PetscInt **remoteOffsets, PetscSection leafSection)
2390*ea844a1aSMatthew Knepley {
2391*ea844a1aSMatthew Knepley   PetscSF        embedSF;
2392*ea844a1aSMatthew Knepley   const PetscInt *indices;
2393*ea844a1aSMatthew Knepley   IS             selected;
2394*ea844a1aSMatthew Knepley   PetscInt       numFields, nroots, rpStart, rpEnd, lpStart = PETSC_MAX_INT, lpEnd = -1, f;
2395*ea844a1aSMatthew Knepley   PetscBool      sub,lsub;
2396*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2397*ea844a1aSMatthew Knepley 
2398*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2399*ea844a1aSMatthew Knepley   ierr = PetscLogEventBegin(PETSCSF_DistSect,sf,0,0,0);CHKERRQ(ierr);
2400*ea844a1aSMatthew Knepley   ierr = PetscSectionGetNumFields(rootSection, &numFields);CHKERRQ(ierr);
2401*ea844a1aSMatthew Knepley   if (numFields) {ierr = PetscSectionSetNumFields(leafSection, numFields);CHKERRQ(ierr);}
2402*ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
2403*ea844a1aSMatthew Knepley     PetscInt numComp = 0;
2404*ea844a1aSMatthew Knepley     ierr = PetscSectionGetFieldComponents(rootSection, f, &numComp);CHKERRQ(ierr);
2405*ea844a1aSMatthew Knepley     ierr = PetscSectionSetFieldComponents(leafSection, f, numComp);CHKERRQ(ierr);
2406*ea844a1aSMatthew Knepley   }
2407*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(rootSection, &rpStart, &rpEnd);CHKERRQ(ierr);
2408*ea844a1aSMatthew Knepley   ierr = PetscSFGetGraph(sf,&nroots,NULL,NULL,NULL);CHKERRQ(ierr);
2409*ea844a1aSMatthew Knepley   rpEnd = PetscMin(rpEnd,nroots);
2410*ea844a1aSMatthew Knepley   rpEnd = PetscMax(rpStart,rpEnd);
2411*ea844a1aSMatthew Knepley   /* see if we can avoid creating the embedded SF, since it can cost more than an allreduce */
2412*ea844a1aSMatthew Knepley   lsub = (PetscBool)(nroots != rpEnd - rpStart);
2413*ea844a1aSMatthew Knepley   ierr = MPIU_Allreduce(&lsub,&sub,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
2414*ea844a1aSMatthew Knepley   if (sub) {
2415*ea844a1aSMatthew Knepley     ierr = ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected);CHKERRQ(ierr);
2416*ea844a1aSMatthew Knepley     ierr = ISGetIndices(selected, &indices);CHKERRQ(ierr);
2417*ea844a1aSMatthew Knepley     ierr = PetscSFCreateEmbeddedSF(sf, rpEnd - rpStart, indices, &embedSF);CHKERRQ(ierr);
2418*ea844a1aSMatthew Knepley     ierr = ISRestoreIndices(selected, &indices);CHKERRQ(ierr);
2419*ea844a1aSMatthew Knepley     ierr = ISDestroy(&selected);CHKERRQ(ierr);
2420*ea844a1aSMatthew Knepley   } else {
2421*ea844a1aSMatthew Knepley     ierr = PetscObjectReference((PetscObject)sf);CHKERRQ(ierr);
2422*ea844a1aSMatthew Knepley     embedSF = sf;
2423*ea844a1aSMatthew Knepley   }
2424*ea844a1aSMatthew Knepley   ierr = PetscSFGetLeafRange(embedSF, &lpStart, &lpEnd);CHKERRQ(ierr);
2425*ea844a1aSMatthew Knepley   lpEnd++;
2426*ea844a1aSMatthew Knepley 
2427*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(leafSection, lpStart, lpEnd);CHKERRQ(ierr);
2428*ea844a1aSMatthew Knepley   /* Could fuse these at the cost of a copy and extra allocation */
2429*ea844a1aSMatthew Knepley   ierr = PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart]);CHKERRQ(ierr);
2430*ea844a1aSMatthew Knepley   ierr = PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasDof[-rpStart], &leafSection->atlasDof[-lpStart]);CHKERRQ(ierr);
2431*ea844a1aSMatthew Knepley   for (f = 0; f < numFields; ++f) {
2432*ea844a1aSMatthew Knepley     ierr = PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart]);CHKERRQ(ierr);
2433*ea844a1aSMatthew Knepley     ierr = PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->field[f]->atlasDof[-rpStart], &leafSection->field[f]->atlasDof[-lpStart]);CHKERRQ(ierr);
2434*ea844a1aSMatthew Knepley   }
2435*ea844a1aSMatthew Knepley   if (remoteOffsets) {
2436*ea844a1aSMatthew Knepley     ierr = PetscMalloc1(lpEnd - lpStart, remoteOffsets);CHKERRQ(ierr);
2437*ea844a1aSMatthew Knepley     ierr = PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);CHKERRQ(ierr);
2438*ea844a1aSMatthew Knepley     ierr = PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);CHKERRQ(ierr);
2439*ea844a1aSMatthew Knepley   }
2440*ea844a1aSMatthew Knepley   ierr = PetscSFDestroy(&embedSF);CHKERRQ(ierr);
2441*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUp(leafSection);CHKERRQ(ierr);
2442*ea844a1aSMatthew Knepley   ierr = PetscLogEventEnd(PETSCSF_DistSect,sf,0,0,0);CHKERRQ(ierr);
2443*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2444*ea844a1aSMatthew Knepley }
2445*ea844a1aSMatthew Knepley 
2446*ea844a1aSMatthew Knepley /*@C
2447*ea844a1aSMatthew Knepley   PetscSFCreateRemoteOffsets - Create offsets for point data on remote processes
2448*ea844a1aSMatthew Knepley 
2449*ea844a1aSMatthew Knepley   Collective on sf
2450*ea844a1aSMatthew Knepley 
2451*ea844a1aSMatthew Knepley   Input Parameters:
2452*ea844a1aSMatthew Knepley + sf          - The SF
2453*ea844a1aSMatthew Knepley . rootSection - Data layout of remote points for outgoing data (this is layout for SF roots)
2454*ea844a1aSMatthew Knepley - leafSection - Data layout of local points for incoming data  (this is layout for SF leaves)
2455*ea844a1aSMatthew Knepley 
2456*ea844a1aSMatthew Knepley   Output Parameter:
2457*ea844a1aSMatthew Knepley . remoteOffsets - Offsets for point data on remote processes (these are offsets from the root section), or NULL
2458*ea844a1aSMatthew Knepley 
2459*ea844a1aSMatthew Knepley   Level: developer
2460*ea844a1aSMatthew Knepley 
2461*ea844a1aSMatthew Knepley .seealso: PetscSFCreate()
2462*ea844a1aSMatthew Knepley @*/
2463*ea844a1aSMatthew Knepley PetscErrorCode PetscSFCreateRemoteOffsets(PetscSF sf, PetscSection rootSection, PetscSection leafSection, PetscInt **remoteOffsets)
2464*ea844a1aSMatthew Knepley {
2465*ea844a1aSMatthew Knepley   PetscSF         embedSF;
2466*ea844a1aSMatthew Knepley   const PetscInt *indices;
2467*ea844a1aSMatthew Knepley   IS              selected;
2468*ea844a1aSMatthew Knepley   PetscInt        numRoots, rpStart = 0, rpEnd = 0, lpStart = 0, lpEnd = 0;
2469*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
2470*ea844a1aSMatthew Knepley 
2471*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2472*ea844a1aSMatthew Knepley   *remoteOffsets = NULL;
2473*ea844a1aSMatthew Knepley   ierr = PetscSFGetGraph(sf, &numRoots, NULL, NULL, NULL);CHKERRQ(ierr);
2474*ea844a1aSMatthew Knepley   if (numRoots < 0) PetscFunctionReturn(0);
2475*ea844a1aSMatthew Knepley   ierr = PetscLogEventBegin(PETSCSF_RemoteOff,sf,0,0,0);CHKERRQ(ierr);
2476*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(rootSection, &rpStart, &rpEnd);CHKERRQ(ierr);
2477*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(leafSection, &lpStart, &lpEnd);CHKERRQ(ierr);
2478*ea844a1aSMatthew Knepley   ierr = ISCreateStride(PETSC_COMM_SELF, rpEnd - rpStart, rpStart, 1, &selected);CHKERRQ(ierr);
2479*ea844a1aSMatthew Knepley   ierr = ISGetIndices(selected, &indices);CHKERRQ(ierr);
2480*ea844a1aSMatthew Knepley   ierr = PetscSFCreateEmbeddedSF(sf, rpEnd - rpStart, indices, &embedSF);CHKERRQ(ierr);
2481*ea844a1aSMatthew Knepley   ierr = ISRestoreIndices(selected, &indices);CHKERRQ(ierr);
2482*ea844a1aSMatthew Knepley   ierr = ISDestroy(&selected);CHKERRQ(ierr);
2483*ea844a1aSMatthew Knepley   ierr = PetscCalloc1(lpEnd - lpStart, remoteOffsets);CHKERRQ(ierr);
2484*ea844a1aSMatthew Knepley   ierr = PetscSFBcastBegin(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);CHKERRQ(ierr);
2485*ea844a1aSMatthew Knepley   ierr = PetscSFBcastEnd(embedSF, MPIU_INT, &rootSection->atlasOff[-rpStart], &(*remoteOffsets)[-lpStart]);CHKERRQ(ierr);
2486*ea844a1aSMatthew Knepley   ierr = PetscSFDestroy(&embedSF);CHKERRQ(ierr);
2487*ea844a1aSMatthew Knepley   ierr = PetscLogEventEnd(PETSCSF_RemoteOff,sf,0,0,0);CHKERRQ(ierr);
2488*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2489*ea844a1aSMatthew Knepley }
2490*ea844a1aSMatthew Knepley 
2491*ea844a1aSMatthew Knepley /*@C
2492*ea844a1aSMatthew Knepley   PetscSFCreateSectionSF - Create an expanded SF of dofs, assuming the input SF relates points
2493*ea844a1aSMatthew Knepley 
2494*ea844a1aSMatthew Knepley   Collective on sf
2495*ea844a1aSMatthew Knepley 
2496*ea844a1aSMatthew Knepley   Input Parameters:
2497*ea844a1aSMatthew Knepley + sf - The SF
2498*ea844a1aSMatthew Knepley . rootSection - Data layout of remote points for outgoing data (this is usually the serial section)
2499*ea844a1aSMatthew Knepley . remoteOffsets - Offsets for point data on remote processes (these are offsets from the root section), or NULL
2500*ea844a1aSMatthew Knepley - leafSection - Data layout of local points for incoming data  (this is the distributed section)
2501*ea844a1aSMatthew Knepley 
2502*ea844a1aSMatthew Knepley   Output Parameters:
2503*ea844a1aSMatthew Knepley - sectionSF - The new SF
2504*ea844a1aSMatthew Knepley 
2505*ea844a1aSMatthew Knepley   Note: Either rootSection or remoteOffsets can be specified
2506*ea844a1aSMatthew Knepley 
2507*ea844a1aSMatthew Knepley   Level: advanced
2508*ea844a1aSMatthew Knepley 
2509*ea844a1aSMatthew Knepley .seealso: PetscSFCreate()
2510*ea844a1aSMatthew Knepley @*/
2511*ea844a1aSMatthew Knepley PetscErrorCode PetscSFCreateSectionSF(PetscSF sf, PetscSection rootSection, PetscInt remoteOffsets[], PetscSection leafSection, PetscSF *sectionSF)
2512*ea844a1aSMatthew Knepley {
2513*ea844a1aSMatthew Knepley   MPI_Comm          comm;
2514*ea844a1aSMatthew Knepley   const PetscInt    *localPoints;
2515*ea844a1aSMatthew Knepley   const PetscSFNode *remotePoints;
2516*ea844a1aSMatthew Knepley   PetscInt          lpStart, lpEnd;
2517*ea844a1aSMatthew Knepley   PetscInt          numRoots, numSectionRoots, numPoints, numIndices = 0;
2518*ea844a1aSMatthew Knepley   PetscInt          *localIndices;
2519*ea844a1aSMatthew Knepley   PetscSFNode       *remoteIndices;
2520*ea844a1aSMatthew Knepley   PetscInt          i, ind;
2521*ea844a1aSMatthew Knepley   PetscErrorCode    ierr;
2522*ea844a1aSMatthew Knepley 
2523*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2524*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
2525*ea844a1aSMatthew Knepley   PetscValidPointer(rootSection,2);
2526*ea844a1aSMatthew Knepley   /* Cannot check PetscValidIntPointer(remoteOffsets,3) because it can be NULL if sf does not reference any points in leafSection */
2527*ea844a1aSMatthew Knepley   PetscValidPointer(leafSection,4);
2528*ea844a1aSMatthew Knepley   PetscValidPointer(sectionSF,5);
2529*ea844a1aSMatthew Knepley   ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr);
2530*ea844a1aSMatthew Knepley   ierr = PetscSFCreate(comm, sectionSF);CHKERRQ(ierr);
2531*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(leafSection, &lpStart, &lpEnd);CHKERRQ(ierr);
2532*ea844a1aSMatthew Knepley   ierr = PetscSectionGetStorageSize(rootSection, &numSectionRoots);CHKERRQ(ierr);
2533*ea844a1aSMatthew Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numPoints, &localPoints, &remotePoints);CHKERRQ(ierr);
2534*ea844a1aSMatthew Knepley   if (numRoots < 0) PetscFunctionReturn(0);
2535*ea844a1aSMatthew Knepley   ierr = PetscLogEventBegin(PETSCSF_SectSF,sf,0,0,0);CHKERRQ(ierr);
2536*ea844a1aSMatthew Knepley   for (i = 0; i < numPoints; ++i) {
2537*ea844a1aSMatthew Knepley     PetscInt localPoint = localPoints ? localPoints[i] : i;
2538*ea844a1aSMatthew Knepley     PetscInt dof;
2539*ea844a1aSMatthew Knepley 
2540*ea844a1aSMatthew Knepley     if ((localPoint >= lpStart) && (localPoint < lpEnd)) {
2541*ea844a1aSMatthew Knepley       ierr = PetscSectionGetDof(leafSection, localPoint, &dof);CHKERRQ(ierr);
2542*ea844a1aSMatthew Knepley       numIndices += dof;
2543*ea844a1aSMatthew Knepley     }
2544*ea844a1aSMatthew Knepley   }
2545*ea844a1aSMatthew Knepley   ierr = PetscMalloc1(numIndices, &localIndices);CHKERRQ(ierr);
2546*ea844a1aSMatthew Knepley   ierr = PetscMalloc1(numIndices, &remoteIndices);CHKERRQ(ierr);
2547*ea844a1aSMatthew Knepley   /* Create new index graph */
2548*ea844a1aSMatthew Knepley   for (i = 0, ind = 0; i < numPoints; ++i) {
2549*ea844a1aSMatthew Knepley     PetscInt localPoint = localPoints ? localPoints[i] : i;
2550*ea844a1aSMatthew Knepley     PetscInt rank       = remotePoints[i].rank;
2551*ea844a1aSMatthew Knepley 
2552*ea844a1aSMatthew Knepley     if ((localPoint >= lpStart) && (localPoint < lpEnd)) {
2553*ea844a1aSMatthew Knepley       PetscInt remoteOffset = remoteOffsets[localPoint-lpStart];
2554*ea844a1aSMatthew Knepley       PetscInt loff, dof, d;
2555*ea844a1aSMatthew Knepley 
2556*ea844a1aSMatthew Knepley       ierr = PetscSectionGetOffset(leafSection, localPoint, &loff);CHKERRQ(ierr);
2557*ea844a1aSMatthew Knepley       ierr = PetscSectionGetDof(leafSection, localPoint, &dof);CHKERRQ(ierr);
2558*ea844a1aSMatthew Knepley       for (d = 0; d < dof; ++d, ++ind) {
2559*ea844a1aSMatthew Knepley         localIndices[ind]        = loff+d;
2560*ea844a1aSMatthew Knepley         remoteIndices[ind].rank  = rank;
2561*ea844a1aSMatthew Knepley         remoteIndices[ind].index = remoteOffset+d;
2562*ea844a1aSMatthew Knepley       }
2563*ea844a1aSMatthew Knepley     }
2564*ea844a1aSMatthew Knepley   }
2565*ea844a1aSMatthew Knepley   if (numIndices != ind) SETERRQ2(comm, PETSC_ERR_PLIB, "Inconsistency in indices, %D should be %D", ind, numIndices);
2566*ea844a1aSMatthew Knepley   ierr = PetscSFSetGraph(*sectionSF, numSectionRoots, numIndices, localIndices, PETSC_OWN_POINTER, remoteIndices, PETSC_OWN_POINTER);CHKERRQ(ierr);
2567*ea844a1aSMatthew Knepley   ierr = PetscSFSetUp(*sectionSF);CHKERRQ(ierr);
2568*ea844a1aSMatthew Knepley   ierr = PetscLogEventEnd(PETSCSF_SectSF,sf,0,0,0);CHKERRQ(ierr);
2569*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2570*ea844a1aSMatthew Knepley }
2571*ea844a1aSMatthew Knepley 
2572*ea844a1aSMatthew Knepley /*@
2573*ea844a1aSMatthew Knepley   PetscSectionSetClosureIndex - Set a cache of points in the closure of each point in the section
2574*ea844a1aSMatthew Knepley 
2575*ea844a1aSMatthew Knepley   Collective on section
2576*ea844a1aSMatthew Knepley 
2577*ea844a1aSMatthew Knepley   Input Parameters:
2578*ea844a1aSMatthew Knepley + section   - The PetscSection
2579*ea844a1aSMatthew Knepley . obj       - A PetscObject which serves as the key for this index
2580*ea844a1aSMatthew Knepley . clSection - Section giving the size of the closure of each point
2581*ea844a1aSMatthew Knepley - clPoints  - IS giving the points in each closure
2582*ea844a1aSMatthew Knepley 
2583*ea844a1aSMatthew Knepley   Note: We compress out closure points with no dofs in this section
2584*ea844a1aSMatthew Knepley 
2585*ea844a1aSMatthew Knepley   Level: advanced
2586*ea844a1aSMatthew Knepley 
2587*ea844a1aSMatthew Knepley .seealso: PetscSectionGetClosureIndex(), DMPlexCreateClosureIndex()
2588*ea844a1aSMatthew Knepley @*/
2589*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetClosureIndex(PetscSection section, PetscObject obj, PetscSection clSection, IS clPoints)
2590*ea844a1aSMatthew Knepley {
2591*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2592*ea844a1aSMatthew Knepley 
2593*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2594*ea844a1aSMatthew Knepley   if (section->clObj != obj) {ierr = PetscFree(section->clPerm);CHKERRQ(ierr);ierr = PetscFree(section->clInvPerm);CHKERRQ(ierr);}
2595*ea844a1aSMatthew Knepley   section->clObj     = obj;
2596*ea844a1aSMatthew Knepley   ierr = PetscSectionDestroy(&section->clSection);CHKERRQ(ierr);
2597*ea844a1aSMatthew Knepley   ierr = ISDestroy(&section->clPoints);CHKERRQ(ierr);
2598*ea844a1aSMatthew Knepley   section->clSection = clSection;
2599*ea844a1aSMatthew Knepley   section->clPoints  = clPoints;
2600*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2601*ea844a1aSMatthew Knepley }
2602*ea844a1aSMatthew Knepley 
2603*ea844a1aSMatthew Knepley /*@
2604*ea844a1aSMatthew Knepley   PetscSectionGetClosureIndex - Get the cache of points in the closure of each point in the section
2605*ea844a1aSMatthew Knepley 
2606*ea844a1aSMatthew Knepley   Collective on section
2607*ea844a1aSMatthew Knepley 
2608*ea844a1aSMatthew Knepley   Input Parameters:
2609*ea844a1aSMatthew Knepley + section   - The PetscSection
2610*ea844a1aSMatthew Knepley - obj       - A PetscObject which serves as the key for this index
2611*ea844a1aSMatthew Knepley 
2612*ea844a1aSMatthew Knepley   Output Parameters:
2613*ea844a1aSMatthew Knepley + clSection - Section giving the size of the closure of each point
2614*ea844a1aSMatthew Knepley - clPoints  - IS giving the points in each closure
2615*ea844a1aSMatthew Knepley 
2616*ea844a1aSMatthew Knepley   Note: We compress out closure points with no dofs in this section
2617*ea844a1aSMatthew Knepley 
2618*ea844a1aSMatthew Knepley   Level: advanced
2619*ea844a1aSMatthew Knepley 
2620*ea844a1aSMatthew Knepley .seealso: PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex()
2621*ea844a1aSMatthew Knepley @*/
2622*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetClosureIndex(PetscSection section, PetscObject obj, PetscSection *clSection, IS *clPoints)
2623*ea844a1aSMatthew Knepley {
2624*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2625*ea844a1aSMatthew Knepley   if (section->clObj == obj) {
2626*ea844a1aSMatthew Knepley     if (clSection) *clSection = section->clSection;
2627*ea844a1aSMatthew Knepley     if (clPoints)  *clPoints  = section->clPoints;
2628*ea844a1aSMatthew Knepley   } else {
2629*ea844a1aSMatthew Knepley     if (clSection) *clSection = NULL;
2630*ea844a1aSMatthew Knepley     if (clPoints)  *clPoints  = NULL;
2631*ea844a1aSMatthew Knepley   }
2632*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2633*ea844a1aSMatthew Knepley }
2634*ea844a1aSMatthew Knepley 
2635*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt clSize, PetscCopyMode mode, PetscInt *clPerm)
2636*ea844a1aSMatthew Knepley {
2637*ea844a1aSMatthew Knepley   PetscInt       i;
2638*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2639*ea844a1aSMatthew Knepley 
2640*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2641*ea844a1aSMatthew Knepley   if (section->clObj != obj) {
2642*ea844a1aSMatthew Knepley     ierr = PetscSectionDestroy(&section->clSection);CHKERRQ(ierr);
2643*ea844a1aSMatthew Knepley     ierr = ISDestroy(&section->clPoints);CHKERRQ(ierr);
2644*ea844a1aSMatthew Knepley   }
2645*ea844a1aSMatthew Knepley   section->clObj  = obj;
2646*ea844a1aSMatthew Knepley   ierr = PetscFree(section->clPerm);CHKERRQ(ierr);
2647*ea844a1aSMatthew Knepley   ierr = PetscFree(section->clInvPerm);CHKERRQ(ierr);
2648*ea844a1aSMatthew Knepley   section->clSize = clSize;
2649*ea844a1aSMatthew Knepley   if (mode == PETSC_COPY_VALUES) {
2650*ea844a1aSMatthew Knepley     ierr = PetscMalloc1(clSize, &section->clPerm);CHKERRQ(ierr);
2651*ea844a1aSMatthew Knepley     ierr = PetscLogObjectMemory((PetscObject) obj, clSize*sizeof(PetscInt));CHKERRQ(ierr);
2652*ea844a1aSMatthew Knepley     ierr = PetscArraycpy(section->clPerm, clPerm, clSize);CHKERRQ(ierr);
2653*ea844a1aSMatthew Knepley   } else if (mode == PETSC_OWN_POINTER) {
2654*ea844a1aSMatthew Knepley     section->clPerm = clPerm;
2655*ea844a1aSMatthew Knepley   } else SETERRQ(PetscObjectComm(obj), PETSC_ERR_SUP, "Do not support borrowed arrays");
2656*ea844a1aSMatthew Knepley   ierr = PetscMalloc1(clSize, &section->clInvPerm);CHKERRQ(ierr);
2657*ea844a1aSMatthew Knepley   for (i = 0; i < clSize; ++i) section->clInvPerm[section->clPerm[i]] = i;
2658*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2659*ea844a1aSMatthew Knepley }
2660*ea844a1aSMatthew Knepley 
2661*ea844a1aSMatthew Knepley /*@
2662*ea844a1aSMatthew Knepley   PetscSectionSetClosurePermutation - Get the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex.
2663*ea844a1aSMatthew Knepley 
2664*ea844a1aSMatthew Knepley   Not Collective
2665*ea844a1aSMatthew Knepley 
2666*ea844a1aSMatthew Knepley   Input Parameters:
2667*ea844a1aSMatthew Knepley + section - The PetscSection
2668*ea844a1aSMatthew Knepley . obj     - A PetscObject which serves as the key for this index
2669*ea844a1aSMatthew Knepley - perm    - Permutation of the cell dof closure
2670*ea844a1aSMatthew Knepley 
2671*ea844a1aSMatthew Knepley   Note: This strategy only works when all cells have the same size dof closure, and no closures are retrieved for
2672*ea844a1aSMatthew Knepley   other points (like faces).
2673*ea844a1aSMatthew Knepley 
2674*ea844a1aSMatthew Knepley   Level: intermediate
2675*ea844a1aSMatthew Knepley 
2676*ea844a1aSMatthew Knepley .seealso: PetscSectionGetClosurePermutation(), PetscSectionGetClosureIndex(), DMPlexCreateClosureIndex(), PetscCopyMode
2677*ea844a1aSMatthew Knepley @*/
2678*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetClosurePermutation(PetscSection section, PetscObject obj, IS perm)
2679*ea844a1aSMatthew Knepley {
2680*ea844a1aSMatthew Knepley   const PetscInt *clPerm = NULL;
2681*ea844a1aSMatthew Knepley   PetscInt        clSize = 0;
2682*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
2683*ea844a1aSMatthew Knepley 
2684*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2685*ea844a1aSMatthew Knepley   if (perm) {
2686*ea844a1aSMatthew Knepley     ierr = ISGetLocalSize(perm, &clSize);CHKERRQ(ierr);
2687*ea844a1aSMatthew Knepley     ierr = ISGetIndices(perm, &clPerm);CHKERRQ(ierr);
2688*ea844a1aSMatthew Knepley   }
2689*ea844a1aSMatthew Knepley   ierr = PetscSectionSetClosurePermutation_Internal(section, obj, clSize, PETSC_COPY_VALUES, (PetscInt *) clPerm);CHKERRQ(ierr);
2690*ea844a1aSMatthew Knepley   if (perm) {ierr = ISRestoreIndices(perm, &clPerm);CHKERRQ(ierr);}
2691*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2692*ea844a1aSMatthew Knepley }
2693*ea844a1aSMatthew Knepley 
2694*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetClosurePermutation_Internal(PetscSection section, PetscObject obj, PetscInt *size, const PetscInt *perm[])
2695*ea844a1aSMatthew Knepley {
2696*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2697*ea844a1aSMatthew Knepley   if (section->clObj == obj) {
2698*ea844a1aSMatthew Knepley     if (size) *size = section->clSize;
2699*ea844a1aSMatthew Knepley     if (perm) *perm = section->clPerm;
2700*ea844a1aSMatthew Knepley   } else {
2701*ea844a1aSMatthew Knepley     if (size) *size = 0;
2702*ea844a1aSMatthew Knepley     if (perm) *perm = NULL;
2703*ea844a1aSMatthew Knepley   }
2704*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2705*ea844a1aSMatthew Knepley }
2706*ea844a1aSMatthew Knepley 
2707*ea844a1aSMatthew Knepley /*@
2708*ea844a1aSMatthew Knepley   PetscSectionGetClosurePermutation - Get the dof permutation for the closure of each cell in the section, meaning clPerm[newIndex] = oldIndex.
2709*ea844a1aSMatthew Knepley 
2710*ea844a1aSMatthew Knepley   Not collective
2711*ea844a1aSMatthew Knepley 
2712*ea844a1aSMatthew Knepley   Input Parameters:
2713*ea844a1aSMatthew Knepley + section   - The PetscSection
2714*ea844a1aSMatthew Knepley - obj       - A PetscObject which serves as the key for this index
2715*ea844a1aSMatthew Knepley 
2716*ea844a1aSMatthew Knepley   Output Parameter:
2717*ea844a1aSMatthew Knepley . perm - The dof closure permutation
2718*ea844a1aSMatthew Knepley 
2719*ea844a1aSMatthew Knepley   Note: This strategy only works when all cells have the same size dof closure, and no closures are retrieved for
2720*ea844a1aSMatthew Knepley   other points (like faces).
2721*ea844a1aSMatthew Knepley 
2722*ea844a1aSMatthew Knepley   The user must destroy the IS that is returned.
2723*ea844a1aSMatthew Knepley 
2724*ea844a1aSMatthew Knepley   Level: intermediate
2725*ea844a1aSMatthew Knepley 
2726*ea844a1aSMatthew Knepley .seealso: PetscSectionSetClosurePermutation(), PetscSectionGetClosureInversePermutation(), PetscSectionGetClosureIndex(), PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex()
2727*ea844a1aSMatthew Knepley @*/
2728*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetClosurePermutation(PetscSection section, PetscObject obj, IS *perm)
2729*ea844a1aSMatthew Knepley {
2730*ea844a1aSMatthew Knepley   const PetscInt *clPerm;
2731*ea844a1aSMatthew Knepley   PetscInt        clSize;
2732*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
2733*ea844a1aSMatthew Knepley 
2734*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2735*ea844a1aSMatthew Knepley   ierr = PetscSectionGetClosurePermutation_Internal(section, obj, &clSize, &clPerm);CHKERRQ(ierr);
2736*ea844a1aSMatthew Knepley   ierr = ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm);CHKERRQ(ierr);
2737*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2738*ea844a1aSMatthew Knepley }
2739*ea844a1aSMatthew Knepley 
2740*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetClosureInversePermutation_Internal(PetscSection section, PetscObject obj, PetscInt *size, const PetscInt *perm[])
2741*ea844a1aSMatthew Knepley {
2742*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2743*ea844a1aSMatthew Knepley   if (section->clObj == obj) {
2744*ea844a1aSMatthew Knepley     if (size) *size = section->clSize;
2745*ea844a1aSMatthew Knepley     if (perm) *perm = section->clInvPerm;
2746*ea844a1aSMatthew Knepley   } else {
2747*ea844a1aSMatthew Knepley     if (size) *size = 0;
2748*ea844a1aSMatthew Knepley     if (perm) *perm = NULL;
2749*ea844a1aSMatthew Knepley   }
2750*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2751*ea844a1aSMatthew Knepley }
2752*ea844a1aSMatthew Knepley 
2753*ea844a1aSMatthew Knepley /*@
2754*ea844a1aSMatthew Knepley   PetscSectionGetClosureInversePermutation - Get the inverse dof permutation for the closure of each cell in the section, meaning clPerm[oldIndex] = newIndex.
2755*ea844a1aSMatthew Knepley 
2756*ea844a1aSMatthew Knepley   Not collective
2757*ea844a1aSMatthew Knepley 
2758*ea844a1aSMatthew Knepley   Input Parameters:
2759*ea844a1aSMatthew Knepley + section   - The PetscSection
2760*ea844a1aSMatthew Knepley - obj       - A PetscObject which serves as the key for this index
2761*ea844a1aSMatthew Knepley 
2762*ea844a1aSMatthew Knepley   Output Parameters:
2763*ea844a1aSMatthew Knepley + size - The dof closure size
2764*ea844a1aSMatthew Knepley - perm - The dof closure permutation
2765*ea844a1aSMatthew Knepley 
2766*ea844a1aSMatthew Knepley   Note: This strategy only works when all cells have the same size dof closure, and no closures are retrieved for
2767*ea844a1aSMatthew Knepley   other points (like faces).
2768*ea844a1aSMatthew Knepley 
2769*ea844a1aSMatthew Knepley   The user must destroy the IS that is returned.
2770*ea844a1aSMatthew Knepley 
2771*ea844a1aSMatthew Knepley   Level: intermediate
2772*ea844a1aSMatthew Knepley 
2773*ea844a1aSMatthew Knepley .seealso: PetscSectionSetClosurePermutation(), PetscSectionGetClosureIndex(), PetscSectionSetClosureIndex(), DMPlexCreateClosureIndex()
2774*ea844a1aSMatthew Knepley @*/
2775*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetClosureInversePermutation(PetscSection section, PetscObject obj, IS *perm)
2776*ea844a1aSMatthew Knepley {
2777*ea844a1aSMatthew Knepley   const PetscInt *clPerm;
2778*ea844a1aSMatthew Knepley   PetscInt        clSize;
2779*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
2780*ea844a1aSMatthew Knepley 
2781*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2782*ea844a1aSMatthew Knepley   ierr = PetscSectionGetClosureInversePermutation_Internal(section, obj, &clSize, &clPerm);CHKERRQ(ierr);
2783*ea844a1aSMatthew Knepley   ierr = ISCreateGeneral(PETSC_COMM_SELF, clSize, clPerm, PETSC_USE_POINTER, perm);CHKERRQ(ierr);
2784*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2785*ea844a1aSMatthew Knepley }
2786*ea844a1aSMatthew Knepley 
2787*ea844a1aSMatthew Knepley /*@
2788*ea844a1aSMatthew Knepley   PetscSectionGetField - Get the subsection associated with a single field
2789*ea844a1aSMatthew Knepley 
2790*ea844a1aSMatthew Knepley   Input Parameters:
2791*ea844a1aSMatthew Knepley + s     - The PetscSection
2792*ea844a1aSMatthew Knepley - field - The field number
2793*ea844a1aSMatthew Knepley 
2794*ea844a1aSMatthew Knepley   Output Parameter:
2795*ea844a1aSMatthew Knepley . subs  - The subsection for the given field
2796*ea844a1aSMatthew Knepley 
2797*ea844a1aSMatthew Knepley   Level: intermediate
2798*ea844a1aSMatthew Knepley 
2799*ea844a1aSMatthew Knepley .seealso: PetscSectionSetNumFields()
2800*ea844a1aSMatthew Knepley @*/
2801*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetField(PetscSection s, PetscInt field, PetscSection *subs)
2802*ea844a1aSMatthew Knepley {
2803*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2804*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s,PETSC_SECTION_CLASSID,1);
2805*ea844a1aSMatthew Knepley   PetscValidPointer(subs,3);
2806*ea844a1aSMatthew Knepley   if ((field < 0) || (field >= s->numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %D should be in [%D, %D)", field, 0, s->numFields);
2807*ea844a1aSMatthew Knepley   *subs = s->field[field];
2808*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2809*ea844a1aSMatthew Knepley }
2810*ea844a1aSMatthew Knepley 
2811*ea844a1aSMatthew Knepley PetscClassId      PETSC_SECTION_SYM_CLASSID;
2812*ea844a1aSMatthew Knepley PetscFunctionList PetscSectionSymList = NULL;
2813*ea844a1aSMatthew Knepley 
2814*ea844a1aSMatthew Knepley /*@
2815*ea844a1aSMatthew Knepley   PetscSectionSymCreate - Creates an empty PetscSectionSym object.
2816*ea844a1aSMatthew Knepley 
2817*ea844a1aSMatthew Knepley   Collective
2818*ea844a1aSMatthew Knepley 
2819*ea844a1aSMatthew Knepley   Input Parameter:
2820*ea844a1aSMatthew Knepley . comm - the MPI communicator
2821*ea844a1aSMatthew Knepley 
2822*ea844a1aSMatthew Knepley   Output Parameter:
2823*ea844a1aSMatthew Knepley . sym - pointer to the new set of symmetries
2824*ea844a1aSMatthew Knepley 
2825*ea844a1aSMatthew Knepley   Level: developer
2826*ea844a1aSMatthew Knepley 
2827*ea844a1aSMatthew Knepley .seealso: PetscSectionSym, PetscSectionSymDestroy()
2828*ea844a1aSMatthew Knepley @*/
2829*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSymCreate(MPI_Comm comm, PetscSectionSym *sym)
2830*ea844a1aSMatthew Knepley {
2831*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2832*ea844a1aSMatthew Knepley 
2833*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2834*ea844a1aSMatthew Knepley   PetscValidPointer(sym,2);
2835*ea844a1aSMatthew Knepley   ierr = ISInitializePackage();CHKERRQ(ierr);
2836*ea844a1aSMatthew Knepley   ierr = PetscHeaderCreate(*sym,PETSC_SECTION_SYM_CLASSID,"PetscSectionSym","Section Symmetry","IS",comm,PetscSectionSymDestroy,PetscSectionSymView);CHKERRQ(ierr);
2837*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2838*ea844a1aSMatthew Knepley }
2839*ea844a1aSMatthew Knepley 
2840*ea844a1aSMatthew Knepley /*@C
2841*ea844a1aSMatthew Knepley   PetscSectionSymSetType - Builds a PetscSection symmetry, for a particular implementation.
2842*ea844a1aSMatthew Knepley 
2843*ea844a1aSMatthew Knepley   Collective on PetscSectionSym
2844*ea844a1aSMatthew Knepley 
2845*ea844a1aSMatthew Knepley   Input Parameters:
2846*ea844a1aSMatthew Knepley + sym    - The section symmetry object
2847*ea844a1aSMatthew Knepley - method - The name of the section symmetry type
2848*ea844a1aSMatthew Knepley 
2849*ea844a1aSMatthew Knepley   Level: developer
2850*ea844a1aSMatthew Knepley 
2851*ea844a1aSMatthew Knepley .seealso: PetscSectionSymGetType(), PetscSectionSymCreate()
2852*ea844a1aSMatthew Knepley @*/
2853*ea844a1aSMatthew Knepley PetscErrorCode  PetscSectionSymSetType(PetscSectionSym sym, PetscSectionSymType method)
2854*ea844a1aSMatthew Knepley {
2855*ea844a1aSMatthew Knepley   PetscErrorCode (*r)(PetscSectionSym);
2856*ea844a1aSMatthew Knepley   PetscBool      match;
2857*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2858*ea844a1aSMatthew Knepley 
2859*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2860*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID,1);
2861*ea844a1aSMatthew Knepley   ierr = PetscObjectTypeCompare((PetscObject) sym, method, &match);CHKERRQ(ierr);
2862*ea844a1aSMatthew Knepley   if (match) PetscFunctionReturn(0);
2863*ea844a1aSMatthew Knepley 
2864*ea844a1aSMatthew Knepley   ierr = PetscFunctionListFind(PetscSectionSymList,method,&r);CHKERRQ(ierr);
2865*ea844a1aSMatthew Knepley   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscSectionSym type: %s", method);
2866*ea844a1aSMatthew Knepley   if (sym->ops->destroy) {
2867*ea844a1aSMatthew Knepley     ierr = (*sym->ops->destroy)(sym);CHKERRQ(ierr);
2868*ea844a1aSMatthew Knepley     sym->ops->destroy = NULL;
2869*ea844a1aSMatthew Knepley   }
2870*ea844a1aSMatthew Knepley   ierr = (*r)(sym);CHKERRQ(ierr);
2871*ea844a1aSMatthew Knepley   ierr = PetscObjectChangeTypeName((PetscObject)sym,method);CHKERRQ(ierr);
2872*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2873*ea844a1aSMatthew Knepley }
2874*ea844a1aSMatthew Knepley 
2875*ea844a1aSMatthew Knepley 
2876*ea844a1aSMatthew Knepley /*@C
2877*ea844a1aSMatthew Knepley   PetscSectionSymGetType - Gets the section symmetry type name (as a string) from the PetscSectionSym.
2878*ea844a1aSMatthew Knepley 
2879*ea844a1aSMatthew Knepley   Not Collective
2880*ea844a1aSMatthew Knepley 
2881*ea844a1aSMatthew Knepley   Input Parameter:
2882*ea844a1aSMatthew Knepley . sym  - The section symmetry
2883*ea844a1aSMatthew Knepley 
2884*ea844a1aSMatthew Knepley   Output Parameter:
2885*ea844a1aSMatthew Knepley . type - The index set type name
2886*ea844a1aSMatthew Knepley 
2887*ea844a1aSMatthew Knepley   Level: developer
2888*ea844a1aSMatthew Knepley 
2889*ea844a1aSMatthew Knepley .seealso: PetscSectionSymSetType(), PetscSectionSymCreate()
2890*ea844a1aSMatthew Knepley @*/
2891*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSymGetType(PetscSectionSym sym, PetscSectionSymType *type)
2892*ea844a1aSMatthew Knepley {
2893*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2894*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sym, PETSC_SECTION_SYM_CLASSID,1);
2895*ea844a1aSMatthew Knepley   PetscValidCharPointer(type,2);
2896*ea844a1aSMatthew Knepley   *type = ((PetscObject)sym)->type_name;
2897*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2898*ea844a1aSMatthew Knepley }
2899*ea844a1aSMatthew Knepley 
2900*ea844a1aSMatthew Knepley /*@C
2901*ea844a1aSMatthew Knepley   PetscSectionSymRegister - Adds a new section symmetry implementation
2902*ea844a1aSMatthew Knepley 
2903*ea844a1aSMatthew Knepley   Not Collective
2904*ea844a1aSMatthew Knepley 
2905*ea844a1aSMatthew Knepley   Input Parameters:
2906*ea844a1aSMatthew Knepley + name        - The name of a new user-defined creation routine
2907*ea844a1aSMatthew Knepley - create_func - The creation routine itself
2908*ea844a1aSMatthew Knepley 
2909*ea844a1aSMatthew Knepley   Notes:
2910*ea844a1aSMatthew Knepley   PetscSectionSymRegister() may be called multiple times to add several user-defined vectors
2911*ea844a1aSMatthew Knepley 
2912*ea844a1aSMatthew Knepley   Level: developer
2913*ea844a1aSMatthew Knepley 
2914*ea844a1aSMatthew Knepley .seealso: PetscSectionSymCreate(), PetscSectionSymSetType()
2915*ea844a1aSMatthew Knepley @*/
2916*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSymRegister(const char sname[], PetscErrorCode (*function)(PetscSectionSym))
2917*ea844a1aSMatthew Knepley {
2918*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2919*ea844a1aSMatthew Knepley 
2920*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2921*ea844a1aSMatthew Knepley   ierr = ISInitializePackage();CHKERRQ(ierr);
2922*ea844a1aSMatthew Knepley   ierr = PetscFunctionListAdd(&PetscSectionSymList,sname,function);CHKERRQ(ierr);
2923*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2924*ea844a1aSMatthew Knepley }
2925*ea844a1aSMatthew Knepley 
2926*ea844a1aSMatthew Knepley /*@
2927*ea844a1aSMatthew Knepley    PetscSectionSymDestroy - Destroys a section symmetry.
2928*ea844a1aSMatthew Knepley 
2929*ea844a1aSMatthew Knepley    Collective on PetscSectionSym
2930*ea844a1aSMatthew Knepley 
2931*ea844a1aSMatthew Knepley    Input Parameters:
2932*ea844a1aSMatthew Knepley .  sym - the section symmetry
2933*ea844a1aSMatthew Knepley 
2934*ea844a1aSMatthew Knepley    Level: developer
2935*ea844a1aSMatthew Knepley 
2936*ea844a1aSMatthew Knepley .seealso: PetscSectionSymCreate(), PetscSectionSymDestroy()
2937*ea844a1aSMatthew Knepley @*/
2938*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSymDestroy(PetscSectionSym *sym)
2939*ea844a1aSMatthew Knepley {
2940*ea844a1aSMatthew Knepley   SymWorkLink    link,next;
2941*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2942*ea844a1aSMatthew Knepley 
2943*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2944*ea844a1aSMatthew Knepley   if (!*sym) PetscFunctionReturn(0);
2945*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific((*sym),PETSC_SECTION_SYM_CLASSID,1);
2946*ea844a1aSMatthew Knepley   if (--((PetscObject)(*sym))->refct > 0) {*sym = 0; PetscFunctionReturn(0);}
2947*ea844a1aSMatthew Knepley   if ((*sym)->ops->destroy) {
2948*ea844a1aSMatthew Knepley     ierr = (*(*sym)->ops->destroy)(*sym);CHKERRQ(ierr);
2949*ea844a1aSMatthew Knepley   }
2950*ea844a1aSMatthew Knepley   if ((*sym)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
2951*ea844a1aSMatthew Knepley   for (link=(*sym)->workin; link; link=next) {
2952*ea844a1aSMatthew Knepley     next = link->next;
2953*ea844a1aSMatthew Knepley     ierr = PetscFree2(*(PetscInt***)&link->perms,*(PetscScalar***)&link->rots);CHKERRQ(ierr);
2954*ea844a1aSMatthew Knepley     ierr = PetscFree(link);CHKERRQ(ierr);
2955*ea844a1aSMatthew Knepley   }
2956*ea844a1aSMatthew Knepley   (*sym)->workin = NULL;
2957*ea844a1aSMatthew Knepley   ierr = PetscHeaderDestroy(sym);CHKERRQ(ierr);
2958*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2959*ea844a1aSMatthew Knepley }
2960*ea844a1aSMatthew Knepley 
2961*ea844a1aSMatthew Knepley /*@C
2962*ea844a1aSMatthew Knepley    PetscSectionSymView - Displays a section symmetry
2963*ea844a1aSMatthew Knepley 
2964*ea844a1aSMatthew Knepley    Collective on PetscSectionSym
2965*ea844a1aSMatthew Knepley 
2966*ea844a1aSMatthew Knepley    Input Parameters:
2967*ea844a1aSMatthew Knepley +  sym - the index set
2968*ea844a1aSMatthew Knepley -  viewer - viewer used to display the set, for example PETSC_VIEWER_STDOUT_SELF.
2969*ea844a1aSMatthew Knepley 
2970*ea844a1aSMatthew Knepley    Level: developer
2971*ea844a1aSMatthew Knepley 
2972*ea844a1aSMatthew Knepley .seealso: PetscViewerASCIIOpen()
2973*ea844a1aSMatthew Knepley @*/
2974*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSymView(PetscSectionSym sym,PetscViewer viewer)
2975*ea844a1aSMatthew Knepley {
2976*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
2977*ea844a1aSMatthew Knepley 
2978*ea844a1aSMatthew Knepley   PetscFunctionBegin;
2979*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,1);
2980*ea844a1aSMatthew Knepley   if (!viewer) {
2981*ea844a1aSMatthew Knepley     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sym),&viewer);CHKERRQ(ierr);
2982*ea844a1aSMatthew Knepley   }
2983*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2984*ea844a1aSMatthew Knepley   PetscCheckSameComm(sym,1,viewer,2);
2985*ea844a1aSMatthew Knepley   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)sym,viewer);CHKERRQ(ierr);
2986*ea844a1aSMatthew Knepley   if (sym->ops->view) {
2987*ea844a1aSMatthew Knepley     ierr = (*sym->ops->view)(sym,viewer);CHKERRQ(ierr);
2988*ea844a1aSMatthew Knepley   }
2989*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
2990*ea844a1aSMatthew Knepley }
2991*ea844a1aSMatthew Knepley 
2992*ea844a1aSMatthew Knepley /*@
2993*ea844a1aSMatthew Knepley   PetscSectionSetSym - Set the symmetries for the data referred to by the section
2994*ea844a1aSMatthew Knepley 
2995*ea844a1aSMatthew Knepley   Collective on PetscSection
2996*ea844a1aSMatthew Knepley 
2997*ea844a1aSMatthew Knepley   Input Parameters:
2998*ea844a1aSMatthew Knepley + section - the section describing data layout
2999*ea844a1aSMatthew Knepley - sym - the symmetry describing the affect of orientation on the access of the data
3000*ea844a1aSMatthew Knepley 
3001*ea844a1aSMatthew Knepley   Level: developer
3002*ea844a1aSMatthew Knepley 
3003*ea844a1aSMatthew Knepley .seealso: PetscSectionGetSym(), PetscSectionSymCreate()
3004*ea844a1aSMatthew Knepley @*/
3005*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetSym(PetscSection section, PetscSectionSym sym)
3006*ea844a1aSMatthew Knepley {
3007*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
3008*ea844a1aSMatthew Knepley 
3009*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3010*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3011*ea844a1aSMatthew Knepley   ierr = PetscSectionSymDestroy(&(section->sym));CHKERRQ(ierr);
3012*ea844a1aSMatthew Knepley   if (sym) {
3013*ea844a1aSMatthew Knepley     PetscValidHeaderSpecific(sym,PETSC_SECTION_SYM_CLASSID,2);
3014*ea844a1aSMatthew Knepley     PetscCheckSameComm(section,1,sym,2);
3015*ea844a1aSMatthew Knepley     ierr = PetscObjectReference((PetscObject) sym);CHKERRQ(ierr);
3016*ea844a1aSMatthew Knepley   }
3017*ea844a1aSMatthew Knepley   section->sym = sym;
3018*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3019*ea844a1aSMatthew Knepley }
3020*ea844a1aSMatthew Knepley 
3021*ea844a1aSMatthew Knepley /*@
3022*ea844a1aSMatthew Knepley   PetscSectionGetSym - Get the symmetries for the data referred to by the section
3023*ea844a1aSMatthew Knepley 
3024*ea844a1aSMatthew Knepley   Not collective
3025*ea844a1aSMatthew Knepley 
3026*ea844a1aSMatthew Knepley   Input Parameters:
3027*ea844a1aSMatthew Knepley . section - the section describing data layout
3028*ea844a1aSMatthew Knepley 
3029*ea844a1aSMatthew Knepley   Output Parameters:
3030*ea844a1aSMatthew Knepley . sym - the symmetry describing the affect of orientation on the access of the data
3031*ea844a1aSMatthew Knepley 
3032*ea844a1aSMatthew Knepley   Level: developer
3033*ea844a1aSMatthew Knepley 
3034*ea844a1aSMatthew Knepley .seealso: PetscSectionSetSym(), PetscSectionSymCreate()
3035*ea844a1aSMatthew Knepley @*/
3036*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetSym(PetscSection section, PetscSectionSym *sym)
3037*ea844a1aSMatthew Knepley {
3038*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3039*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3040*ea844a1aSMatthew Knepley   *sym = section->sym;
3041*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3042*ea844a1aSMatthew Knepley }
3043*ea844a1aSMatthew Knepley 
3044*ea844a1aSMatthew Knepley /*@
3045*ea844a1aSMatthew Knepley   PetscSectionSetFieldSym - Set the symmetries for the data referred to by a field of the section
3046*ea844a1aSMatthew Knepley 
3047*ea844a1aSMatthew Knepley   Collective on PetscSection
3048*ea844a1aSMatthew Knepley 
3049*ea844a1aSMatthew Knepley   Input Parameters:
3050*ea844a1aSMatthew Knepley + section - the section describing data layout
3051*ea844a1aSMatthew Knepley . field - the field number
3052*ea844a1aSMatthew Knepley - sym - the symmetry describing the affect of orientation on the access of the data
3053*ea844a1aSMatthew Knepley 
3054*ea844a1aSMatthew Knepley   Level: developer
3055*ea844a1aSMatthew Knepley 
3056*ea844a1aSMatthew Knepley .seealso: PetscSectionGetFieldSym(), PetscSectionSymCreate()
3057*ea844a1aSMatthew Knepley @*/
3058*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetFieldSym(PetscSection section, PetscInt field, PetscSectionSym sym)
3059*ea844a1aSMatthew Knepley {
3060*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
3061*ea844a1aSMatthew Knepley 
3062*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3063*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3064*ea844a1aSMatthew Knepley   if (field < 0 || field >= section->numFields) SETERRQ2(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number %D (not in [0,%D)", field, section->numFields);
3065*ea844a1aSMatthew Knepley   ierr = PetscSectionSetSym(section->field[field],sym);CHKERRQ(ierr);
3066*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3067*ea844a1aSMatthew Knepley }
3068*ea844a1aSMatthew Knepley 
3069*ea844a1aSMatthew Knepley /*@
3070*ea844a1aSMatthew Knepley   PetscSectionGetFieldSym - Get the symmetries for the data referred to by a field of the section
3071*ea844a1aSMatthew Knepley 
3072*ea844a1aSMatthew Knepley   Collective on PetscSection
3073*ea844a1aSMatthew Knepley 
3074*ea844a1aSMatthew Knepley   Input Parameters:
3075*ea844a1aSMatthew Knepley + section - the section describing data layout
3076*ea844a1aSMatthew Knepley - field - the field number
3077*ea844a1aSMatthew Knepley 
3078*ea844a1aSMatthew Knepley   Output Parameters:
3079*ea844a1aSMatthew Knepley . sym - the symmetry describing the affect of orientation on the access of the data
3080*ea844a1aSMatthew Knepley 
3081*ea844a1aSMatthew Knepley   Level: developer
3082*ea844a1aSMatthew Knepley 
3083*ea844a1aSMatthew Knepley .seealso: PetscSectionSetFieldSym(), PetscSectionSymCreate()
3084*ea844a1aSMatthew Knepley @*/
3085*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldSym(PetscSection section, PetscInt field, PetscSectionSym *sym)
3086*ea844a1aSMatthew Knepley {
3087*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3088*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3089*ea844a1aSMatthew Knepley   if (field < 0 || field >= section->numFields) SETERRQ2(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number %D (not in [0,%D)", field, section->numFields);
3090*ea844a1aSMatthew Knepley   *sym = section->field[field]->sym;
3091*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3092*ea844a1aSMatthew Knepley }
3093*ea844a1aSMatthew Knepley 
3094*ea844a1aSMatthew Knepley /*@C
3095*ea844a1aSMatthew Knepley   PetscSectionGetPointSyms - Get the symmetries for a set of points in a PetscSection under specific orientations.
3096*ea844a1aSMatthew Knepley 
3097*ea844a1aSMatthew Knepley   Not collective
3098*ea844a1aSMatthew Knepley 
3099*ea844a1aSMatthew Knepley   Input Parameters:
3100*ea844a1aSMatthew Knepley + section - the section
3101*ea844a1aSMatthew Knepley . numPoints - the number of points
3102*ea844a1aSMatthew Knepley - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an
3103*ea844a1aSMatthew Knepley     arbitrary integer: its interpretation is up to sym.  Orientations are used by DM: for their interpretation in that
3104*ea844a1aSMatthew Knepley     context, see DMPlexGetConeOrientation()).
3105*ea844a1aSMatthew Knepley 
3106*ea844a1aSMatthew Knepley   Output Parameter:
3107*ea844a1aSMatthew Knepley + perms - The permutations for the given orientations (or NULL if there is no symmetry or the permutation is the identity).
3108*ea844a1aSMatthew Knepley - rots - The field rotations symmetries for the given orientations (or NULL if there is no symmetry or the rotations are all
3109*ea844a1aSMatthew Knepley     identity).
3110*ea844a1aSMatthew Knepley 
3111*ea844a1aSMatthew Knepley   Example of usage, gathering dofs into a local array (lArray) from a section array (sArray):
3112*ea844a1aSMatthew Knepley .vb
3113*ea844a1aSMatthew Knepley      const PetscInt    **perms;
3114*ea844a1aSMatthew Knepley      const PetscScalar **rots;
3115*ea844a1aSMatthew Knepley      PetscInt            lOffset;
3116*ea844a1aSMatthew Knepley 
3117*ea844a1aSMatthew Knepley      PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots);
3118*ea844a1aSMatthew Knepley      for (i = 0, lOffset = 0; i < numPoints; i++) {
3119*ea844a1aSMatthew Knepley        PetscInt           point = points[2*i], dof, sOffset;
3120*ea844a1aSMatthew Knepley        const PetscInt    *perm  = perms ? perms[i] : NULL;
3121*ea844a1aSMatthew Knepley        const PetscScalar *rot   = rots  ? rots[i]  : NULL;
3122*ea844a1aSMatthew Knepley 
3123*ea844a1aSMatthew Knepley        PetscSectionGetDof(section,point,&dof);
3124*ea844a1aSMatthew Knepley        PetscSectionGetOffset(section,point,&sOffset);
3125*ea844a1aSMatthew Knepley 
3126*ea844a1aSMatthew Knepley        if (perm) {for (j = 0; j < dof; j++) {lArray[lOffset + perm[j]]  = sArray[sOffset + j];}}
3127*ea844a1aSMatthew Knepley        else      {for (j = 0; j < dof; j++) {lArray[lOffset +      j ]  = sArray[sOffset + j];}}
3128*ea844a1aSMatthew Knepley        if (rot)  {for (j = 0; j < dof; j++) {lArray[lOffset +      j ] *= rot[j];             }}
3129*ea844a1aSMatthew Knepley        lOffset += dof;
3130*ea844a1aSMatthew Knepley      }
3131*ea844a1aSMatthew Knepley      PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots);
3132*ea844a1aSMatthew Knepley .ve
3133*ea844a1aSMatthew Knepley 
3134*ea844a1aSMatthew Knepley   Example of usage, adding dofs into a section array (sArray) from a local array (lArray):
3135*ea844a1aSMatthew Knepley .vb
3136*ea844a1aSMatthew Knepley      const PetscInt    **perms;
3137*ea844a1aSMatthew Knepley      const PetscScalar **rots;
3138*ea844a1aSMatthew Knepley      PetscInt            lOffset;
3139*ea844a1aSMatthew Knepley 
3140*ea844a1aSMatthew Knepley      PetscSectionGetPointSyms(section,numPoints,points,&perms,&rots);
3141*ea844a1aSMatthew Knepley      for (i = 0, lOffset = 0; i < numPoints; i++) {
3142*ea844a1aSMatthew Knepley        PetscInt           point = points[2*i], dof, sOffset;
3143*ea844a1aSMatthew Knepley        const PetscInt    *perm  = perms ? perms[i] : NULL;
3144*ea844a1aSMatthew Knepley        const PetscScalar *rot   = rots  ? rots[i]  : NULL;
3145*ea844a1aSMatthew Knepley 
3146*ea844a1aSMatthew Knepley        PetscSectionGetDof(section,point,&dof);
3147*ea844a1aSMatthew Knepley        PetscSectionGetOffset(section,point,&sOff);
3148*ea844a1aSMatthew Knepley 
3149*ea844a1aSMatthew Knepley        if (perm) {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset + perm[j]] * (rot ? PetscConj(rot[perm[j]]) : 1.);}}
3150*ea844a1aSMatthew Knepley        else      {for (j = 0; j < dof; j++) {sArray[sOffset + j] += lArray[lOffset +      j ] * (rot ? PetscConj(rot[     j ]) : 1.);}}
3151*ea844a1aSMatthew Knepley        offset += dof;
3152*ea844a1aSMatthew Knepley      }
3153*ea844a1aSMatthew Knepley      PetscSectionRestorePointSyms(section,numPoints,points,&perms,&rots);
3154*ea844a1aSMatthew Knepley .ve
3155*ea844a1aSMatthew Knepley 
3156*ea844a1aSMatthew Knepley   Level: developer
3157*ea844a1aSMatthew Knepley 
3158*ea844a1aSMatthew Knepley .seealso: PetscSectionRestorePointSyms(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym()
3159*ea844a1aSMatthew Knepley @*/
3160*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetPointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3161*ea844a1aSMatthew Knepley {
3162*ea844a1aSMatthew Knepley   PetscSectionSym sym;
3163*ea844a1aSMatthew Knepley   PetscErrorCode  ierr;
3164*ea844a1aSMatthew Knepley 
3165*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3166*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3167*ea844a1aSMatthew Knepley   if (numPoints) PetscValidIntPointer(points,3);
3168*ea844a1aSMatthew Knepley   if (perms) *perms = NULL;
3169*ea844a1aSMatthew Knepley   if (rots)  *rots  = NULL;
3170*ea844a1aSMatthew Knepley   sym = section->sym;
3171*ea844a1aSMatthew Knepley   if (sym && (perms || rots)) {
3172*ea844a1aSMatthew Knepley     SymWorkLink link;
3173*ea844a1aSMatthew Knepley 
3174*ea844a1aSMatthew Knepley     if (sym->workin) {
3175*ea844a1aSMatthew Knepley       link        = sym->workin;
3176*ea844a1aSMatthew Knepley       sym->workin = sym->workin->next;
3177*ea844a1aSMatthew Knepley     } else {
3178*ea844a1aSMatthew Knepley       ierr = PetscNewLog(sym,&link);CHKERRQ(ierr);
3179*ea844a1aSMatthew Knepley     }
3180*ea844a1aSMatthew Knepley     if (numPoints > link->numPoints) {
3181*ea844a1aSMatthew Knepley       ierr = PetscFree2(*(PetscInt***)&link->perms,*(PetscInt***)&link->rots);CHKERRQ(ierr);
3182*ea844a1aSMatthew Knepley       ierr = PetscMalloc2(numPoints,(PetscInt***)&link->perms,numPoints,(PetscScalar***)&link->rots);CHKERRQ(ierr);
3183*ea844a1aSMatthew Knepley       link->numPoints = numPoints;
3184*ea844a1aSMatthew Knepley     }
3185*ea844a1aSMatthew Knepley     link->next   = sym->workout;
3186*ea844a1aSMatthew Knepley     sym->workout = link;
3187*ea844a1aSMatthew Knepley     ierr = PetscArrayzero((PetscInt**)link->perms,numPoints);CHKERRQ(ierr);
3188*ea844a1aSMatthew Knepley     ierr = PetscArrayzero((PetscInt**)link->rots,numPoints);CHKERRQ(ierr);
3189*ea844a1aSMatthew Knepley     ierr = (*sym->ops->getpoints) (sym, section, numPoints, points, link->perms, link->rots);CHKERRQ(ierr);
3190*ea844a1aSMatthew Knepley     if (perms) *perms = link->perms;
3191*ea844a1aSMatthew Knepley     if (rots)  *rots  = link->rots;
3192*ea844a1aSMatthew Knepley   }
3193*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3194*ea844a1aSMatthew Knepley }
3195*ea844a1aSMatthew Knepley 
3196*ea844a1aSMatthew Knepley /*@C
3197*ea844a1aSMatthew Knepley   PetscSectionRestorePointSyms - Restore the symmetries returned by PetscSectionGetPointSyms()
3198*ea844a1aSMatthew Knepley 
3199*ea844a1aSMatthew Knepley   Not collective
3200*ea844a1aSMatthew Knepley 
3201*ea844a1aSMatthew Knepley   Input Parameters:
3202*ea844a1aSMatthew Knepley + section - the section
3203*ea844a1aSMatthew Knepley . numPoints - the number of points
3204*ea844a1aSMatthew Knepley - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an
3205*ea844a1aSMatthew Knepley     arbitrary integer: its interpretation is up to sym.  Orientations are used by DM: for their interpretation in that
3206*ea844a1aSMatthew Knepley     context, see DMPlexGetConeOrientation()).
3207*ea844a1aSMatthew Knepley 
3208*ea844a1aSMatthew Knepley   Output Parameter:
3209*ea844a1aSMatthew Knepley + perms - The permutations for the given orientations: set to NULL at conclusion
3210*ea844a1aSMatthew Knepley - rots - The field rotations symmetries for the given orientations: set to NULL at conclusion
3211*ea844a1aSMatthew Knepley 
3212*ea844a1aSMatthew Knepley   Level: developer
3213*ea844a1aSMatthew Knepley 
3214*ea844a1aSMatthew Knepley .seealso: PetscSectionGetPointSyms(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym()
3215*ea844a1aSMatthew Knepley @*/
3216*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionRestorePointSyms(PetscSection section, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3217*ea844a1aSMatthew Knepley {
3218*ea844a1aSMatthew Knepley   PetscSectionSym sym;
3219*ea844a1aSMatthew Knepley 
3220*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3221*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3222*ea844a1aSMatthew Knepley   sym = section->sym;
3223*ea844a1aSMatthew Knepley   if (sym && (perms || rots)) {
3224*ea844a1aSMatthew Knepley     SymWorkLink *p,link;
3225*ea844a1aSMatthew Knepley 
3226*ea844a1aSMatthew Knepley     for (p=&sym->workout; (link=*p); p=&link->next) {
3227*ea844a1aSMatthew Knepley       if ((perms && link->perms == *perms) || (rots && link->rots == *rots)) {
3228*ea844a1aSMatthew Knepley         *p          = link->next;
3229*ea844a1aSMatthew Knepley         link->next  = sym->workin;
3230*ea844a1aSMatthew Knepley         sym->workin = link;
3231*ea844a1aSMatthew Knepley         if (perms) *perms = NULL;
3232*ea844a1aSMatthew Knepley         if (rots)  *rots  = NULL;
3233*ea844a1aSMatthew Knepley         PetscFunctionReturn(0);
3234*ea844a1aSMatthew Knepley       }
3235*ea844a1aSMatthew Knepley     }
3236*ea844a1aSMatthew Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
3237*ea844a1aSMatthew Knepley   }
3238*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3239*ea844a1aSMatthew Knepley }
3240*ea844a1aSMatthew Knepley 
3241*ea844a1aSMatthew Knepley /*@C
3242*ea844a1aSMatthew Knepley   PetscSectionGetFieldPointSyms - Get the symmetries for a set of points in a field of a PetscSection under specific orientations.
3243*ea844a1aSMatthew Knepley 
3244*ea844a1aSMatthew Knepley   Not collective
3245*ea844a1aSMatthew Knepley 
3246*ea844a1aSMatthew Knepley   Input Parameters:
3247*ea844a1aSMatthew Knepley + section - the section
3248*ea844a1aSMatthew Knepley . field - the field of the section
3249*ea844a1aSMatthew Knepley . numPoints - the number of points
3250*ea844a1aSMatthew Knepley - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an
3251*ea844a1aSMatthew Knepley     arbitrary integer: its interpretation is up to sym.  Orientations are used by DM: for their interpretation in that
3252*ea844a1aSMatthew Knepley     context, see DMPlexGetConeOrientation()).
3253*ea844a1aSMatthew Knepley 
3254*ea844a1aSMatthew Knepley   Output Parameter:
3255*ea844a1aSMatthew Knepley + perms - The permutations for the given orientations (or NULL if there is no symmetry or the permutation is the identity).
3256*ea844a1aSMatthew Knepley - rots - The field rotations symmetries for the given orientations (or NULL if there is no symmetry or the rotations are all
3257*ea844a1aSMatthew Knepley     identity).
3258*ea844a1aSMatthew Knepley 
3259*ea844a1aSMatthew Knepley   Level: developer
3260*ea844a1aSMatthew Knepley 
3261*ea844a1aSMatthew Knepley .seealso: PetscSectionGetPointSyms(), PetscSectionRestoreFieldPointSyms()
3262*ea844a1aSMatthew Knepley @*/
3263*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3264*ea844a1aSMatthew Knepley {
3265*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
3266*ea844a1aSMatthew Knepley 
3267*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3268*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3269*ea844a1aSMatthew Knepley   if (field > section->numFields) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"field %D greater than number of fields (%D) in section",field,section->numFields);
3270*ea844a1aSMatthew Knepley   ierr = PetscSectionGetPointSyms(section->field[field],numPoints,points,perms,rots);CHKERRQ(ierr);
3271*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3272*ea844a1aSMatthew Knepley }
3273*ea844a1aSMatthew Knepley 
3274*ea844a1aSMatthew Knepley /*@C
3275*ea844a1aSMatthew Knepley   PetscSectionRestoreFieldPointSyms - Restore the symmetries returned by PetscSectionGetFieldPointSyms()
3276*ea844a1aSMatthew Knepley 
3277*ea844a1aSMatthew Knepley   Not collective
3278*ea844a1aSMatthew Knepley 
3279*ea844a1aSMatthew Knepley   Input Parameters:
3280*ea844a1aSMatthew Knepley + section - the section
3281*ea844a1aSMatthew Knepley . field - the field number
3282*ea844a1aSMatthew Knepley . numPoints - the number of points
3283*ea844a1aSMatthew Knepley - points - an array of size 2 * numPoints, containing a list of (point, orientation) pairs. (An orientation is an
3284*ea844a1aSMatthew Knepley     arbitrary integer: its interpretation is up to sym.  Orientations are used by DM: for their interpretation in that
3285*ea844a1aSMatthew Knepley     context, see DMPlexGetConeOrientation()).
3286*ea844a1aSMatthew Knepley 
3287*ea844a1aSMatthew Knepley   Output Parameter:
3288*ea844a1aSMatthew Knepley + perms - The permutations for the given orientations: set to NULL at conclusion
3289*ea844a1aSMatthew Knepley - rots - The field rotations symmetries for the given orientations: set to NULL at conclusion
3290*ea844a1aSMatthew Knepley 
3291*ea844a1aSMatthew Knepley   Level: developer
3292*ea844a1aSMatthew Knepley 
3293*ea844a1aSMatthew Knepley .seealso: PetscSectionRestorePointSyms(), petscSectionGetFieldPointSyms(), PetscSectionSymCreate(), PetscSectionSetSym(), PetscSectionGetSym()
3294*ea844a1aSMatthew Knepley @*/
3295*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionRestoreFieldPointSyms(PetscSection section, PetscInt field, PetscInt numPoints, const PetscInt *points, const PetscInt ***perms, const PetscScalar ***rots)
3296*ea844a1aSMatthew Knepley {
3297*ea844a1aSMatthew Knepley   PetscErrorCode ierr;
3298*ea844a1aSMatthew Knepley 
3299*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3300*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,1);
3301*ea844a1aSMatthew Knepley   if (field > section->numFields) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"field %D greater than number of fields (%D) in section",field,section->numFields);
3302*ea844a1aSMatthew Knepley   ierr = PetscSectionRestorePointSyms(section->field[field],numPoints,points,perms,rots);CHKERRQ(ierr);
3303*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3304*ea844a1aSMatthew Knepley }
3305*ea844a1aSMatthew Knepley 
3306*ea844a1aSMatthew Knepley /*@
3307*ea844a1aSMatthew Knepley   PetscSectionGetUseFieldOffsets - Get the flag to use field offsets directly in a global section, rather than just the point offset
3308*ea844a1aSMatthew Knepley 
3309*ea844a1aSMatthew Knepley   Not collective
3310*ea844a1aSMatthew Knepley 
3311*ea844a1aSMatthew Knepley   Input Parameter:
3312*ea844a1aSMatthew Knepley . s - the global PetscSection
3313*ea844a1aSMatthew Knepley 
3314*ea844a1aSMatthew Knepley   Output Parameters:
3315*ea844a1aSMatthew Knepley . flg - the flag
3316*ea844a1aSMatthew Knepley 
3317*ea844a1aSMatthew Knepley   Level: developer
3318*ea844a1aSMatthew Knepley 
3319*ea844a1aSMatthew Knepley .seealso: PetscSectionSetChart(), PetscSectionCreate()
3320*ea844a1aSMatthew Knepley @*/
3321*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionGetUseFieldOffsets(PetscSection s, PetscBool *flg)
3322*ea844a1aSMatthew Knepley {
3323*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3324*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
3325*ea844a1aSMatthew Knepley   *flg = s->useFieldOff;
3326*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3327*ea844a1aSMatthew Knepley }
3328*ea844a1aSMatthew Knepley 
3329*ea844a1aSMatthew Knepley /*@
3330*ea844a1aSMatthew Knepley   PetscSectionSetUseFieldOffsets - Set the flag to use field offsets directly in a global section, rather than just the point offset
3331*ea844a1aSMatthew Knepley 
3332*ea844a1aSMatthew Knepley   Not collective
3333*ea844a1aSMatthew Knepley 
3334*ea844a1aSMatthew Knepley   Input Parameters:
3335*ea844a1aSMatthew Knepley + s   - the global PetscSection
3336*ea844a1aSMatthew Knepley - flg - the flag
3337*ea844a1aSMatthew Knepley 
3338*ea844a1aSMatthew Knepley   Level: developer
3339*ea844a1aSMatthew Knepley 
3340*ea844a1aSMatthew Knepley .seealso: PetscSectionGetUseFieldOffsets(), PetscSectionSetChart(), PetscSectionCreate()
3341*ea844a1aSMatthew Knepley @*/
3342*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionSetUseFieldOffsets(PetscSection s, PetscBool flg)
3343*ea844a1aSMatthew Knepley {
3344*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3345*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
3346*ea844a1aSMatthew Knepley   s->useFieldOff = flg;
3347*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3348*ea844a1aSMatthew Knepley }
3349*ea844a1aSMatthew Knepley 
3350*ea844a1aSMatthew Knepley #define PetscSectionExpandPoints_Loop(TYPE) \
3351*ea844a1aSMatthew Knepley { \
3352*ea844a1aSMatthew Knepley   PetscInt i, n, o0, o1, size; \
3353*ea844a1aSMatthew Knepley   TYPE *a0 = (TYPE*)origArray, *a1; \
3354*ea844a1aSMatthew Knepley   ierr = PetscSectionGetStorageSize(s, &size);CHKERRQ(ierr); \
3355*ea844a1aSMatthew Knepley   ierr = PetscMalloc1(size, &a1);CHKERRQ(ierr); \
3356*ea844a1aSMatthew Knepley   for (i=0; i<npoints; i++) { \
3357*ea844a1aSMatthew Knepley     ierr = PetscSectionGetOffset(origSection, points_[i], &o0);CHKERRQ(ierr); \
3358*ea844a1aSMatthew Knepley     ierr = PetscSectionGetOffset(s, i, &o1);CHKERRQ(ierr); \
3359*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(s, i, &n);CHKERRQ(ierr); \
3360*ea844a1aSMatthew Knepley     ierr = PetscMemcpy(&a1[o1], &a0[o0], n*unitsize);CHKERRQ(ierr); \
3361*ea844a1aSMatthew Knepley   } \
3362*ea844a1aSMatthew Knepley   *newArray = (void*)a1; \
3363*ea844a1aSMatthew Knepley }
3364*ea844a1aSMatthew Knepley 
3365*ea844a1aSMatthew Knepley /*@
3366*ea844a1aSMatthew Knepley   PetscSectionExtractDofsFromArray - Extracts elements of an array corresponding to DOFs of specified points.
3367*ea844a1aSMatthew Knepley 
3368*ea844a1aSMatthew Knepley   Not collective
3369*ea844a1aSMatthew Knepley 
3370*ea844a1aSMatthew Knepley   Input Parameters:
3371*ea844a1aSMatthew Knepley + origSection - the PetscSection describing the layout of the array
3372*ea844a1aSMatthew Knepley . dataType - MPI_Datatype describing the data type of the array (currently only MPIU_INT, MPIU_SCALAR, MPIU_REAL)
3373*ea844a1aSMatthew Knepley . origArray - the array; its size must be equal to the storage size of origSection
3374*ea844a1aSMatthew Knepley - points - IS with points to extract; its indices must lie in the chart of origSection
3375*ea844a1aSMatthew Knepley 
3376*ea844a1aSMatthew Knepley   Output Parameters:
3377*ea844a1aSMatthew Knepley + newSection - the new PetscSection desribing the layout of the new array (with points renumbered 0,1,... but preserving numbers of DOFs)
3378*ea844a1aSMatthew Knepley - newArray - the array of the extracted DOFs; its size is the storage size of newSection
3379*ea844a1aSMatthew Knepley 
3380*ea844a1aSMatthew Knepley   Level: developer
3381*ea844a1aSMatthew Knepley 
3382*ea844a1aSMatthew Knepley .seealso: PetscSectionGetChart(), PetscSectionGetDof(), PetscSectionGetStorageSize(), PetscSectionCreate()
3383*ea844a1aSMatthew Knepley @*/
3384*ea844a1aSMatthew Knepley PetscErrorCode PetscSectionExtractDofsFromArray(PetscSection origSection, MPI_Datatype dataType, const void *origArray, IS points, PetscSection *newSection, void *newArray[])
3385*ea844a1aSMatthew Knepley {
3386*ea844a1aSMatthew Knepley   PetscSection        s;
3387*ea844a1aSMatthew Knepley   const PetscInt      *points_;
3388*ea844a1aSMatthew Knepley   PetscInt            i, n, npoints, pStart, pEnd;
3389*ea844a1aSMatthew Knepley   PetscMPIInt         unitsize;
3390*ea844a1aSMatthew Knepley   PetscErrorCode      ierr;
3391*ea844a1aSMatthew Knepley 
3392*ea844a1aSMatthew Knepley   PetscFunctionBegin;
3393*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(origSection, PETSC_SECTION_CLASSID, 1);
3394*ea844a1aSMatthew Knepley   PetscValidPointer(origArray, 3);
3395*ea844a1aSMatthew Knepley   PetscValidHeaderSpecific(points, IS_CLASSID, 4);
3396*ea844a1aSMatthew Knepley   if (newSection) PetscValidPointer(newSection, 5);
3397*ea844a1aSMatthew Knepley   if (newArray) PetscValidPointer(newArray, 6);
3398*ea844a1aSMatthew Knepley   ierr = MPI_Type_size(dataType, &unitsize);CHKERRQ(ierr);
3399*ea844a1aSMatthew Knepley   ierr = ISGetLocalSize(points, &npoints);CHKERRQ(ierr);
3400*ea844a1aSMatthew Knepley   ierr = ISGetIndices(points, &points_);CHKERRQ(ierr);
3401*ea844a1aSMatthew Knepley   ierr = PetscSectionGetChart(origSection, &pStart, &pEnd);CHKERRQ(ierr);
3402*ea844a1aSMatthew Knepley   ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr);
3403*ea844a1aSMatthew Knepley   ierr = PetscSectionSetChart(s, 0, npoints);CHKERRQ(ierr);
3404*ea844a1aSMatthew Knepley   for (i=0; i<npoints; i++) {
3405*ea844a1aSMatthew Knepley     if (PetscUnlikely(points_[i] < pStart || points_[i] >= pEnd)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "point %d (index %d) in input IS out of input section's chart", points_[i], i);
3406*ea844a1aSMatthew Knepley     ierr = PetscSectionGetDof(origSection, points_[i], &n);CHKERRQ(ierr);
3407*ea844a1aSMatthew Knepley     ierr = PetscSectionSetDof(s, i, n);CHKERRQ(ierr);
3408*ea844a1aSMatthew Knepley   }
3409*ea844a1aSMatthew Knepley   ierr = PetscSectionSetUp(s);CHKERRQ(ierr);
3410*ea844a1aSMatthew Knepley   if (newArray) {
3411*ea844a1aSMatthew Knepley     if (dataType == MPIU_INT)           {PetscSectionExpandPoints_Loop(PetscInt);}
3412*ea844a1aSMatthew Knepley     else if (dataType == MPIU_SCALAR)   {PetscSectionExpandPoints_Loop(PetscScalar);}
3413*ea844a1aSMatthew Knepley     else if (dataType == MPIU_REAL)     {PetscSectionExpandPoints_Loop(PetscReal);}
3414*ea844a1aSMatthew Knepley     else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "not implemented for this MPI_Datatype");
3415*ea844a1aSMatthew Knepley   }
3416*ea844a1aSMatthew Knepley   if (newSection) {
3417*ea844a1aSMatthew Knepley     *newSection = s;
3418*ea844a1aSMatthew Knepley   } else {
3419*ea844a1aSMatthew Knepley     ierr = PetscSectionDestroy(&s);CHKERRQ(ierr);
3420*ea844a1aSMatthew Knepley   }
3421*ea844a1aSMatthew Knepley   PetscFunctionReturn(0);
3422*ea844a1aSMatthew Knepley }
3423