xref: /petsc/doc/manual/dmstag.md (revision b59054469e8e75e7f1217f4456448261033ebd2d)
1(ch_stag)=
2
3# DMSTAG: Staggered, Structured Grid
4
5For structured (aka "regular") grids with staggered data (degrees of freedom potentially living on elements, faces, edges,
6and/or vertices), the `DMSTAG` object is available. This can
7be useful for problems in many domains, including fluid flow, MHD, and seismology.
8
9It is possible, though extremely cumbersome, to implement a staggered-grid code using multiple `DMDA` objects, or a single
10multi-component `DMDA` object where some degrees of freedom are unused.
11`DMSTAG` was developed for two main purposes:
12
131. To help manage some of the burden of choosing and adhering to the complex indexing conventions needed for staggered grids (in parallel)
142. To provide a uniform abstraction for which scalable solvers and preconditioners may be developed (in particular, using `PCFIELDSPLIT` and `PCMG`).
15
16`DMSTAG` is design to behave much
17like {ref}`DMDA <sec_struct>`, with a couple of important distinctions, and borrows some terminology
18from {doc}`DMPLEX <dmplex>`.
19
20## Terminology
21
22Like a `DMPLEX` object, a `DMSTAG` represents a [cell complex](https://en.wikipedia.org/wiki/CW_complex),
23distributed in parallel over the ranks of an `MPI_Comm`. It is, however,
24a very regular complex, consisting of a structured grid of $d$-dimensional cells, with $d \in \{1,2,3\}$,
25which are referred to as *elements*, $d-1$ dimensional cells defining boundaries between these elements,
26and the boundaries of the domain, and in 2 or more dimensions, boundaries of *these* cells,
27all the way down to 0 dimensional cells referred to as *vertices*. In 2 dimensions, the 1-dimensional
28element boundaries are referred to as *edges* or *faces*. In 3 dimensions, the 2-dimensional element boundaries
29are referred to as *faces* and the 1-dimensional boundaries between faces are referred to as *edges*
30The set of cells of a given dimension is referred to as a *stratum* (which one can think of as a level in DAG representation of the mesh); a `DMSTAG` object of dimension $d$
31represents a complete cell complex with $d+1$ *strata* (levels).
32
33In the description of any:`ch_unstructured` the cells at each level are referred to as *points*. Thus we adopt that terminology uniformly in PETSc and
34so furthermore in this document,
35point will refer to a cell.
36
37Each stratum has a constant number of unknowns (which may be zero) associated with each point (cell) on that level.
38The distinct unknowns associated with each point are referred to as *components*. For a `DMPLEX` there may be a different
39number of unknowns for each point on the same level.
40
41The structured grid, is like with `DMDA`, decomposed via a Cartesian product of decompositions in each dimension,
42giving a rectangular local subdomain on each rank. This is extended by an element-wise stencil width
43of *ghost* elements to create an atlas of overlapping patches.
44
45## Working with vectors and operators (matrices)
46
47`DMSTAG` allows the user to reason almost entirely about a global indexing of elements.
48Element indices are simply 1-3 `PetscInt` values, starting at $0$, in the
49back, bottom, left corner of the domain. For instance, element $(1,2,3)$, in 3D,
50is the element second from the left, third from the bottom, and fourth from the back
51(regardless of how many MPI ranks are used).
52
53To refer to points (elements, faces, edges, and vertices), a value of
54`DMStagStencilLocation` is used, relative to the element index. The element
55itself is referred to with `DMSTAG_ELEMENT`, the top right vertex (in 2D)
56or the top right edge (in 3D) with `DMSTAG_UP_RIGHT`, the back bottom left
57corner in 3D with `DMSTAG_BACK_DOWN_LEFT`, and so on.
58
59{numref}`figure_dmstag_indexing` gives a few examples in 2D.
60
61:::{figure} /images/manual/dmstag_indexing.svg
62:name: figure_dmstag_indexing
63
64Locations in `DMSTAG` are indexed according to global element indices (here, two in 2D) and a location name. Elements have unique names but other locations can be referred to in more than one way. Element colors correspond to a parallel decomposition, but locations on the grid have names which are invariant to this. Note that the face on the top right can be referred to as being to the left of a "dummy" element $(3,3)$ outside the physical domain.
65:::
66
67Crucially, this global indexing scheme does not include any "ghost" or "padding" unknowns outside the physical domain.
68This is useful for higher-level operations such as computing norms or developing physics-based solvers. However
69(unlike `DMDA`), this implies that the global `Vec` do not have a natural block structure, as different
70strata have different numbers of points (e.g. in 1D there is an "extra" vertex on the right). This regular block
71structure is, however, very useful for the *local* representation of the data, so in that case *dummy* DOF
72are included, drawn as grey in {numref}`figure_dmstag_local_global`.
73
74:::{figure} /images/manual/dmstag_local_global.svg
75:name: figure_dmstag_local_global
76
77Local and global representations for a 2D `DMSTAG` object, 3 by 4 elements, with one degree of freedom on each of the three strata: element (squares), faces (triangles), and vertices (circles). The cell complex is parallelized across 4 MPI ranks. In the global representation, the colors correspond to which rank holds the native representation of the unknown. The 4 local representations are shown, with an (elementwise) stencil "box" stencil width of 1. Unknowns are colored by their native rank. Dummy unknowns, which correspond to no global degree of freedom, are colored grey. Note that the local representations have a natural block size of 4, and the global representation has no natural block size.
78:::
79
80For working with `Vec` data, this approach is used to allow direct access to a multi-dimensional, regular-blocked
81array. To avoid the user having to know about the {ref}`internal numbering conventions used <sec_dmstag_numbering>`,
82helper functions are used to produce the proper final integer index for a given location and component, referred to as a "slot".
83Similarly to `DMDAVecGetArrayDOF()`, this uses a $d+1$ dimensional array in $d$ dimensions.
84The following snippet give an example of this usage.
85
86```{literalinclude} /../src/dm/impls/stag/tests/ex51.c
87:end-at: PetscCall(DMStagVecRestoreArray
88:start-at: /* Set
89```
90
91`DMSTAG` provides a stencil-based method for getting and setting entries of `Mat` and `Vec` objects.
92The follow excerpt from <a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/dm/impls/stag/tutorials/ex1.c.html">DMSTAG Tutorial ex1</a> demonstrates
93the idea. For more, see the manual page for `DMStagMatSetValuesStencil()`.
94
95```{literalinclude} /../src/dm/impls/stag/tutorials/ex1.c
96:end-at: PetscCall(DMStagMatSetValuesStencil
97:start-at: /* Velocity is either a BC
98```
99
100The array-based approach for `Vec` is likely to be more efficient than the stencil-based method just introduced above.
101
102## Coordinates
103
104`DMSTAG`, unlike `DMDA`, supports two approaches to defining coordinates. This is captured by which type of `DM`
105is used to represent the coordinates. No default is imposed, so the user must directly or indirectly call
106`DMStagSetCoordinateDMType()`.
107
108If a second `DMSTAG` object is used to represent coordinates in "explicit" form, behavior is much like with `DMDA` - the coordinate `DM`
109has $d$ DOF on each stratum corresponding to coordinates associated with each point.
110
111If `DMPRODUCT` is used instead, coordinates are represented by a `DMPRODUCT` object referring to a
112Cartesian product of 1D `DMSTAG` objects, each of which features explicit coordinates as just mentioned.
113
114Navigating these nested `DM` in `DMPRODUCT` can be tedious, but note the existence of helper functions like
115`DMStagSetUniformCoordinatesProduct()` and `DMStagGetProductCoordinateArrays()`.
116
117(sec_dmstag_numbering)=
118
119## Numberings and internal data layout
120
121While `DMSTAG` aims to hide the details of its internal data layout, for debugging, optimization, and
122customization purposes, it can be important to know how `DMSTAG` internally numbers unknowns.
123
124Internally, each point is canonically associated with an element (top-level point (cell)). For purposes of local,
125regular-blocked storage, an element is grouped with lower-dimensional points left of, below ("down"), and behind ("back") it.
126This means that "canonical" values of `DMStagStencilLocation` are `DMSTAG_ELEMENT`, plus all entries consisting only of "LEFT", "DOWN", and "BACK". In general, these are the most efficient values to use, unless convenience dictates otherwise, as they are the ones used internally.
127
128When creating the decomposition of the domain to local ranks, and extending these local domains to handle overlapping halo regions and boundary ghost unknowns, this same per-element association is used. This has the advantage of maintaining a regular blocking, but may not be optimal in some situations in terms of data movement.
129
130Numberings are, like `DMDA`, based on a local "x-fastest, z-slowest" or "PETSc" ordering of elements (see {ref}`sec_ao`), with ordering of locations canonically associated with each element decided by considering unknowns on each point
131to be located at the center of their point, and using a nested ordering of the same style. Thus, in 3-D, the ordering of the 8 canonical `DMStagStencilLocation` values associated
132with an element is
133
134```
135DMSTAG_BACK_DOWN_LEFT
136DMSTAG_BACK_DOWN
137DMSTAG_BACK_LEFT
138DMSTAG_BACK
139DMSTAG_DOWN_LEFT
140DMSTAG_DOWN
141DMSTAG_LEFT
142DMSTAG_ELEMENT
143```
144
145Multiple DOF associated with a given point are stored sequentially (as with `DMDA`).
146
147For local `Vec`s, this gives a regular-blocked numbering, with the same number of unknowns associated with each element, including some "dummy" unknowns which to not correspond to any (local or global) unknown in the global representation. See {numref}`figure_dmstag_numbering_local` for an example.
148
149In the global representation, only physical unknowns are numbered (using the same "Z" ordering for unknowns which are present), giving irregular numbers of unknowns, depending on whether a domain boundary is present. See {numref}`figure_dmstag_numbering_global` for an example.
150
151:::{figure} /images/manual/dmstag_numbering_global.svg
152:name: figure_dmstag_numbering_global
153
154Global numbering scheme for a 2D `DMSTAG` object with one DOF per stratum. Note that the numbering depends on the parallel decomposition (over 4 ranks, here).
155:::
156
157:::{figure} /images/manual/dmstag_numbering_local.svg
158:name: figure_dmstag_numbering_local
159
160Local numbering scheme on rank 1 (Cf. {numref}`figure_dmstag_local_global`) for a 2D `DMSTAG` object with one DOF per stratum. Note that dummy locations (grey) are used to give a regular block size (here, 4).
161:::
162
163It should be noted that this is an *interlaced* (AoS) representation. If a segregated (SoA) representation is required,
164one should use `DMCOMPOSITE` collecting several `DMSTAG` objects, perhaps using `DMStagCreateCompatibleDMStag()` to
165quickly create additional `DMSTAG` objects from an initial one.
166