DSS
ClimaCore.Topologies.dss_transform
— Functiondss_transform(arg, local_geometry, weight, I)
Transfrom arg[I]
to a basis for direct stiffness summation (DSS). Transformations only apply to vector quantities.
local_geometry[I]
is the relevantLocalGeometry
object. If it isnothing
, then no transformation is performedweight[I]
is the relevant DSS weights. Ifweight
isnothing
, then the result is simply summation.
ClimaCore.Topologies.dss_transform!
— Functiondss_transform!(
device::ClimaComms.AbstractDevice,
dss_buffer::DSSBuffer,
data::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
local_geometry::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
dss_weights::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
perimeter::Perimeter2D,
localelems::AbstractVector{Int},
)
Transforms vectors from Covariant axes to physical (local axis), weights the data at perimeter nodes, and stores result in the perimeter_data
array. This function calls the appropriate version of dss_transform!
based on the data layout of the input arguments.
Arguments:
dss_buffer
:DSSBuffer
generated bycreate_dss_buffer
function for field datadata
: field datalocal_geometry
: local metric information defined at each nodedss_weights
: local dss weights for horizontal spaceperimeter
: perimeter iteratorlocalelems
: list of local elements to perform transformation operations on
Part of ClimaCore.Spaces.weighted_dss!
.
function dss_transform!(
::ClimaComms.AbstractCPUDevice,
perimeter_data::Union{DataLayouts.VIFH, DataLayouts.VIHF},
data::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
perimeter::Perimeter2D,
local_geometry::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
dss_weights::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
localelems::Vector{Int},
)
Transforms vectors from Covariant axes to physical (local axis), weights the data at perimeter nodes, and stores result in the perimeter_data
array.
Arguments:
perimeter_data
: contains the perimeter field data, represented on the physical axis, corresponding to the full field data indata
data
: field dataperimeter
: perimeter iteratorlocal_geometry
: local metric information defined at each nodedss_weights
: local dss weights for horizontal spacelocalelems
: list of local elements to perform transformation operations on
Part of ClimaCore.Spaces.weighted_dss!
.
ClimaCore.Topologies.dss_untransform!
— Functiondss_untransform!(
device::ClimaComms.AbstractDevice,
dss_buffer::DSSBuffer,
data::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
local_geometry::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF},
perimeter::AbstractPerimeter,
)
Transforms the DSS'd local vectors back to Covariant12 vectors, and copies the DSS'd data from the perimeter_data
to data
. This function calls the appropriate version of dss_transform!
function based on the data layout of the input arguments.
Arguments:
dss_buffer
:DSSBuffer
generated bycreate_dss_buffer
function for field datadata
: field datalocal_geometry
: local metric information defined at each nodeperimeter
: perimeter iteratorlocalelems
: list of local elements to perform transformation operations on
Part of ClimaCore.Spaces.weighted_dss!
.
ClimaCore.Topologies.dss_untransform
— Functiondss_untransform(T, targ, local_geometry, I...)
Transform targ[I...]
back to a value of type T
after performing direct stiffness summation (DSS).
ClimaCore.Topologies.dss_local_vertices!
— Functiondss_local_vertices!(
perimeter_data::DataLayouts.VIFH,
perimeter::Perimeter2D,
topology::Topology2D,
)
Apply dss to local vertices.
ClimaCore.Topologies.dss_local!
— Functionfunction dss_local!(
::ClimaComms.AbstractCPUDevice,
perimeter_data::DataLayouts.VIFH,
perimeter::AbstractPerimeter,
topology::AbstractTopology,
)
Performs DSS on local vertices and faces.
Part of ClimaCore.Spaces.weighted_dss!
.
ClimaCore.Topologies.dss_local_ghost!
— Functionfunction dss_local_ghost!(
::ClimaComms.AbstractCPUDevice,
perimeter_data::DataLayouts.VIFH,
perimeter::AbstractPerimeter,
topology::AbstractTopology,
)
Computes the "local" part of ghost vertex dss. (i.e. it computes the summation of all the shared local vertices of a unique ghost vertex and stores the value in each of the local vertex locations in perimeter_data
)
Part of ClimaCore.Spaces.weighted_dss!
.
ClimaCore.Topologies.dss_ghost!
— Functiondss_ghost!(
device::ClimaComms.AbstractCPUDevice,
perimeter_data::DataLayouts.VIFH,
perimeter::AbstractPerimeter,
topology::AbstractTopology,
)
Sets the value for all local vertices of each unique ghost vertex, in perimeter_data
, to that of the representative ghost vertex.
Part of ClimaCore.Spaces.weighted_dss!
.
ClimaCore.Topologies.create_dss_buffer
— Functioncreate_dss_buffer(data, space)
Creates a DSSBuffer
for the field data corresponding to data
Spaces.create_dss_buffer(fv::FieldVector)
Create a NamedTuple of buffers for communicating neighbour information of each Field in fv
. In this NamedTuple, the name of each field is mapped to the buffer.
Spaces.create_dss_buffer(field::Field)
Create a buffer for communicating neighbour information of field
.
create_dss_buffer(
data::Union{DataLayouts.IJFH{S}, DataLayouts.IJHF{S}, DataLayouts.VIJFH{S}, DataLayouts.VIJHF{S}},
topology::Topology2D,
local_geometry::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF, Nothing} = nothing,
dss_weights::Union{DataLayouts.IJFH, DataLayouts.IJHF, DataLayouts.VIJFH, DataLayouts.VIJHF, Nothing} = nothing,
) where {S}
Creates a DSSBuffer
for the field data corresponding to data
ClimaCore.Topologies.fill_send_buffer!
— Functionfill_send_buffer!(::ClimaComms.AbstractCPUDevice, dss_buffer::DSSBuffer; synchronize=true)
Loads the send buffer from perimeter_data
. For unique ghost vertices, only data from the representative vertices which store result of "ghost local" DSS are loaded.
Part of ClimaCore.Spaces.weighted_dss!
.
ClimaCore.Topologies.DSSBuffer
— TypeDSSBuffer{G, D, A, B}
Fields
graph_context
: ClimaComms graph context for communicationperimeter_data
: PerimeterDataLayout
object: typically aVIFH{TT,Nv,Np,Nh}
orVIHF{TT,Nv,Np,Nh}
, whereTT
is the transformed type,Nv
is the number of vertical levels, andNp
is the length of the perimetersend_date
: send bufferAbstractVector{FT}
recv_data
: recv bufferAbstractVector{FT}
send_buf_idx
: indexing array for loading send buffer fromperimeter_data
recv_buf_idx
: indexing array for loading (and summing) data from recv buffer tointernal_elems
: internal local elements (lidx)perimeter_elems
: local elements (lidx) located on process boundary
ClimaCore.Topologies.load_from_recv_buffer!
— Functionload_from_recv_buffer!(::ClimaComms.AbstractCPUDevice, dss_buffer::DSSBuffer)
Adds data from the recv buffer to the corresponding location in perimeter_data
. For ghost vertices, this data is added only to the representative vertices. The values are then scattered to other local vertices corresponding to each unique ghost vertex in dss_local_ghost
.
Part of ClimaCore.Spaces.weighted_dss!
.
ClimaCore.Topologies.dss!
— Functiondss!(data, topology)
Computed unweighted/pure DSS of data
.
ClimaCore.Spaces.weighted_dss_start!
— Functionweighted_dss_start!(
data::Union{
DataLayouts.IFH,
DataLayouts.IHF,
DataLayouts.VIFH,
DataLayouts.VIHF,
DataLayouts.IJFH,
DataLayouts.IJHF,
DataLayouts.VIJFH,
DataLayouts.VIJHF,
},
space::Union{
AbstractSpectralElementSpace,
ExtrudedFiniteDifferenceSpace,
},
dss_buffer::Union{DSSBuffer, Nothing},
)
It comprises of the following steps:
1). Apply Spaces.dss_transform!
on perimeter elements. This weights and tranforms vector fields to physical basis if needed. Scalar fields are weighted. The transformed and/or weighted perimeter data
is stored in perimeter_data
.
2). Apply Spaces.dss_local_ghost!
This computes partial weighted DSS on ghost vertices, using only the information from local
vertices.
3). Spaces.fill_send_buffer!
Loads the send buffer from perimeter_data
. For unique ghost vertices, only data from the representative ghost vertices which store result of "ghost local" DSS are loaded.
4). Start DSS communication with neighboring processes
ClimaCore.Spaces.weighted_dss_internal!
— Functionweighted_dss_internal!(
data::Union{
DataLayouts.IFH,
DataLayouts.IHF,
DataLayouts.VIFH,
DataLayouts.VIHF,
DataLayouts.IJFH,
DataLayouts.IJHF,
DataLayouts.VIJFH,
DataLayouts.VIJHF,
},
space::Union{
AbstractSpectralElementSpace,
ExtrudedFiniteDifferenceSpace,
},
dss_buffer::DSSBuffer,
)
1). Apply Spaces.dss_transform!
on interior elements. Local elements are split into interior and perimeter elements to facilitate overlapping of communication with computation.
2). Probe communication
3). Spaces.dss_local!
computes the weighted DSS on local vertices and faces.
ClimaCore.Spaces.weighted_dss_ghost!
— Functionweighted_dss_ghost!(
data::Union{
DataLayouts.IFH,
DataLayouts.IHF,
DataLayouts.VIFH,
DataLayouts.VIHF,
DataLayouts.IJFH,
DataLayouts.IJHF,
DataLayouts.VIJFH,
DataLayouts.VIJHF,
},
space::Union{
AbstractSpectralElementSpace,
ExtrudedFiniteDifferenceSpace,
},
dss_buffer::Union{DSSBuffer, Nothing},
)
1). Finish communications.
2). Call Spaces.load_from_recv_buffer!
After the communication is complete, this adds data from the recv buffer to the corresponding location in perimeter_data
. For ghost vertices, this data is added only to the representative vertices. The values are then scattered to other local vertices corresponding to each unique ghost vertex in dss_local_ghost
.
3). Call Spaces.dss_untransform!
on all local elements. This transforms the DSS'd local vectors back to Covariant12 vectors, and copies the DSS'd data from the perimeter_data
to data
.
ClimaCore.Spaces.weighted_dss!
— Functionfunction weighted_dss!(
data::Union{
DataLayouts.IFH,
DataLayouts.IHF,
DataLayouts.VIFH,
DataLayouts.VIHF,
DataLayouts.IJFH,
DataLayouts.IJHF,
DataLayouts.VIJFH,
DataLayouts.VIJHF,
},
space::Union{
AbstractSpectralElementSpace,
ExtrudedFiniteDifferenceSpace,
},
dss_buffer::Union{DSSBuffer, Nothing},
)
Computes weighted dss of data
.
It comprises of the following steps:
1). Spaces.weighted_dss_start!
Spaces.weighted_dss!(fv::FieldVector, dss_buffer = Spaces.create_dss_buffer(fv))
Apply weighted direct stiffness summation (DSS) to each field in fv
. If a dss_buffer
object is not provided, a buffer will be created for each field in fv
. Note that using the Pair
interface here parallelizes the weighted_dss!
calls.
Spaces.weighted_dss!(f::Field, dss_buffer = Spaces.create_dss_buffer(field))
Apply weighted direct stiffness summation (DSS) to f
. This operates in-place (i.e. it modifies the f
). ghost_buffer
contains the necessary information for communication in a distributed setting, see Spaces.create_dss_buffer
.
This is a projection operation from the piecewise polynomial space $\mathcal{V}_0$ to the continuous space $\mathcal{V}_1 = \mathcal{V}_0 \cap \mathcal{C}_0$, defined as the field $\theta \in \mathcal{V}_1$ such that for all $\phi \in \mathcal{V}_1$
\[\int_\Omega \phi \theta \,d\Omega = \int_\Omega \phi f \,d\Omega\]
In matrix form, we define $\bar \theta$ to be the unique global node representation, and $Q$ to be the "scatter" operator which maps to the redundant node representation $\theta$
\[\theta = Q \bar \theta\]
Then the problem can be written as
\[(Q \bar\phi)^\top W J Q \bar\theta = (Q \bar\phi)^\top W J f\]
which reduces to
\[\theta = Q \bar\theta = Q (Q^\top W J Q)^{-1} Q^\top W J f\]
Spaces.weighted_dss!(field1 => ghost_buffer1, field2 => ghost_buffer2, ...)
Call Spaces.weighted_dss!
on multiple fields at once, overlapping communication as much as possible.
ClimaCore.Spaces.unique_nodes
— Functionunique_nodes(space::SpectralElementSpace2D)
An iterator over the unique nodes of space
. Each node is represented by the first ((i,j), e)
triple.
This function is experimental, and may change in future.