Commits

Matt Knepley committed 0164434 Merge

Merge branch 'knepley/feature-section-reorder'

* knepley/feature-section-reorder:
DMPlex: Fixed F90 binding for DMPlexCreateSection()
DMPlex exf90: Forgot Fortran change
DMPlex: Added permutation argument to DMPlexCreateSection() - Need it because it calls PetscSectionSetUp()
PetscSection: Added an optional permutation for the chart - Removed the unnecessary atlasLayout - This permutation will allow people to segregate ghost unknowns at the end of their numbering, and also to get around the stratification of point numbering in Plex

Comments (0)

Files changed (16)

include/finclude/ftn-custom/petscdmplex.h90

 
       Interface
         Subroutine DMPlexCreateSection(m,dim,numFields,numComp,         &
-     &  numDof,numBC,bcField,bcPoints,section,ierr)
+     &  numDof,numBC,bcField,bcPoints,perm,section,ierr)
           USE_DMPLEX_HIDE
           PETSCSECTION_HIDE section
           PetscInt     dim, numFields, numBC
           PetscInt, pointer :: numDof(:)
           PetscInt, pointer :: bcField(:)
           IS_HIDE,  pointer :: bcPoints(:)
+          IS_HIDE perm
           PetscErrorCode ierr
           DM_HIDE m
         End Subroutine

include/petsc-private/isimpl.h

 };
 
 /* ----------------------------------------------------------------------------*/
-typedef struct _n_PetscUniformSection *PetscUniformSection;
-struct _n_PetscUniformSection {
-  MPI_Comm comm;
-  PetscInt pStart, pEnd; /* The chart: all points are contained in [pStart, pEnd) */
-  PetscInt numDof;       /* Describes layout of storage, point --> (constant # of values, (p - pStart)*constant # of values) */
-};
-
 struct _p_PetscSection {
   PETSCHEADER(int);
-  struct _n_PetscUniformSection atlasLayout;  /* Layout for the atlas */
+  PetscInt                      pStart, pEnd; /* The chart: all points are contained in [pStart, pEnd) */
+  IS                            perm;         /* A permutation of [0, pEnd-pStart) */
   PetscInt                     *atlasDof;     /* Describes layout of storage, point --> # of values */
   PetscInt                     *atlasOff;     /* Describes layout of storage, point --> offset into storage */
   PetscInt                      maxDof;       /* Maximum dof on any point */

include/petscdmplex.h

 PETSC_EXTERN PetscErrorCode DMPlexComputeCellGeometryFVM(DM, PetscInt, PetscReal *, PetscReal [], PetscReal []);
 
 /* FEM Support */
-PETSC_EXTERN PetscErrorCode DMPlexCreateSection(DM, PetscInt, PetscInt,const PetscInt [],const PetscInt [], PetscInt,const PetscInt [],const IS [], PetscSection *);
+PETSC_EXTERN PetscErrorCode DMPlexCreateSection(DM, PetscInt, PetscInt,const PetscInt [],const PetscInt [], PetscInt,const PetscInt [],const IS [], IS, PetscSection *);
 
 PETSC_EXTERN PetscErrorCode DMPlexComputeCellGeometry(DM, PetscInt, PetscReal *, PetscReal *, PetscReal *, PetscReal *);
 PETSC_EXTERN PetscErrorCode DMPlexVecGetClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]);

include/petscis.h

 PETSC_EXTERN PetscErrorCode PetscSectionSetFieldComponents(PetscSection, PetscInt, PetscInt);
 PETSC_EXTERN PetscErrorCode PetscSectionGetChart(PetscSection, PetscInt *, PetscInt *);
 PETSC_EXTERN PetscErrorCode PetscSectionSetChart(PetscSection, PetscInt, PetscInt);
+PETSC_EXTERN PetscErrorCode PetscSectionGetPermutation(PetscSection, IS *);
+PETSC_EXTERN PetscErrorCode PetscSectionSetPermutation(PetscSection, IS);
 PETSC_EXTERN PetscErrorCode PetscSectionGetDof(PetscSection, PetscInt, PetscInt*);
 PETSC_EXTERN PetscErrorCode PetscSectionSetDof(PetscSection, PetscInt, PetscInt);
 PETSC_EXTERN PetscErrorCode PetscSectionAddDof(PetscSection, PetscInt, PetscInt);

src/dm/impls/plex/examples/tests/ex10.c

   ierr = ProcessOptions(&user);CHKERRQ(ierr);
   ierr = DMPlexCreateDoublet(PETSC_COMM_WORLD, user.dim, user.cellSimplex, user.interpolate, user.refinementUniform, user.refinementLimit, &dm);CHKERRQ(ierr);
   ierr = DMSetFromOptions(dm);CHKERRQ(ierr);
