The Earth mantle is approximated via a thick spherical shell \(\Omega\) , i.e., a hollow sphere centered at the origin
\[ \Omega = \{\mathbf{x} \in \mathbb{R}^3 : r_\mathrm{min} \leq \|\mathbf{x}\| \leq r_\mathrm{max} \} \]
A corresponding mesh is constructed by splitting the outer surface of \(\Omega\) into 10 spherical diamonds that are extruded towards (or equivalently away from) the origin.
The figures/videos below show the diamonds in a three-dimensional visualization (each diamond is refined 4 times in lateral and 4 times in radial direction).
Single diamond (diamond_id == 0):
Northern (0 <= diamond_id <= 4) and southern diamonds (5 <= diamond_id <= 9):
Unfolding the surface partitioning, we can visualize the surface of the 10 spherical diamonds as a net that when curved and pieced together recovers the spherical shell:
Indexing in radial direction always goes from the inner boundary to the outer boundary. Note that the extrusion in radial direction is not visible from the net.
Each diamond can (optionally) be subdivided in lateral and radial direction. Below, two angles of an exploded diamond (diamond ID 0, one lateral and one radial subdomain refinement level) are shown:
After radial and lateral refinement of the diamonds, each subdomain can be associated with a globally unique identifying tuple
as illustrated in the figure below (for one refinement step in the lateral direction; note that the radial refinement is not visible in the figure and indicated by the colon in the tuple):
The subdomain_id is implemented in the class terra::grid::shell::SubdomainInfo.
The information about the global structure is captured in the terra::grid::shell::DomainInfo class. That class does not compute any node coordinates. It just stores the refinement information, i.e., how many subdomains are present for each diamond in either direction. In the lateral direction, refinement currently has to be uniform. In the radial direction, the concrete radii of the layers can be specified. For more details refer to the documentation of terra::grid::shell::DomainInfo.
Subdomains on the same MPI process are sorted by their global subdomain_id (it is sortable and globally unique) and continuously assigned to an integer local_subdomain_id that ranges from 0 to the number of process-local subdomains minus 1. The local_subdomain_id is then the first index of the 4D (or 5D) data grids introduced above.
For instance, for a scalar data array data the expression
accesses the node with
The mapping from the subdomain_id (type SubdomainInfo) to the local_subdomain_id (type int) is performed during set up and stored together with other information in the corresponding terra::grid::shell::DistributedDomain instance. More details are found in the parallelization section.
The concrete coordinates of the nodes are computed with two functions:
coords_shell( local_subdomain_id, x_index, y_index, cartesian_coord ).coords_radii( local_subdomain_id, r_index ) The cartesian coordinate of a node ( local_subdomain_id, x_index, y_index, r_index ) can then be computed viaThis is implemented in terra::grid::shell::coords. The radius is obviously just coords_radii( local_subdomain_id, r_index ).