1*7f296bb3SBarry Smith(ch_petscsection)= 2*7f296bb3SBarry Smith 3*7f296bb3SBarry Smith# PetscSection: Connecting Grids to Data 4*7f296bb3SBarry Smith 5*7f296bb3SBarry SmithThe strongest links between solvers and discretizations are 6*7f296bb3SBarry Smith 7*7f296bb3SBarry Smith- the relationship between the layout of data over a mesh (or similar structure) and the data layout in arrays and `Vec` used for computation, 8*7f296bb3SBarry Smith- data partitioning, and 9*7f296bb3SBarry Smith- ordering of data. 10*7f296bb3SBarry Smith 11*7f296bb3SBarry SmithTo enable modularity, we encode the operations above in simple data 12*7f296bb3SBarry Smithstructures that can be understood by the linear algebraic and solver components of PETSc (`Vec`, `Mat`, `KSP`, `PC`, `SNES`, `TS`, `Tao`) 13*7f296bb3SBarry Smithwithout explicit reference to the mesh (topology) or discretization (analysis). 14*7f296bb3SBarry Smith 15*7f296bb3SBarry SmithWhile `PetscSection` is currently only employed for `DMPlex`, `DMForest`, and `DMNetwork` mesh descriptions, much of its operation is general enough to be utilized for other types of discretizations. 16*7f296bb3SBarry SmithThis section will explain the basic concepts of a `PetscSection` that are generalizable to other mesh descriptions. 17*7f296bb3SBarry Smith 18*7f296bb3SBarry Smith(sec_petscsection_concept)= 19*7f296bb3SBarry Smith 20*7f296bb3SBarry Smith## General concept 21*7f296bb3SBarry Smith 22*7f296bb3SBarry SmithSpecific entries (or collections of entries) in a `Vec` (or a simple array) can be associated with a "location" on a mesh (or other types of data structure) using the `PetscSection` object. 23*7f296bb3SBarry SmithA **point** is a `PetscInt` that serves as an abstract "index" into arrays from iterable sets, such as k-cells in a mesh. 24*7f296bb3SBarry SmithOther iterable set examples can be as simple as the points of a finite difference grid, or cells of a finite volume grid, or as complex as the topological entities of an unstructured mesh (cells, faces, edges, and vertices). 25*7f296bb3SBarry Smith 26*7f296bb3SBarry SmithAt it's most basic, a `PetscSection` is a mapping between the mesh points and a tuple `(ndof, offset)`, where `ndof` is the number of values stored at that mesh point and `offset` is the location in the array of that data. 27*7f296bb3SBarry SmithSo given the tuple for a mesh point, its data can be accessed by `array[offset + d]`, where `d` in `[0, ndof)` is the dof to access. 28*7f296bb3SBarry Smith 29*7f296bb3SBarry Smith### Charts: Defining mesh points 30*7f296bb3SBarry Smith 31*7f296bb3SBarry SmithThe mesh points for a `PetscSection` must be contiguously numbered and are defined to be in some range $[\mathrm{pStart}, \mathrm{pEnd})$, which is called a **chart**. 32*7f296bb3SBarry SmithThe chart of a `PetscSection` is set via `PetscSectionSetChart()`. 33*7f296bb3SBarry SmithNote that even though the mesh points must be contiguously numbered, the indexes into the array (defined by each `(ndof, offset)` tuple) associated with the `PetscSection` need not be. 34*7f296bb3SBarry SmithIn other words, there may be elements in the array that are not associated with any mesh points, though this is not often the case. 35*7f296bb3SBarry Smith 36*7f296bb3SBarry Smith### Defining the (ndof, offset) tuple 37*7f296bb3SBarry Smith 38*7f296bb3SBarry SmithDefining the `(ndof, offset)` tuple for each mesh point generally first starts with setting the `ndof` for each point, which is done using `PetscSectionSetDof()`. 39*7f296bb3SBarry SmithThis associates a set of degrees of freedom (dof), (a small space $\{e_k\}\ 0 < k < ndof$), with every point. 40*7f296bb3SBarry SmithIf `ndof` is not set for a mesh point, it is assumed to be 0. 41*7f296bb3SBarry Smith 42*7f296bb3SBarry SmithThe offset for each mesh point is usually set automatically by `PetscSectionSetUp()`. 43*7f296bb3SBarry SmithThis will concatenate each mesh point's dofs together in the order of the mesh points. 44*7f296bb3SBarry SmithThis concatenation can be done in a different order by setting a permutation, which is described in {any}`sec_petscsection_permutation`. 45*7f296bb3SBarry Smith 46*7f296bb3SBarry SmithAlternatively, the offset for each mesh point can be set manually by `PetscSectionSetOffset()`, though this is not commonly needed. 47*7f296bb3SBarry Smith 48*7f296bb3SBarry SmithOnce the tuples are created, the `PetscSection` is ready to use. 49*7f296bb3SBarry Smith 50*7f296bb3SBarry Smith### Basic Setup Example 51*7f296bb3SBarry Smith 52*7f296bb3SBarry SmithTo summarize, the sequence for constructing a basic `PetscSection` is the following: 53*7f296bb3SBarry Smith 54*7f296bb3SBarry Smith1. Specify the range of points, or chart, with `PetscSectionSetChart()`. 55*7f296bb3SBarry Smith2. Specify the number of dofs per point with `PetscSectionSetDof()`. Any values not set will be zero. 56*7f296bb3SBarry Smith3. Set up the `PetscSection` with `PetscSectionSetUp()`. 57*7f296bb3SBarry Smith 58*7f296bb3SBarry Smith## Multiple Fields 59*7f296bb3SBarry Smith 60*7f296bb3SBarry SmithIn many discretizations, it is useful to differentiate between different kinds of dofs present on a mesh. 61*7f296bb3SBarry SmithFor example, a dof attached to a cell point might represent pressure while dofs on vertices might represent velocity or displacement. 62*7f296bb3SBarry SmithA `PetscSection` can represent this additional structure with what are called **fields**. 63*7f296bb3SBarry Smith**Fields** are indexed contiguously from `[0, num_fields)`. 64*7f296bb3SBarry SmithTo set the number of fields for a `PetscSection`, call `PetscSectionSetNumFields()`. 65*7f296bb3SBarry Smith 66*7f296bb3SBarry SmithInternally, each field is stored in a separate `PetscSection`. 67*7f296bb3SBarry SmithIn fact, all the concepts and functions presented in {any}`sec_petscsection_concept` were actually applied onto the **default field**, which is indexed as `0`. 68*7f296bb3SBarry SmithThe fields inherit the same chart as the "parent" `PetscSection`. 69*7f296bb3SBarry Smith 70*7f296bb3SBarry Smith### Setting Up Multiple Fields 71*7f296bb3SBarry Smith 72*7f296bb3SBarry SmithSetup for a `PetscSection` with multiple fields is nearly identical to setup for a single field. 73*7f296bb3SBarry Smith 74*7f296bb3SBarry SmithThe sequence for constructing such a `PetscSection` is the following: 75*7f296bb3SBarry Smith 76*7f296bb3SBarry Smith1. Specify the range of points, or chart, with `PetscSectionSetChart()`. All fields share the same chart. 77*7f296bb3SBarry Smith2. Specify the number of fields with `PetscSectionSetNumFields()`. 78*7f296bb3SBarry Smith3. Set the number of dof for each point on each field with `PetscSectionSetFieldDof()`. Any values not set will be zero. 79*7f296bb3SBarry Smith4. Set the **total** number of dof for each point with `PetscSectionSetDof()`. Thus value must be greater than or equal to the sum of the values set with 80*7f296bb3SBarry Smith `PetscSectionSetFieldDof()` at that point. Again, values not set will be zero. 81*7f296bb3SBarry Smith5. Set up the `PetscSection` with `PetscSectionSetUp()`. 82*7f296bb3SBarry Smith 83*7f296bb3SBarry Smith### Point Major or Field Major 84*7f296bb3SBarry Smith 85*7f296bb3SBarry SmithA `PetscSection` with one field and and offsets set in `PetscSectionSetUp()` may be thought of as defining a two dimensional array indexed by point in the outer dimension with a variable length inner dimension indexed by the dof at that point: $v[\mathrm{pStart} <= point < \mathrm{pEnd}][0 <= dof < \mathrm{ndof}]$ [^petscsection-footnote]. 86*7f296bb3SBarry Smith 87*7f296bb3SBarry SmithWith multiple fields, this array is now three dimensional, with the outer dimensions being both indexed by mesh points and field points. 88*7f296bb3SBarry SmithThus, there is a choice on whether to index by points first, or by fields first. 89*7f296bb3SBarry SmithIn other words, will the array be laid out in a point-major or field-major fashion. 90*7f296bb3SBarry Smith 91*7f296bb3SBarry SmithPoint-major ordering corresponds to $v[\mathrm{pStart} <= point < \mathrm{pEnd}][0 <= field < \mathrm{num\_fields}][0 <= dof < \mathrm{ndof}]$. 92*7f296bb3SBarry SmithAll the dofs for each mesh point are stored contiguously, meaning the fields are **interlaced**. 93*7f296bb3SBarry SmithField-major ordering corresponds to $v[0 <= field < \mathrm{num\_fields}][\mathrm{pStart} <= point < \mathrm{pEnd}][0 <= dof < \mathrm{ndof}]$. 94*7f296bb3SBarry SmithThe all the dofs for each field are stored contiguously, meaning the points are **interlaced**. 95*7f296bb3SBarry Smith 96*7f296bb3SBarry SmithConsider a `PetscSection` with 2 fields and 2 points (from 0 to 2). Let the 0th field have `ndof=1` for each point and the 1st field have `ndof=2` for each point. 97*7f296bb3SBarry SmithDenote each array entry $(p_i, f_i, d_i)$ for $p_i$ being the ith point, $f_i$ being the ith field, and $d_i$ being the ith dof. 98*7f296bb3SBarry Smith 99*7f296bb3SBarry SmithPoint-major order would result in: 100*7f296bb3SBarry Smith 101*7f296bb3SBarry Smith$$ 102*7f296bb3SBarry Smith[(p_0, f_0, d_0), (p_0, f_1, d_0), (p_0, f_1, d_1),\\ (p_1, f_0, d_0), (p_1, f_1, d_0), (p_1, f_1, d_1)] 103*7f296bb3SBarry Smith$$ 104*7f296bb3SBarry Smith 105*7f296bb3SBarry SmithConversely, field-major ordering would result in: 106*7f296bb3SBarry Smith 107*7f296bb3SBarry Smith$$ 108*7f296bb3SBarry Smith[(p_0, f_0, d_0), (p_1, f_0, d_0),\\ (p_0, f_1, d_0), (p_0, f_1, d_1), (p_1, f_1, d_0), (p_1, f_1, d_1)] 109*7f296bb3SBarry Smith$$ 110*7f296bb3SBarry Smith 111*7f296bb3SBarry SmithNote that dofs are always contiguous, regardless of the outer dimensional ordering. 112*7f296bb3SBarry Smith 113*7f296bb3SBarry SmithSetting the which ordering is done with `PetscSectionSetPointMajor()`, where `PETSC_TRUE` sets point-major and `PETSC_FALSE` sets field major. 114*7f296bb3SBarry Smith 115*7f296bb3SBarry Smith**NOTE:** The current default is for point-major, and many operations on `DMPlex` will only work with this ordering. Field-major ordering is provided mainly for compatibility with external packages, such as LibMesh. 116*7f296bb3SBarry Smith 117*7f296bb3SBarry Smith## Working with data 118*7f296bb3SBarry Smith 119*7f296bb3SBarry SmithOnce a `PetscSection` has been created one can use `PetscSectionGetStorageSize()` to determine the total number of entries that can be stored in an array or `Vec` accessible by the `PetscSection`. 120*7f296bb3SBarry SmithThis is most often used when creating a new `Vec` for a `PetscSection` such as: 121*7f296bb3SBarry Smith 122*7f296bb3SBarry Smith``` 123*7f296bb3SBarry SmithPetscSectionGetStorageSize(s, &n); 124*7f296bb3SBarry SmithVecSetSizes(localVec, n, PETSC_DETERMINE); 125*7f296bb3SBarry SmithVecSetFromOptions(localVec); 126*7f296bb3SBarry Smith``` 127*7f296bb3SBarry Smith 128*7f296bb3SBarry SmithThe memory locations in the associated array are found using an **offset** which can be obtained with: 129*7f296bb3SBarry Smith 130*7f296bb3SBarry SmithSingle-field `PetscSection`: 131*7f296bb3SBarry Smith 132*7f296bb3SBarry Smith``` 133*7f296bb3SBarry SmithPetscSectionGetOffset(PetscSection, PetscInt point, PetscInt &offset); 134*7f296bb3SBarry Smith``` 135*7f296bb3SBarry Smith 136*7f296bb3SBarry SmithMulti-field `PetscSection`: 137*7f296bb3SBarry Smith 138*7f296bb3SBarry Smith``` 139*7f296bb3SBarry SmithPetscSectionGetFieldOffset(PetscSection, PetscInt point, PetscInt field, PetscInt &offset); 140*7f296bb3SBarry Smith``` 141*7f296bb3SBarry Smith 142*7f296bb3SBarry SmithThe value in the array is then accessed with `array[offset + d]`, where `d` in `[0, ndof)` is the dof to access. 143*7f296bb3SBarry Smith 144*7f296bb3SBarry Smith## Global Sections: Constrained and Distributed Data 145*7f296bb3SBarry Smith 146*7f296bb3SBarry SmithTo handle distributed data and data with constraints, we use a pair of `PetscSections` called the `localSection` and `globalSection`. 147*7f296bb3SBarry SmithTheir use for each is described below. 148*7f296bb3SBarry Smith 149*7f296bb3SBarry Smith### Distributed Data 150*7f296bb3SBarry Smith 151*7f296bb3SBarry Smith`PetscSection` can also be applied to distributed problems as well. 152*7f296bb3SBarry SmithThis is done using the same local/global system described in {any}`sec_localglobal`. 153*7f296bb3SBarry SmithTo do this, we introduce three new concepts; a `localSection`, `globalSection`, `pointSF`, and `sectionSF`. 154*7f296bb3SBarry Smith 155*7f296bb3SBarry SmithAssume the mesh points of the "global" mesh are partitioned amongst processes and that some mesh points are shared between multiple processes (i.e there is an overlap in the partitions). 156*7f296bb3SBarry SmithThe shared mesh points define the ghost/halo points needed in many PDE problems. 157*7f296bb3SBarry SmithFor each shared mesh point, appoint one process to be the owner of that mesh point. 158*7f296bb3SBarry SmithTo describe this parallel mesh point layout, we use a `PetscSF` and call it the `pointSF`. 159*7f296bb3SBarry SmithThe `pointSF` describes which processes "own" which mesh points and which process is the owner of each shared mesh point. 160*7f296bb3SBarry Smith 161*7f296bb3SBarry SmithNext, for each process define a `PetscSection` that describes the mapping between that process's partition (including shared mesh points) and the data stored on it and call it the `localSection`. 162*7f296bb3SBarry SmithThe `localSection` describes the layout of the local vector. 163*7f296bb3SBarry SmithTo generate the `globalSection` we use `PetscSectionCreateGlobalSection()`, which takes the `localSection` and `pointSF` as inputs. 164*7f296bb3SBarry SmithThe global section returns $-(dof+1)$ for the number of dofs on an unowned (ghost) point, and traditionally $-(off+1)$ for its offset on the owning process. 165*7f296bb3SBarry SmithThis behavior of the offsets is controlled via an argument to `PetscSectionCreateGlobalSection()`. 166*7f296bb3SBarry SmithThe `globalSection` can be used to create global vectors, just as the local section is used to create local vectors. 167*7f296bb3SBarry Smith 168*7f296bb3SBarry SmithTo perform the global-to-local and local-to-global communication, we define `sectionSF` to be the `PetscSF` describing the mapping between the local and global vectors. 169*7f296bb3SBarry SmithThis is generated via `PetscSFSetGraphSection()`. 170*7f296bb3SBarry SmithUsing `PetscSFBcastBegin()` will send data from the global vector to the local vector, while `PetscSFReduceBegin()` will send data from the local vector to the global vector. 171*7f296bb3SBarry Smith 172*7f296bb3SBarry SmithIf using `DM`, this entire process is done automatically. 173*7f296bb3SBarry SmithThe `localSection`, `globalSection`, `pointSF`, and `sectionSF` on a `DM` can be obtained via `DMGetLocalSection()`, `DMGetGlobalSection()`, `DMGetPointSF()`, and `DMGetSectionSF()`, respectively. 174*7f296bb3SBarry SmithAdditionally, communication from global to local vectors and vice versa can be done via `DMGlobalToLocal()` and `DMLocalToGlobal()` as described in {any}`sec_localglobal`. 175*7f296bb3SBarry SmithNote that not all `DM` types use this system, such as `DMDA` (see {any}`sec_struct`). 176*7f296bb3SBarry Smith 177*7f296bb3SBarry Smith### Constrained Data 178*7f296bb3SBarry Smith 179*7f296bb3SBarry SmithIn addition to describing parallel data, the `localSection`/`globalSection` pair can be used to describe *constrained* dofs 180*7f296bb3SBarry SmithThese constraints usually represent essential (Dirichlet) boundary conditions, or algebraic constraints. 181*7f296bb3SBarry SmithThey are dofs that have a given fixed value, so they are present in local vectors for finite element/volume assembly or finite difference stencil application purposes, but generally absent from global vectors since they are not unknowns in the algebraic solves. 182*7f296bb3SBarry Smith 183*7f296bb3SBarry SmithConstraints should be indicated in the `localSection`. 184*7f296bb3SBarry SmithUse `PetscSectionSetConstraintDof()` to set the number of constrained dofs for a given point, and `PetscSectionSetConstraintIndices()` to indicate which dofs on the given point are constrained. 185*7f296bb3SBarry SmithThis must be done before `PetscSectionCreateGlobalSection()` is called to create the `globalSection`. 186*7f296bb3SBarry Smith 187*7f296bb3SBarry SmithNote that it is possible to have constraints set in a `localSection`, but have the `globalSection` be generated to include those constraints. 188*7f296bb3SBarry SmithThis is useful when doing some form of post-processing of a solution where you want to access all data (see `DMGetOutputDM()` for example). 189*7f296bb3SBarry SmithSee `PetscSectionCreateGlobalSection()` for more details on this. 190*7f296bb3SBarry Smith 191*7f296bb3SBarry Smith(sec_petscsection_permutation)= 192*7f296bb3SBarry Smith 193*7f296bb3SBarry Smith## Permutation: Changing the order of array data 194*7f296bb3SBarry Smith 195*7f296bb3SBarry SmithBy default, when `PetscSectionSetUp()` is called, the data laid out in the associated array is assumed to be in the same order of the grid points. 196*7f296bb3SBarry SmithFor example, the DoFs associated with grid point 0 appear directly before grid point 1, which appears before grid point 2, etc. 197*7f296bb3SBarry Smith 198*7f296bb3SBarry SmithIt may be desired to have a different the ordering of data in the array than the order of grid points defined by a section. 199*7f296bb3SBarry SmithFor example, one may want grid points associated with the boundary of a domain to appear before points associated with the interior of the domain. 200*7f296bb3SBarry Smith 201*7f296bb3SBarry SmithThis can be accomplished by either changing the indexes of the grid points themselves, or by informing the section of the change in array ordering. 202*7f296bb3SBarry SmithEither method uses an `IS` to define the permutation. 203*7f296bb3SBarry Smith 204*7f296bb3SBarry SmithTo change the indices of the grid points, call `PetscSectionPermute()` to generate a new `PetscSection` with the desired grid point permutation. 205*7f296bb3SBarry Smith 206*7f296bb3SBarry SmithTo just change the array layout without changing the grid point indexing, call `PetscSectionSetPermutation()`. 207*7f296bb3SBarry SmithThis must be called before `PetscSectionSetUp()` and will only affect the calculation of the offsets for each grid point. 208*7f296bb3SBarry Smith 209*7f296bb3SBarry Smith% TODO: Add example to demonstrate the difference between the two permutation methods 210*7f296bb3SBarry Smith 211*7f296bb3SBarry Smith## DMPlex Specific Functionality: Obtaining data from the array 212*7f296bb3SBarry Smith 213*7f296bb3SBarry SmithA vanilla `PetscSection` (what's been described up till now) gives a relatively naive perspective on the underlying data; it doesn't describe how DoFs attached to a single grid point are ordered or how different grid points relate to each other. 214*7f296bb3SBarry SmithA `PetscSection` can store and use this extra information in the form of **closures**, **symmetries**, and **closure permutations**. 215*7f296bb3SBarry SmithThese features currently target `DMPlex` and other unstructured grid descriptions. 216*7f296bb3SBarry SmithA description of those features will be left to {any}`ch_unstructured`. 217*7f296bb3SBarry Smith 218*7f296bb3SBarry Smith```{rubric} Footnotes 219*7f296bb3SBarry Smith``` 220*7f296bb3SBarry Smith 221*7f296bb3SBarry Smith[^petscsection-footnote]: A `PetscSection` can be thought of as a generalization of `PetscLayout`, in the same way that a fiber bundle is a generalization 222*7f296bb3SBarry Smith of the normal Euclidean basis used in linear algebra. With `PetscLayout`, we associate a unit vector ($e_i$) with every 223*7f296bb3SBarry Smith point in the space, and just divide up points between processes. 224*7f296bb3SBarry Smith Conversely, `PetscSection` associates multiple unit vectors with every mesh point (one for each dof) and divides the mesh points between processes using a `PetscSF` to define the distribution. 225*7f296bb3SBarry Smith 226*7f296bb3SBarry Smith```{eval-rst} 227*7f296bb3SBarry Smith.. bibliography:: /petsc.bib 228*7f296bb3SBarry Smith :filter: docname in docnames 229*7f296bb3SBarry Smith``` 230