-  ierr = DMPlexCreateSection(dm, user.dim, user.numFields, user.numComponents, user.numDof, 0, NULL, NULL, &s);CHKERRQ(ierr);
+  ierr = DMPlexCreateSection(dm, user.dim, user.numFields, user.numComponents, user.numDof, 0, NULL, NULL, NULL, &s);CHKERRQ(ierr);
   ierr = DMSetDefaultSection(dm, s);CHKERRQ(ierr);
   ierr = PetscSectionDestroy(&s);CHKERRQ(ierr);
   ierr = TestReordering(dm, &user);CHKERRQ(ierr);

src/dm/impls/plex/examples/tests/ex9.c

     ierr = PetscLogEventRegister("VecClosure", PETSC_OBJECT_CLASSID, &event);CHKERRQ(ierr);
   }
   ierr = PetscLogStagePush(stage);CHKERRQ(ierr);
-  ierr = DMPlexCreateSection(dm, user->dim, user->numFields, user->numComponents, user->numDof, 0, NULL, NULL, &s);CHKERRQ(ierr);
+  ierr = DMPlexCreateSection(dm, user->dim, user->numFields, user->numComponents, user->numDof, 0, NULL, NULL, NULL, &s);CHKERRQ(ierr);
   ierr = DMSetDefaultSection(dm, s);CHKERRQ(ierr);
   if (useIndex) {ierr = DMPlexCreateClosureIndex(dm, s);CHKERRQ(ierr);}
   ierr = PetscSectionDestroy(&s);CHKERRQ(ierr);

src/dm/impls/plex/examples/tutorials/ex1.c

   bcField[0] = 0;
   ierr = DMPlexGetStratumIS(dm, "marker", 1, &bcPointIS[0]);CHKERRQ(ierr);
   /* Create a PetscSection with this data layout */
-  ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcField, bcPointIS, &section);CHKERRQ(ierr);
+  ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcField, bcPointIS, NULL, &section);CHKERRQ(ierr);
   ierr = ISDestroy(&bcPointIS[0]);CHKERRQ(ierr);
   /* Name the Field variables */
   ierr = PetscSectionSetFieldName(section, 0, "u");CHKERRQ(ierr);

src/dm/impls/plex/examples/tutorials/ex1f90.F

       pBcPointIS => bcPointIS
 !     Create a PetscSection with this data layout
       call DMPlexCreateSection(dm, dim, numFields, pNumComp,
-     $     pNumDof, numBC, pBcField, pBcPointIS, section,
-     $     ierr)
+     $     pNumDof, numBC, pBcField, pBcPointIS, PETSC_NULL_OBJECT,
+     $     section, ierr)
       CHKERRQ(ierr)
       call ISDestroy(bcPointIS(1), ierr)
       CHKERRQ(ierr)

src/dm/impls/plex/f90-custom/zplexf90.c

   *ierr = F90Array1dDestroy(cptr, PETSC_INT PETSC_F90_2PTR_PARAM(cptrd));if (*ierr) return;
 }
 
-PETSC_EXTERN void PETSC_STDCALL dmplexcreatesection_(DM *dm, PetscInt *dim, PetscInt *numFields, F90Array1d *ptrC, F90Array1d *ptrD, PetscInt *numBC, F90Array1d *ptrF, F90Array1d *ptrP, PetscSection *section, int *ierr PETSC_F90_2PTR_PROTO(ptrCd) PETSC_F90_2PTR_PROTO(ptrDd) PETSC_F90_2PTR_PROTO(ptrFd) PETSC_F90_2PTR_PROTO(ptrPd))
+PETSC_EXTERN void PETSC_STDCALL dmplexcreatesection_(DM *dm, PetscInt *dim, PetscInt *numFields, F90Array1d *ptrC, F90Array1d *ptrD, PetscInt *numBC, F90Array1d *ptrF, F90Array1d *ptrP, IS *perm, PetscSection *section, int *ierr PETSC_F90_2PTR_PROTO(ptrCd) PETSC_F90_2PTR_PROTO(ptrDd) PETSC_F90_2PTR_PROTO(ptrFd) PETSC_F90_2PTR_PROTO(ptrPd))
 {
   PetscInt *numComp;
   PetscInt *numDof;
   PetscInt *bcField;
   IS       *bcPoints;
 
+  CHKFORTRANNULLOBJECT(perm);
   *ierr = F90Array1dAccess(ptrC, PETSC_INT, (void**) &numComp PETSC_F90_2PTR_PARAM(ptrCd));if (*ierr) return;
   *ierr = F90Array1dAccess(ptrD, PETSC_INT, (void**) &numDof PETSC_F90_2PTR_PARAM(ptrDd));if (*ierr) return;
   *ierr = F90Array1dAccess(ptrF, PETSC_INT, (void**) &bcField PETSC_F90_2PTR_PARAM(ptrFd));if (*ierr) return;
   *ierr = F90Array1dAccess(ptrP, PETSC_FORTRANADDR, (void**) &bcPoints PETSC_F90_2PTR_PARAM(ptrPd));if (*ierr) return;
-  *ierr = DMPlexCreateSection(*dm, *dim, *numFields, numComp, numDof, *numBC, bcField, bcPoints, section);
+  *ierr = DMPlexCreateSection(*dm, *dim, *numFields, numComp, numDof, *numBC, bcField, bcPoints, *perm, section);
 }
 
 PETSC_EXTERN void PETSC_STDCALL dmplexcomputecellgeometry_(DM *dm, PetscInt *cell, F90Array1d *ptrV, F90Array1d *ptrJ, F90Array1d *ptrIJ, PetscReal *detJ, int *ierr PETSC_F90_2PTR_PROTO(ptrVd) PETSC_F90_2PTR_PROTO(ptrJd) PETSC_F90_2PTR_PROTO(ptrIJd))

