Meshes
A Mesh
is a division of a domain into elements.
Mesh types
ClimaCore.Meshes.AbstractMesh
— TypeAbstractMesh{dim}
A Mesh
is an object which represents how we discretize a domain into elements.
It should be lightweight (i.e. exists on all MPI ranks), e.g for meshes stored in a file, it would contain the filename.
Face and vertex numbering
In 1D, faces and vertices are the same, and both are numbered [1,2]
.
In 2D, a face is a line segment between to vertices, and both are numbered [1,2,3,4]
, in a counter-clockwise direction.
v4 f3 v3
o-----------------o
| | face vertices
| | f1 => v1 v2
f4 | | f2 f2 => v2 v3
| | f3 => v3 v4
| | f4 => v4 v1
| |
o-----------------o
v1 f1 v2
Interface
A subtype of AbstractMesh
should define the following methods:
domain(mesh)
elements(mesh)
is_boundary_face(mesh, elem, face)
boundary_face_name(mesh, elem, face)
opposing_face(mesh, elem, face)
coordinates(mesh, elem, vert)
containing_element
(optional)
The following types/methods are provided by AbstractMesh
:
ClimaCore.Meshes.IntervalMesh
— TypeIntervalMesh <: AbstractMesh
A 1D mesh on an IntervalDomain
.
Constuctors
IntervalMesh(domain::IntervalDomain, faces::AbstractVector)
Construct a 1D mesh with face locations at faces
.
IntervalMesh(domain::IntervalDomain[, stretching=Uniform()]; nelems=)
Constuct a 1D mesh on domain
with nelems
elements, using stretching
. Possible values of stretching
are:
ClimaCore.Meshes.RectilinearMesh
— TypeRectilinearMesh <: AbstractMesh2D
Constructors
RectilinearMesh(domain::RectangleDomain, n1, n2)
Construct a RectilinearMesh
of equally-spaced n1
by n2
elements on domain
.
RectilinearMesh(intervalmesh1::IntervalMesh1, intervalmesh2::IntervalMesh2)
Construct the product mesh of intervalmesh1
and intervalmesh2
.
ClimaCore.Meshes.AbstractCubedSphere
— TypeAbstractCubedSphere <: AbstractMesh2D
This is an abstract type of cubed-sphere meshes on SphereDomain
s. A cubed-sphere mesh has 6 panels, laid out as follows:
: Panel 1 :
+-------------+-------------+
| +x1 | +x1 |
| | |
| Panel | Panel |
|+x3 5 -x3|-x2 6 +x2|
| -x2 | -x3 |
| | |
| -x1 | -x1 |
+-------------+-------------+-------------+
| -x2 | -x2 |
| | |
| Panel | Panel |
|+x1 3 -x1|+x3 4 -x3|
| +x3 | -x1 |
| | |
| +x2 | +x2 |
+-------------+-------------+-------------+
| +x3 | +x3 |
| | |
| Panel | Panel |
|-x2 1 +x2|+x1 2 -x1|
| +x1 | +x2 |
| | |
| -x3 | -x3 |
+-------------+-------------+
: Panel 6 :
This is the same panel ordering used by the S2 Geometry library (though we use 1-based instead of 0-based numering).
Elements are indexed by a CartesianIndex{3}
object, where the components are:
- horizontal element index (left to right) within each panel.
- vertical element index (bottom to top) within each panel.
- panel number
Subtypes should have the following fields:
domain
: aSphereDomain
ne
: number of elements across each panel
External links
ClimaCore.Meshes.EquiangularCubedSphere
— TypeEquiangularCubedSphere <: AbstractCubedSphere
An equiangular gnomonic mesh proposed by [8]. Uses the element indexing convention of AbstractCubedSphere
.
Constructors
EquiangularCubedSphere(
domain::Domains.SphereDomain,
ne::Integer,
localelementmap=NormalizedBilinearMap()
)
Constuct an EquiangularCubedSphere
on domain
with ne
elements across each panel.
ClimaCore.Meshes.EquidistantCubedSphere
— TypeEquidistantCubedSphere <: AbstractCubedSphere
An equidistant gnomonic mesh outlined in [9] and [10]. Uses the element indexing convention of AbstractCubedSphere
.
Constructors
EquidistantCubedSphere(domain::Domains.SphereDomain, ne::Integer)
Constuct an EquidistantCubedSphere
on domain
with ne
elements across each panel.
ClimaCore.Meshes.ConformalCubedSphere
— TypeConformalCubedSphere <: AbstractCubedSphere
A conformal mesh outlined in [9]. Uses the element indexing convention of AbstractCubedSphere
.
Constructors
ConformalCubedSphere(domain::Domains.SphereDomain, ne::Integer)
Constuct a ConformalCubedSphere
on domain
with ne
elements across each panel.
Local element map
ClimaCore.Meshes.LocalElementMap
— TypeLocalElementMap
An abstract type of mappings from the reference element to a physical domain.
ClimaCore.Meshes.IntrinsicMap
— TypeIntrinsicMap()
This LocalElementMap
uses the intrinsic mapping of the cubed sphere to map the reference element to the physical domain.
ClimaCore.Meshes.NormalizedBilinearMap
— TypeNormalizedBilinearMap()
The LocalElementMap
for meshes on spherical domains of [11]. It uses bilinear interpolation between the Cartesian coordinates of the element vertices, then normalizes the result to lie on the sphere.
Mesh stretching
ClimaCore.Meshes.Uniform
— TypeUniform()
Use uniformly-sized elements.
ClimaCore.Meshes.ExponentialStretching
— TypeExponentialStretching(H::FT)
Apply exponential stretching to the domain when constructing elements. H
is the scale height (a typical atmospheric scale height H ≈ 7.5
km).
For an interval $[z_0,z_1]$, this makes the elements uniformally spaced in $\zeta$, where
\[\zeta = \frac{1 - e^{-\eta/h}}{1-e^{-1/h}},\]
where $\eta = \frac{z - z_0}{z_1-z_0}$, and $h = \frac{H}{z_1-z_0}$ is the non-dimensional scale height. If reverse_mode
is true
, the smallest element is at the top, and the largest at the bottom (this is typical for land model configurations).
Then, the user can define a stretched mesh via
ClimaCore.Meshes.IntervalMesh(interval_domain, ExponentialStretching(H); nelems::Int, reverse_mode = false)
faces
contain reference z without any warping.
ClimaCore.Meshes.GeneralizedExponentialStretching
— TypeGeneralizedExponentialStretching(dz_bottom::FT, dz_top::FT)
Apply a generalized form of exponential stretching to the domain when constructing elements. dz_bottom
and dz_top
are target element grid spacings at the bottom and at the top of the vertical column domain (m). In typical atmosphere configurations, dz_bottom
is the smallest grid spacing and dz_top
the largest one. On the other hand, for typical land configurations, dz_bottom
is the largest grid spacing and dz_top
the smallest one.
For land configurations, use reverse_mode
= true
(default value false
).
Then, the user can define a generalized stretched mesh via
ClimaCore.Meshes.IntervalMesh(interval_domain, GeneralizedExponentialStretching(dz_bottom, dz_top); nelems::Int, reverse_mode = false)
faces
contain reference z without any warping.
ClimaCore.Meshes.HyperbolicTangentStretching
— TypeHyperbolicTangentStretching(dz_surface::FT)
Apply a hyperbolic tangent stretching to the domain when constructing elements. dz_surface
is the target element grid spacing at the surface. In typical atmosphere configuration, it is the grid spacing at the bottom of the vertical column domain (m). On the other hand, for typical land configurations, it is the grid spacing at the top of the vertical column domain.
For an interval $[z_0,z_1]$, this makes the elements uniformally spaced in $\zeta$, where
\[\eta = 1 - \frac{tanh[\gamma(1-\zeta)]}{tanh(\gamma)},\]
where $\eta = \frac{z - z_0}{z_1-z_0}$. The stretching parameter $\gamma$ is chosen to achieve a given resolution dz_surface
at the surface.
Then, the user can define a stretched mesh via
ClimaCore.Meshes.IntervalMesh(interval_domain, HyperbolicTangentStretching(dz_surface); nelems::Int, reverse_mode)
reverse_mode
is default to false for atmosphere configurations. For land configurations, use reverse_mode
= true
.
faces
contain reference z without any warping.
Mesh utilities
ClimaCore.Meshes.truncate_mesh
— Functiontruncate_mesh(
parent_mesh::AbstractMesh,
trunc_domain::IntervalDomain{CT},
)
Constructs an IntervalMesh
, truncating the given parent_mesh
defined on a truncated trunc_domain
. The truncation preserves the number of degrees of freedom covering the space from the trunc_domain
's z_bottom
to z_top
, adjusting the stretching.
Interfaces
ClimaCore.Meshes.domain
— FunctionMeshes.domain(mesh::AbstractMesh)
The domain (a subtype of Domains.AbstractDomain
) on which the mesh is defined.
ClimaCore.Meshes.elements
— FunctionMeshes.elements(mesh::AbstractMesh)
An iterator over the elements of a mesh. Elements of a mesh can be of any type.
ClimaCore.Meshes.nelements
— Functionnelements(mesh::AbstractMesh)
The number of elements in the mesh.
ClimaCore.Meshes.is_boundary_face
— FunctionMeshes.is_boundary_face(mesh::AbstractMesh, elem, face::Int)::Bool
Determine whether face face
of element elem
is on the boundary of mesh
.
elem
should be an element of elements(mesh)
.
ClimaCore.Meshes.boundary_face_name
— FunctionMeshes.boundary_face_name(mesh::AbstractMesh, elem, face::Int)::Union{Symbol,Nothing}
The name of the boundary facing face
of element elem
, or nothing
if it is not on the boundary.
ClimaCore.Meshes.opposing_face
— Functionopelem, opface, reversed = Meshes.opposing_face(mesh::AbstractMesh, elem, face::Int)
The element and face (opelem
, opface
) that oppose face face
of element elem
.
ClimaCore.Meshes.coordinates
— FunctionMeshes.coordinates(mesh, elem, vert::Int)
Meshes.coordinates(mesh, elem, ξ::SVector)
Return the physical coordinates of a point in an element elem
of mesh
. The position of the point can either be a vertex number vert
or the coordinates ξ
in the reference element.
ClimaCore.Meshes.containing_element
— Functionelem = Meshes.containing_element(mesh::AbstractMesh, coord)
The element elem
in mesh
containing the coordinate coord
. If the coordinate falls on the boundary between two or more elements, an arbitrary element is chosen.
ClimaCore.Meshes.reference_coordinates
— Functionξ = Meshes.reference_coordinates(mesh::AbstractMesh, elem, coord)
An SVector
of coordinates in the reference element such that
Meshes.coordinates(mesh, elem, ξ) == coord
This can be used for interpolation to a specific point.
ClimaCore.Meshes.SharedVertices
— TypeMeshes.SharedVertices(mesh, elem, vert)
An iterator over (element, vertex) pairs that are shared with (elem,vert)
.
ClimaCore.Meshes.face_connectivity_matrix
— FunctionM = Meshes.face_connectivity_matrix(mesh, elemorder = elements(mesh))
Construct a Bool
-valued SparseCSCMatrix
containing the face connections of mesh
. Elements are indexed according to elemorder
.
Note that M[i,i] == true
only if two distinct faces of element i
are connected.
ClimaCore.Meshes.vertex_connectivity_matrix
— FunctionM = Meshes.vertex_connectivity_matrix(mesh, elemorder = elements(mesh))
Construct a Bool
-valued SparseCSCMatrix
containing the vertex connections of mesh
. Elements are indexed according to elemorder
.
Note that M[i,i] == true
only if two distinct vertices of element i
are connected.
ClimaCore.Meshes.linearindices
— FunctionMeshes.linearindices(elemorder)
Given a data structure elemorder[i] = elem
that orders elements, construct the inverse map from orderindex = linearindices(elemorder)
such that orderindex[elem] = i
.
This will try to use the most efficient structure available.
ClimaCore.Meshes.element_horizontal_length_scale
— FunctionMeshes.element_horizontal_length_scale(mesh::AbstractMesh)
The approximate length scale (in units of distance) of the elements of the mesh.