DSS
Direct stiffness summation makes a field on a continuous spectral-element space single-valued at element boundaries (DSS and numerical fluxes). Spaces.weighted_dss! is the user-level entry point; its internal phases are the Topologies functions, exposed for callers that need to overlap communication with computation, or to run DSS directly on a DataLayout.
ClimaCore.Spaces.weighted_dss! — Function
weighted_dss!(data, space, dss_buffer)Compute the weighted direct stiffness summation (DSS) of data in place: values at nodes shared between elements are replaced by their weighted average. On a discontinuous (DG) space this is a no-op.
It consists of the following steps:
Spaces.weighted_dss!(fv::FieldVector, dss_buffer = Spaces.create_dss_buffer(fv))Apply weighted direct stiffness summation (DSS) to each field in fv in place. If dss_buffer is not provided, a buffer is created for each field in fv. The fields are passed to the Pair method of Spaces.weighted_dss!, which overlaps their communication.
Spaces.weighted_dss!(f::Field, dss_buffer = Spaces.create_dss_buffer(field))Apply weighted direct stiffness summation (DSS) to f in place and return f. dss_buffer holds the buffers for communication in a distributed setting; see Spaces.create_dss_buffer. On a discontinuous (DG) space this is a no-op.
This is a projection operation from the piecewise polynomial space $V_0$ to the continuous space $V_1 = V_0 \cap C_0$, defined as the field $\theta \in V_1$ such that for all $\phi \in 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 => dss_buffer1, field2 => dss_buffer2, ...)Call Spaces.weighted_dss! on multiple fields at once, overlapping the communication of all fields with computation. Returns nothing.
ClimaCore.Spaces.weighted_dss_start! — Function
weighted_dss_start!(data, space, dss_buffer)Start the weighted DSS of data: prepare the perimeter data of the elements on the process boundary and begin communication with neighboring processes. Returns nothing.
It consists of the following steps:
- Apply
Spaces.dss_transform!on perimeter elements. This weights, and transforms to the physical basis if needed, the vector fields; scalar fields are weighted. The result is stored indss_buffer.perimeter_data. - Apply
Spaces.dss_local_ghost!, which computes the partial weighted DSS on ghost vertices using only the information from local vertices. - Apply
Spaces.fill_send_buffer!, which loads the send buffer fromperimeter_data. For unique ghost vertices, only the representative vertices, which hold the result of the "ghost local" DSS, are loaded. - Start the DSS communication with neighboring processes.
ClimaCore.Spaces.weighted_dss_internal! — Function
weighted_dss_internal!(data, space, dss_buffer)Perform the part of the weighted DSS of data that needs no communication, while the communication started by Spaces.weighted_dss_start! is in flight. Returns nothing.
It consists of the following steps:
- Apply
Spaces.dss_transform!on interior elements. Local elements are split into interior and perimeter elements so that communication overlaps with computation. - Apply
Spaces.dss_local!, which computes the weighted DSS on local vertices and faces. - Apply
Spaces.dss_untransform!on interior elements.
On a 1D spectral element space, the whole DSS is performed here with dss_1d!.
ClimaCore.Spaces.weighted_dss_ghost! — Function
weighted_dss_ghost!(data, space, dss_buffer)Finish the weighted DSS of data started by Spaces.weighted_dss_start!. Returns data.
It consists of the following steps:
- Finish the communication.
- Apply
Spaces.load_from_recv_buffer!, which adds the data in the receive buffer to the corresponding locations inperimeter_data. For ghost vertices, the data is added only to the representative vertices; the values are then scattered to the other local vertices of each unique ghost vertex bydss_ghost!. - Apply
Spaces.dss_untransform!on perimeter elements, which transforms the summed vectors back to their original basis and copies the summed data fromperimeter_datatodata.
ClimaCore.Spaces.unique_nodes — Function
unique_nodes(space::SpectralElementSpace2D)Return an iterator over the unique nodes of space. Each node is represented by the first ((i, j), e) triple at which it occurs.
This function is experimental, and may change in future.
Buffers
ClimaCore.Topologies.DSSBuffer — Type
DSSBuffer{T, G, D, A, B, VI}Buffers and index maps for the direct stiffness summation (DSS) of one data layout with element type T on a Topology2D. Construct with create_dss_buffer(data, topology, local_geometry = nothing, dss_weights = nothing).
Fields
graph_context:ClimaCommsgraph context for communication.perimeter_data:DataLayoutholding the (transformed) values at the perimeter nodes of each element.send_data: Send buffer, anAbstractVector{FT}.recv_data: Receive buffer, anAbstractVector{FT}.send_buf_idx: Indexing array for loading the send buffer fromperimeter_data.recv_buf_idx: Indexing array for adding the receive buffer intoperimeter_data.internal_elems: Local elements (lidx) that touch no ghost element.perimeter_elems: Local elements (lidx) on the process boundary.
ClimaCore.Topologies.create_dss_buffer — Function
create_dss_buffer(data, space)Create a Topologies.DSSBuffer for the field data data on space. Return nothing if space is discontinuous (DG) or has no second horizontal dimension (1D spectral element spaces use dss_1d! and need no buffer).
Spaces.create_dss_buffer(fv::FieldVector)Create a NamedTuple mapping the name of each field in fv to its DSS buffer.
Spaces.create_dss_buffer(field::Field)Create a DSS buffer for communicating the neighbor information of field, or nothing if field needs no buffer.
ClimaCore.Topologies.Perimeter2D — Type
Perimeter2D(Nq)Construct an iterator over the (i, j) node indices on the perimeter of a 2D spectral element with Nq nodes per dimension (polynomial degree Nq - 1). The four vertices come first, followed by the interior nodes of each face.
Phases
ClimaCore.Topologies.dss! — Function
dss!(data, topology)Perform unweighted DSS of data in place: values at nodes shared between elements are replaced by their sum. Returns nothing.
ClimaCore.Topologies.dss_load_perimeter_data! — Function
dss_load_perimeter_data!(device, dss_buffer, data, perimeter)Copy the values of data at the element-perimeter nodes given by perimeter into dss_buffer.perimeter_data. This is the first phase of a DSS operation; the untransformed counterpart of dss_transform!, used when data needs no local geometry transformation.
Part of ClimaCore.Spaces.weighted_dss!; see also DSSBuffer.
ClimaCore.Topologies.dss_local! — Function
dss_local!(device, perimeter_data, perimeter, topology)Perform DSS on the local vertices and interior faces of topology: the values in perimeter_data at nodes shared between local elements are replaced by their sum.
Part of ClimaCore.Spaces.weighted_dss!.
ClimaCore.Topologies.dss_local_ghost! — Function
dss_local_ghost!(device, perimeter_data, perimeter, topology)Compute the "local" part of the ghost-vertex DSS: for each unique ghost vertex, sum the values of all its local vertices and store the sum at each of those local vertex locations in perimeter_data.
Part of ClimaCore.Spaces.weighted_dss!.
ClimaCore.Topologies.fill_send_buffer! — Function
fill_send_buffer!(topology, data, ghost_buffer::GhostBuffer)Load the send buffer of ghost_buffer with the data of the elements that neighboring processes need for their ghost elements. Returns nothing.
fill_send_buffer!(device, dss_buffer)Load the send buffer of dss_buffer from its perimeter_data. For unique ghost vertices, only the representative vertices, which hold the result of the "ghost local" DSS, are loaded.
Part of ClimaCore.Spaces.weighted_dss!.
ClimaCore.Topologies.load_from_recv_buffer! — Function
load_from_recv_buffer!(device, dss_buffer)Add the data in the receive buffer of dss_buffer to the corresponding locations in its perimeter_data. For ghost vertices, the data is added only to the representative vertices; dss_ghost! then scatters the values to the other local vertices of each unique ghost vertex.
Part of ClimaCore.Spaces.weighted_dss!.
ClimaCore.Topologies.dss_ghost! — Function
dss_ghost!(device, perimeter_data, perimeter, topology)Set the value in perimeter_data of all local vertices of each unique ghost vertex to that of the representative vertex.
Part of ClimaCore.Spaces.weighted_dss!.
ClimaCore.Topologies.dss_unload_perimeter_data! — Function
dss_unload_perimeter_data!(device, data, dss_buffer, perimeter)Copy the summed values in dss_buffer.perimeter_data back into data at the element-perimeter nodes given by perimeter. This is the final phase of a DSS operation; the untransformed counterpart of dss_untransform!, used when data needs no local geometry transformation.
Part of ClimaCore.Spaces.weighted_dss!; see also DSSBuffer.