src/dm/impls/plex/plex.c

 . numDof    - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d
 . numBC     - The number of boundary conditions
 . bcField   - An array of size numBC giving the field number for each boundry condition
-- bcPoints  - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies
+. bcPoints  - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies
+- perm      - Optional permutation of the chart, or NULL
 
   Output Parameter:
 . section - The PetscSection object
 
   Notes: numDof[f*(dim+1)+d] gives the number of dof for field f on sieve points of dimension d. For instance, numDof[1] is the
-  nubmer of dof for field 0 on each edge.
+  number of dof for field 0 on each edge.
+
+  The chart permutation is the same one set using PetscSectionSetPermutation()
 
   Level: developer
 
   A Fortran 90 version is available as DMPlexCreateSectionF90()
 
 .keywords: mesh, elements
-.seealso: DMPlexCreate(), PetscSectionCreate()
+.seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation()
 @*/
-PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section)
+PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], IS perm, PetscSection *section)
 {
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
   ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr);
   ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr);
+  if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);}
   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
   if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);}
   ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr);
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
-  ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr);
+  ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
     (*gsection)->atlasOff[p] = off;
     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
   }
-  ierr       = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr);
+  ierr       = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr);
   globalOff -= off;
   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
     (*gsection)->atlasOff[p] += globalOff;
       if ((numDof[f*(dim+1)+d] > 0) && (depth < dim)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces.");
     }
   }
-  ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, &section);CHKERRQ(ierr);
+  ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, NULL, &section);CHKERRQ(ierr);
   for (f = 0; f < numFields; ++f) {
     PetscFE     fe;
     const char *name;

src/dm/impls/plex/plexpoint.c

 #else
   {
     PetscSection s = dm->defaultSection;
-    *offset = s->atlasOff[point - s->atlasLayout.pStart];
+    *offset = s->atlasOff[point - s->pStart];
   }
 #endif
   PetscFunctionReturn(0);
   {
     PetscSection s = dm->defaultGlobalSection;
     PetscInt     dof,cdof;
-    *offset = s->atlasOff[point - s->atlasLayout.pStart];
-    dof     = s->atlasDof[point - s->atlasLayout.pStart];
-    cdof    = s->bc ? s->bc->atlasDof[point - s->bc->atlasLayout.pStart] : 0;
+    *offset = s->atlasOff[point - s->pStart];
+    dof     = s->atlasDof[point - s->pStart];
+    cdof    = s->bc ? s->bc->atlasDof[point - s->bc->pStart] : 0;
     if (dof-cdof <= 0) *offset = -1;
   }
 #endif

src/snes/examples/tutorials/ex12.c

   if (user->variableCoefficient != COEFF_FIELD) PetscFunctionReturn(0);
   ierr = PetscFEGetNumComponents(user->feAux[0], &numComp[0]);CHKERRQ(ierr);
   ierr = PetscFEGetNumDof(user->feAux[0], &numDof);CHKERRQ(ierr);
-  ierr = DMPlexCreateSection(dm, dim, 1, numComp, numDof, numBC, NULL, NULL, &section);CHKERRQ(ierr);
+  ierr = DMPlexCreateSection(dm, dim, 1, numComp, numDof, numBC, NULL, NULL, NULL, &section);CHKERRQ(ierr);
   ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr);
   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
   PetscFunctionReturn(0);

src/snes/examples/tutorials/ex52.c

   PetscFunctionBeginUser;
   ierr = PetscFEGetNumComponents(user->fe[0], &numComp[0]);CHKERRQ(ierr);
   ierr = PetscFEGetNumDof(user->fe[0], &numDof);CHKERRQ(ierr);
-  ierr = DMPlexCreateSection(dm, dim, 1, numComp, numDof, numBC, NULL, NULL, &section);CHKERRQ(ierr);
+  ierr = DMPlexCreateSection(dm, dim, 1, numComp, numDof, numBC, NULL, NULL, NULL, &section);CHKERRQ(ierr);
   ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr);
   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
   PetscFunctionReturn(0);

src/snes/examples/tutorials/ex72.c

     numBC = 1;
     ierr  = DMPlexGetStratumIS(dm, "marker", 1, &bcPoints[0]);CHKERRQ(ierr);
   }
-  ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, &section);CHKERRQ(ierr);
+  ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, NULL, &section);CHKERRQ(ierr);
   ierr = PetscSectionSetFieldName(section, 0, "velocity");CHKERRQ(ierr);
   ierr = PetscSectionSetFieldName(section, 1, "pressure");CHKERRQ(ierr);
   ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr);

src/vec/is/utils/vsectionis.c

 
   ierr = PetscHeaderCreate(*s,_p_PetscSection,int,PETSC_SECTION_CLASSID,"PetscSection","Section","IS",comm,PetscSectionDestroy,PetscSectionView);CHKERRQ(ierr);
 
-  (*s)->atlasLayout.comm   = comm;
-  (*s)->atlasLayout.pStart = -1;
-  (*s)->atlasLayout.pEnd   = -1;
-  (*s)->atlasLayout.numDof = 1;
+  (*s)->pStart             = -1;
+  (*s)->pEnd               = -1;
+  (*s)->perm               = NULL;
   (*s)->maxDof             = 0;
   (*s)->atlasDof           = NULL;
   (*s)->atlasOff           = NULL;
 @*/
 PetscErrorCode PetscSectionClone(PetscSection section, PetscSection *newSection)
 {
+  IS             perm;
   PetscInt       numFields, f, pStart, pEnd, p;
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
-  ierr = PetscSectionCreate(section->atlasLayout.comm, newSection);CHKERRQ(ierr);
+  ierr = PetscSectionCreate(PetscObjectComm((PetscObject) section), newSection);CHKERRQ(ierr);
   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
   if (numFields) {ierr = PetscSectionSetNumFields(*newSection, numFields);CHKERRQ(ierr);}
   for (f = 0; f < numFields; ++f) {
   }
   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
   ierr = PetscSectionSetChart(*newSection, pStart, pEnd);CHKERRQ(ierr);
+  ierr = PetscSectionGetPermutation(section, &perm);CHKERRQ(ierr);
+  ierr = PetscSectionSetPermutation(*newSection, perm);CHKERRQ(ierr);
   for (p = pStart; p < pEnd; ++p) {
     PetscInt dof, cdof, fcdof = 0;
 
 
     s->numFieldComponents[f] = 1;
 
-    ierr = PetscSectionCreate(s->atlasLayout.comm, &s->field[f]);CHKERRQ(ierr);
+    ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), &s->field[f]);CHKERRQ(ierr);
     ierr = PetscSNPrintf(name, 64, "Field_%D", f);CHKERRQ(ierr);
     ierr = PetscStrallocpy(name, (char **) &s->fieldNames[f]);CHKERRQ(ierr);
   }
 }
 
 #undef __FUNCT__
-#define __FUNCT__ "PetscSectionCheckConstraints"
-PetscErrorCode PetscSectionCheckConstraints(PetscSection s)
+#define __FUNCT__ "PetscSectionCheckConstraints_Static"
+static PetscErrorCode PetscSectionCheckConstraints_Static(PetscSection s)
 {
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
   if (!s->bc) {
     ierr = PetscSectionCreate(PETSC_COMM_SELF, &s->bc);CHKERRQ(ierr);
-    ierr = PetscSectionSetChart(s->bc, s->atlasLayout.pStart, s->atlasLayout.pEnd);CHKERRQ(ierr);
+    ierr = PetscSectionSetChart(s->bc, s->pStart, s->pEnd);CHKERRQ(ierr);
   }
   PetscFunctionReturn(0);
 }
 PetscErrorCode PetscSectionGetChart(PetscSection s, PetscInt *pStart, PetscInt *pEnd)
 {
   PetscFunctionBegin;
-  if (pStart) *pStart = s->atlasLayout.pStart;
-  if (pEnd)   *pEnd   = s->atlasLayout.pEnd;
+  PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
+  if (pStart) *pStart = s->pStart;
+  if (pEnd)   *pEnd   = s->pEnd;
   PetscFunctionReturn(0);
 }
 
 
   Level: intermediate
 
-.seealso: PetscSectionSetChart(), PetscSectionCreate()
+.seealso: PetscSectionGetChart(), PetscSectionCreate()
 @*/
 PetscErrorCode PetscSectionSetChart(PetscSection s, PetscInt pStart, PetscInt pEnd)
 {
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
+  PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
   /* Cannot Reset() because it destroys field information */
   s->setup = PETSC_FALSE;
   ierr = PetscSectionDestroy(&s->bc);CHKERRQ(ierr);
   ierr = PetscFree(s->bcIndices);CHKERRQ(ierr);
   ierr = PetscFree2(s->atlasDof, s->atlasOff);CHKERRQ(ierr);
 
-  s->atlasLayout.pStart = pStart;
-  s->atlasLayout.pEnd   = pEnd;
+  s->pStart = pStart;
+  s->pEnd   = pEnd;
   ierr = PetscMalloc2((pEnd - pStart), &s->atlasDof, (pEnd - pStart), &s->atlasOff);CHKERRQ(ierr);
   ierr = PetscMemzero(s->atlasDof, (pEnd - pStart)*sizeof(PetscInt));CHKERRQ(ierr);
   for (f = 0; f < s->numFields; ++f) {
 }
 
 #undef __FUNCT__
+#define __FUNCT__ "PetscSectionGetPermutation"
+/*@
+  PetscSectionGetPermutation - Returns the permutation of [0, pEnd-pStart) or NULL
+
+  Not collective
+
+  Input Parameter:
+. s - the PetscSection
+
+  Output Parameters:
+. perm - The permutation as an IS
+
+  Level: intermediate
+
+.seealso: PetscSectionSetPermutation(), PetscSectionCreate()
+@*/
+PetscErrorCode PetscSectionGetPermutation(PetscSection s, IS *perm)
+{
+  PetscFunctionBegin;
+  PetscValidHeaderSpecific(s, PETSC_SECTION_CLASSID, 1);
+  if (perm) {PetscValidPointer(perm, 2); *perm = s->perm;}
+  PetscFunctionReturn(0);
+}
+
+#undef __FUNCT__
+#define __FUNCT__ "PetscSectionSetPermutation"
+/*@
+  PetscSectionSetPermutation - Sets the permutation for [0, pEnd-pStart)
+
+  Not collective
+
+  Input Parameters:
++ s - the PetscSection
+- perm - the permutation of points
+
+  Level: intermediate
+
+.seealso: PetscSectionGetPermutation(), PetscSectionCreate()
+@*/
+PetscErrorCode PetscSectionSetPermutation(PetscSection s, IS perm)
+{
+  PetscErrorCode ierr;
+
+  PetscFunctionBegin;
+  if (s->setup) SETERRQ(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONGSTATE, "Cannot set a permutation after the section is setup");
+  if (s->perm != perm) {
+    ierr = ISDestroy(&s->perm);CHKERRQ(ierr);
+    s->perm = perm;
+    ierr = PetscObjectReference((PetscObject) s->perm);CHKERRQ(ierr);
+  }
+  PetscFunctionReturn(0);
+}
+
+#undef __FUNCT__
 #define __FUNCT__ "PetscSectionGetDof"
 /*@
   PetscSectionGetDof - Return the number of degrees of freedom associated with a given point.
 {
   PetscFunctionBegin;
 #if defined(PETSC_USE_DEBUG)
-  if ((point < s->atlasLayout.pStart) || (point >= s->atlasLayout.pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->atlasLayout.pStart, s->atlasLayout.pEnd);
+  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);
 #endif
-  *numDof = s->atlasDof[point - s->atlasLayout.pStart];
+  *numDof = s->atlasDof[point - s->pStart];
   PetscFunctionReturn(0);
 }
 
 PetscErrorCode PetscSectionSetDof(PetscSection s, PetscInt point, PetscInt numDof)
 {
   PetscFunctionBegin;
-  if ((point < s->atlasLayout.pStart) || (point >= s->atlasLayout.pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->atlasLayout.pStart, s->atlasLayout.pEnd);
-  s->atlasDof[point - s->atlasLayout.pStart] = numDof;
+  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);
+  s->atlasDof[point - s->pStart] = numDof;
   PetscFunctionReturn(0);
 }
 
 PetscErrorCode PetscSectionAddDof(PetscSection s, PetscInt point, PetscInt numDof)
 {
   PetscFunctionBegin;
-  if ((point < s->atlasLayout.pStart) || (point >= s->atlasLayout.pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->atlasLayout.pStart, s->atlasLayout.pEnd);
-  s->atlasDof[point - s->atlasLayout.pStart] += numDof;
+  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);
+  s->atlasDof[point - s->pStart] += numDof;
   PetscFunctionReturn(0);
 }
 
 
   PetscFunctionBegin;
   if (numDof) {
-    ierr = PetscSectionCheckConstraints(s);CHKERRQ(ierr);
+    ierr = PetscSectionCheckConstraints_Static(s);CHKERRQ(ierr);
     ierr = PetscSectionSetDof(s->bc, point, numDof);CHKERRQ(ierr);
   }
   PetscFunctionReturn(0);
 
   PetscFunctionBegin;
   if (numDof) {
-    ierr = PetscSectionCheckConstraints(s);CHKERRQ(ierr);
+    ierr = PetscSectionCheckConstraints_Static(s);CHKERRQ(ierr);
     ierr = PetscSectionAddDof(s->bc, point, numDof);CHKERRQ(ierr);
   }
   PetscFunctionReturn(0);
 
   PetscFunctionBegin;
   if (s->bc) {
-    const PetscInt last = (s->bc->atlasLayout.pEnd-s->bc->atlasLayout.pStart) - 1;
+    const PetscInt last = (s->bc->pEnd-s->bc->pStart) - 1;
 
     ierr = PetscSectionSetUp(s->bc);CHKERRQ(ierr);
     ierr = PetscMalloc1((s->bc->atlasOff[last] + s->bc->atlasDof[last]), &s->bcIndices);CHKERRQ(ierr);
 @*/
 PetscErrorCode PetscSectionSetUp(PetscSection s)
 {
-  PetscInt       offset = 0, p, f;
-  PetscErrorCode ierr;
+  const PetscInt *pind   = NULL;
+  PetscInt        offset = 0, p, f;
+  PetscErrorCode  ierr;
 
   PetscFunctionBegin;
   if (s->setup) PetscFunctionReturn(0);
   s->setup = PETSC_TRUE;
-  for (p = 0; p < s->atlasLayout.pEnd - s->atlasLayout.pStart; ++p) {
-    s->atlasOff[p] = offset;
-    offset        += s->atlasDof[p];
-    s->maxDof      = PetscMax(s->maxDof, s->atlasDof[p]);
+  if (s->perm) {ierr = ISGetIndices(s->perm, &pind);CHKERRQ(ierr);}
+  for (p = 0; p < s->pEnd - s->pStart; ++p) {
+    const PetscInt q = pind ? pind[p] : p;
+
+    s->atlasOff[q] = offset;
+    offset        += s->atlasDof[q];
+    s->maxDof      = PetscMax(s->maxDof, s->atlasDof[q]);
   }
   ierr = PetscSectionSetUpBC(s);CHKERRQ(ierr);
   /* Assume that all fields have the same chart */
-  for (p = 0; p < s->atlasLayout.pEnd - s->atlasLayout.pStart; ++p) {
-    PetscInt off = s->atlasOff[p];
+  for (p = 0; p < s->pEnd - s->pStart; ++p) {
+    const PetscInt q   = pind ? pind[p] : p;
+    PetscInt       off = s->atlasOff[q];
 
     for (f = 0; f < s->numFields; ++f) {
       PetscSection sf = s->field[f];
 
-      sf->atlasOff[p] = off;
-      off += sf->atlasDof[p];
+      sf->atlasOff[q] = off;
+      off += sf->atlasDof[q];
     }
   }
+  if (s->perm) {ierr = ISRestoreIndices(s->perm, &pind);CHKERRQ(ierr);}
   for (f = 0; f < s->numFields; ++f) {
     ierr = PetscSectionSetUpBC(s->field[f]);CHKERRQ(ierr);
   }
 #undef __FUNCT__
 #define __FUNCT__ "PetscSectionGetStorageSize"
 /*@
-  PetscSectionGetStorageSize - Return the size of an arary or local Vec capable of holding all the degrees of freedom.
+  PetscSectionGetStorageSize - Return the size of an array or local Vec capable of holding all the degrees of freedom.
 
   Not collective
 
 
   Level: intermediate
 
-.seealso: PetscSectionGetOffset(), PetscSectionCreate()
+.seealso: PetscSectionGetOffset(), PetscSectionGetConstrainedStorageSize(), PetscSectionCreate()
 @*/
 PetscErrorCode PetscSectionGetStorageSize(PetscSection s, PetscInt *size)
 {
   PetscInt p, n = 0;
 
   PetscFunctionBegin;
-  for (p = 0; p < s->atlasLayout.pEnd - s->atlasLayout.pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0;
+  for (p = 0; p < s->pEnd - s->pStart; ++p) n += s->atlasDof[p] > 0 ? s->atlasDof[p] : 0;
   *size = n;
   PetscFunctionReturn(0);
 }
 
 #undef __FUNCT__
 #define __FUNCT__ "PetscSectionGetConstrainedStorageSize"
+/*@
+  PetscSectionGetConstrainedStorageSize - Return the size of an array or local Vec capable of holding all unconstrained degrees of freedom.
+
+  Not collective
+
+  Input Parameters:
++ s - the PetscSection
+- point - the point
+
+  Output Parameter:
+. size - the size of an array which can hold all unconstrained dofs
+
+  Level: intermediate
+
+.seealso: PetscSectionGetStorageSize(), PetscSectionGetOffset(), PetscSectionCreate()
+@*/
 PetscErrorCode PetscSectionGetConstrainedStorageSize(PetscSection s, PetscInt *size)
 {
   PetscInt p, n = 0;
 
   PetscFunctionBegin;
-  for (p = 0; p < s->atlasLayout.pEnd - s->atlasLayout.pStart; ++p) {
+  for (p = 0; p < s->pEnd - s->pStart; ++p) {
     const PetscInt cdof = s->bc ? s->bc->atlasDof[p] : 0;
     n += s->atlasDof[p] > 0 ? s->atlasDof[p] - cdof : 0;
   }
 @*/
 PetscErrorCode PetscSectionCreateGlobalSection(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscSection *gsection)
 {
-  PetscInt       *neg = NULL, *recv = NULL;
-  PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots, nlocal;
-  PetscErrorCode ierr;
+  const PetscInt *pind = NULL;
+  PetscInt       *recv = NULL, *neg = NULL;
+  PetscInt        pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots, nlocal;
+  PetscErrorCode  ierr;
 
   PetscFunctionBegin;
-  ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr);
+  ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
     }
   }
   /* Calculate new sizes, get proccess offset, and calculate point offsets */
+  if (s->perm) {ierr = ISGetIndices(s->perm, &pind);CHKERRQ(ierr);}
   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
-    cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
-    (*gsection)->atlasOff[p] = off;
-    off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
+    const PetscInt q = pind ? pind[p] : p;
+
+    cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
+    (*gsection)->atlasOff[q] = off;
+    off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0;
   }
-  ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr);
+  ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr);
   globalOff -= off;
   for (p = pStart, off = 0; p < pEnd; ++p) {
     (*gsection)->atlasOff[p-pStart] += globalOff;
     if (neg) neg[p] = -((*gsection)->atlasOff[p-pStart]+1);
   }
+  if (s->perm) {ierr = ISRestoreIndices(s->perm, &pind);CHKERRQ(ierr);}
   /* Put in negative offsets for ghost points */
   if (nroots >= 0) {
     ierr = PetscMemzero(recv,nlocal*sizeof(PetscInt));CHKERRQ(ierr);
 @*/
 PetscErrorCode PetscSectionCreateGlobalSectionCensored(PetscSection s, PetscSF sf, PetscBool includeConstraints, PetscInt numExcludes, const PetscInt excludes[], PetscSection *gsection)
 {
-  PetscInt      *neg = NULL, *tmpOff = NULL;
-  PetscInt       pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots;
-  PetscErrorCode ierr;
+  const PetscInt *pind = NULL;
+  PetscInt       *neg  = NULL, *tmpOff = NULL;
+  PetscInt        pStart, pEnd, p, e, dof, cdof, off, globalOff = 0, nroots;
+  PetscErrorCode  ierr;
 
   PetscFunctionBegin;
-  ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr);
+  ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr);
   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
     }
   }
   /* Calculate new sizes, get proccess offset, and calculate point offsets */
+  if (s->perm) {ierr = ISGetIndices(s->perm, &pind);CHKERRQ(ierr);}
   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
-    cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
-    (*gsection)->atlasOff[p] = off;
-    off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
+    const PetscInt q = pind ? pind[p] : p;
+
+    cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[q] : 0;
+    (*gsection)->atlasOff[q] = off;
+    off += (*gsection)->atlasDof[q] > 0 ? (*gsection)->atlasDof[q]-cdof : 0;
   }
-  ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr);
+  ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr);
   globalOff -= off;
   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
     (*gsection)->atlasOff[p] += globalOff;
     if (neg) neg[p+pStart] = -((*gsection)->atlasOff[p]+1);
   }
+  if (s->perm) {ierr = ISRestoreIndices(s->perm, &pind);CHKERRQ(ierr);}
   /* Put in negative offsets for ghost points */
   if (nroots >= 0) {
     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
 {
   PetscFunctionBegin;
 #if defined(PETSC_USE_DEBUG)
-  if ((point < s->atlasLayout.pStart) || (point >= s->atlasLayout.pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->atlasLayout.pStart, s->atlasLayout.pEnd);
+  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);
 #endif
-  *offset = s->atlasOff[point - s->atlasLayout.pStart];
+  *offset = s->atlasOff[point - s->pStart];
   PetscFunctionReturn(0);
 }
 
 PetscErrorCode PetscSectionSetOffset(PetscSection s, PetscInt point, PetscInt offset)
 {
   PetscFunctionBegin;
-  if ((point < s->atlasLayout.pStart) || (point >= s->atlasLayout.pEnd)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section point %d should be in [%d, %d)", point, s->atlasLayout.pStart, s->atlasLayout.pEnd);
-  s->atlasOff[point - s->atlasLayout.pStart] = offset;
+  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);
+  s->atlasOff[point - s->pStart] = offset;
   PetscFunctionReturn(0);
 }
 
   PetscFunctionBegin;
   if (!numFields) PetscFunctionReturn(0);
   ierr = PetscSectionGetNumFields(s, &nF);CHKERRQ(ierr);
-  if (numFields > nF) SETERRQ2(s->atlasLayout.comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of fields %d", numFields, nF);
-  ierr = PetscSectionCreate(s->atlasLayout.comm, subs);CHKERRQ(ierr);
+  if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject) s), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of fields %d", numFields, nF);
+  ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);CHKERRQ(ierr);
   ierr = PetscSectionSetNumFields(*subs, numFields);CHKERRQ(ierr);
   for (f = 0; f < numFields; ++f) {
     const char *name   = NULL;
 
   PetscFunctionBegin;
   ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr);
-  ierr = PetscSectionCreate(s->atlasLayout.comm, subs);CHKERRQ(ierr);
+  ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), subs);CHKERRQ(ierr);
   if (numFields) {ierr = PetscSectionSetNumFields(*subs, numFields);CHKERRQ(ierr);}
   for (f = 0; f < numFields; ++f) {
     const char *name   = NULL;
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
-  if (s->atlasLayout.numDof != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle %d dof in a uniform section", s->atlasLayout.numDof);
   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr);
   ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr);
   ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr);
-  for (p = 0; p < s->atlasLayout.pEnd - s->atlasLayout.pStart; ++p) {
+  for (p = 0; p < s->pEnd - s->pStart; ++p) {
     if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
       PetscInt b;
 
-      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d constrained", p+s->atlasLayout.pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
+      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d constrained", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
       for (b = 0; b < s->bc->atlasDof[p]; ++b) {
         ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %d", s->bcIndices[s->bc->atlasOff[p]+b]);CHKERRQ(ierr);
       }
       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr);
     } else {
-      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d\n", p+s->atlasLayout.pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
+      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d\n", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
     }
   }
   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
   ierr = PetscSectionDestroy(&s->clSection);CHKERRQ(ierr);
   ierr = ISDestroy(&s->clPoints);CHKERRQ(ierr);
 
-  s->atlasLayout.pStart = -1;
-  s->atlasLayout.pEnd   = -1;
-  s->atlasLayout.numDof = 1;
-  s->maxDof             = 0;
-  s->setup              = PETSC_FALSE;
-  s->numFields          = 0;
-  s->clObj              = NULL;
+  s->pStart    = -1;
+  s->pEnd      = -1;
+  s->maxDof    = 0;
+  s->setup     = PETSC_FALSE;
+  s->numFields = 0;
+  s->clObj     = NULL;
   PetscFunctionReturn(0);
 }
 
 #define __FUNCT__ "VecIntGetValuesSection"
 PetscErrorCode VecIntGetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt **values)
 {
-  const PetscInt p = point - s->atlasLayout.pStart;
+  const PetscInt p = point - s->pStart;
 
   PetscFunctionBegin;
   *values = &baseArray[s->atlasOff[p]];
 PetscErrorCode VecIntSetValuesSection(PetscInt *baseArray, PetscSection s, PetscInt point, const PetscInt values[], InsertMode mode)
 {
   PetscInt       *array;
-  const PetscInt p           = point - s->atlasLayout.pStart;
+  const PetscInt p           = point - s->pStart;
   const PetscInt orientation = 0; /* Needs to be included for use in closure operations */
   PetscInt       cDim        = 0;
   PetscErrorCode ierr;

src/vec/vec/utils/vsection.c

   PetscErrorCode ierr;
 
   PetscFunctionBegin;
-  if (s->atlasLayout.numDof != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle %d dof in a uniform section", s->atlasLayout.numDof);
   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr);
   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
   ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr);
   ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr);
-  for (p = 0; p < s->atlasLayout.pEnd - s->atlasLayout.pStart; ++p) {
+  for (p = 0; p < s->pEnd - s->pStart; ++p) {
     if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
       PetscInt b;
 
-      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d", p+s->atlasLayout.pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
+      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
       for (i = s->atlasOff[p]; i < s->atlasOff[p]+s->atlasDof[p]; ++i) {
         PetscScalar v = array[i];
 #if defined(PETSC_USE_COMPLEX)
       }
       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr);
     } else {
-      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d", p+s->atlasLayout.pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
+      ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4d) dim %2d offset %3d", p+s->pStart, s->atlasDof[p], s->atlasOff[p]);CHKERRQ(ierr);
       for (i = s->atlasOff[p]; i < s->atlasOff[p]+s->atlasDof[p]; ++i) {
         PetscScalar v = array[i];
 #if defined(PETSC_USE_COMPLEX)
 PetscErrorCode VecGetValuesSection(Vec v, PetscSection s, PetscInt point, PetscScalar **values)
 {
   PetscScalar    *baseArray;
-  const PetscInt p = point - s->atlasLayout.pStart;
+  const PetscInt p = point - s->pStart;
   PetscErrorCode ierr;
 
   PetscFunctionBegin;
   const PetscBool doInsert    = mode == INSERT_VALUES     || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES                          ? PETSC_TRUE : PETSC_FALSE;
   const PetscBool doInterior  = mode == INSERT_ALL_VALUES || mode == ADD_ALL_VALUES    || mode == INSERT_VALUES    || mode == ADD_VALUES    ? PETSC_TRUE : PETSC_FALSE;
   const PetscBool doBC        = mode == INSERT_ALL_VALUES || mode == ADD_ALL_VALUES    || mode == INSERT_BC_VALUES || mode == ADD_BC_VALUES ? PETSC_TRUE : PETSC_FALSE;
-  const PetscInt  p           = point - s->atlasLayout.pStart;
+  const PetscInt  p           = point - s->pStart;
   const PetscInt  orientation = 0; /* Needs to be included for use in closure operations */
   PetscInt        cDim        = 0;
   PetscErrorCode  ierr;