Loading...
Searching...
No Matches
centered_rk2_advection_diffusion.hpp
Go to the documentation of this file.
1
2#pragma once
3
4#include "../../quadrature/quadrature.hpp"
6#include "dense/vec.hpp"
10#include "linalg/operator.hpp"
11#include "linalg/vector.hpp"
12#include "linalg/vector_q1.hpp"
13#include "util/timer.hpp"
14
16
17/// \brief Matrix-free Galerkin **rate** operator for the unsteady advection-diffusion equation.
18///
19/// Computes
20/// \f[
21/// \mathrm{dst} = -\bigl( K_\text{adv} + K_\text{diff} \bigr)\,\mathrm{src}
22/// = -\!\!\int_\Omega \phi_i \,(\mathbf{u}\!\cdot\!\nabla\phi_j)\,\mathrm{d}x \,T_j
23/// -\!\!\int_\Omega \kappa\,\nabla\phi_i\!\cdot\!\nabla\phi_j\,\mathrm{d}x \,T_j .
24/// \f]
25/// In the lumped-mass time-stepping picture this is the (assembled, additively reduced)
26/// right-hand side of \f$ M_\text{lumped}\,\dot{T} = -K T + F \f$ from which the actual
27/// nodal rate \f$\dot{T}_i\f$ is recovered by pointwise division by the lumped mass diagonal.
28///
29/// This is the central building block of the explicit centred Runge-Kutta-2 energy integrator
30/// that mirrors TERRA's `advect`/`advance` pair (TERRA-group/src/code/energy.f:6-181 and
31/// convct.F:207-244). Unlike `UnsteadyAdvectionDiffusionSUPG`, there is **no** SUPG
32/// stabilisation, **no** mass term in the bilinear form, **no** time-step or Dirichlet
33/// row treatment in the kernel, and **no** lumping flag — the operator is purely the
34/// stiffness contribution \f$K\f$ with the leading minus sign baked in. Boundary
35/// conditions are handled outside, by overwriting Dirichlet nodes after each RK substage,
36/// matching TERRA's strategy of zeroing `dhdt` at top/bottom rows.
37///
38/// The advection term uses the **centred** Galerkin form
39/// \f$\int \phi_i (\mathbf{u}\cdot\nabla\phi_j)\f$ — no upwinding, no limiter. This is
40/// the Q1 analogue of TERRA's face-centred update
41/// \f$\tfrac{1}{2}(T_i + T_j)\cdot\mathbf{u}\!\cdot\!\mathbf{n}\f$ at energy.f:73.
42template < typename ScalarT, int VelocityVecDim = 3 >
44{
45 public:
48 using ScalarType = ScalarT;
49
50 private:
52
55
57
58 ScalarT diffusivity_;
59
60 linalg::OperatorApplyMode operator_apply_mode_;
61 linalg::OperatorCommunicationMode operator_communication_mode_;
62
65
69
70 public:
76 const ScalarT diffusivity,
78 linalg::OperatorCommunicationMode operator_communication_mode =
80 : domain_( domain )
81 , grid_( grid )
82 , radii_( radii )
83 , velocity_( velocity )
84 , diffusivity_( diffusivity )
85 , operator_apply_mode_( operator_apply_mode )
86 , operator_communication_mode_( operator_communication_mode )
87 , send_buffers_( domain )
88 , recv_buffers_( domain )
89 {}
90
91 ScalarT& diffusivity() { return diffusivity_; }
92 const ScalarT& diffusivity() const { return diffusivity_; }
93
94 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
95 {
96 util::Timer timer_apply( "centered_rk2_rate_apply" );
97
98 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
99 {
100 assign( dst, 0 );
101 }
102
103 src_ = src.grid_data();
104 dst_ = dst.grid_data();
105 vel_grid_ = velocity_.grid_data();
106
107 util::Timer timer_kernel( "centered_rk2_rate_kernel" );
108 Kokkos::parallel_for( "matvec", grid::shell::local_domain_md_range_policy_cells( domain_ ), *this );
109 Kokkos::fence();
110 timer_kernel.stop();
111
112 if ( operator_communication_mode_ == linalg::OperatorCommunicationMode::CommunicateAdditively )
113 {
114 util::Timer timer_comm( "centered_rk2_rate_comm" );
115
117 domain_, dst_, send_buffers_, recv_buffers_ );
119 }
120 }
121
122 KOKKOS_INLINE_FUNCTION void
123 operator()( const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell ) const
124 {
125 // Gather surface points for each wedge.
127 wedge_surface_physical_coords( wedge_phy_surf, grid_, local_subdomain_id, x_cell, y_cell );
128
129 // Gather wedge radii.
130 const ScalarT r_1 = radii_( local_subdomain_id, r_cell );
131 const ScalarT r_2 = radii_( local_subdomain_id, r_cell + 1 );
132
133 // Quadrature points.
134 constexpr auto num_quad_points = quadrature::quad_felippa_3x2_num_quad_points;
135
136 dense::Vec< ScalarT, 3 > quad_points[num_quad_points];
137 ScalarT quad_weights[num_quad_points];
138
141
142 // Interpolate velocity to quadrature points using Q1 wedge basis.
143 // (Same pattern as UnsteadyAdvectionDiffusionSUPG kernel.)
145 dense::Vec< ScalarT, 6 > vel_coeffs[VelocityVecDim][num_wedges_per_hex_cell];
146
147 for ( int d = 0; d < VelocityVecDim; d++ )
148 {
150 vel_coeffs[d], local_subdomain_id, x_cell, y_cell, r_cell, d, vel_grid_ );
151 }
152
153 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
154 {
155 for ( int q = 0; q < num_quad_points; q++ )
156 {
157 for ( int i = 0; i < num_nodes_per_wedge; i++ )
158 {
159 const auto shape_i = shape( i, quad_points[q] );
160 for ( int d = 0; d < VelocityVecDim; d++ )
161 {
162 vel_interp[wedge][q]( d ) += vel_coeffs[d][wedge]( i ) * shape_i;
163 }
164 }
165 }
166 }
167
168 // Assemble the local stiffness matrix K_e = K_adv_e + K_diff_e per wedge.
169 // (No SUPG term, no mass term, no time step.)
171
172 for ( int q = 0; q < num_quad_points; q++ )
173 {
174 const auto w = quad_weights[q];
175
176 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
177 {
178 const auto J = jac( wedge_phy_surf[wedge], r_1, r_2, quad_points[q] );
179 const auto det = Kokkos::abs( J.det() );
180 const auto J_inv_transposed = J.inv().transposed();
181
182 const auto vel = vel_interp[wedge][q];
183
184 for ( int i = 0; i < num_nodes_per_wedge; i++ )
185 {
186 const auto shape_i = shape( i, quad_points[q] );
187 const auto grad_i = J_inv_transposed * grad_shape( i, quad_points[q] );
188
189 for ( int j = 0; j < num_nodes_per_wedge; j++ )
190 {
191 const auto grad_j = J_inv_transposed * grad_shape( j, quad_points[q] );
192
193 // Centred Galerkin advection: int phi_i (u . grad phi_j)
194 const auto advection = ( vel.dot( grad_j ) ) * shape_i;
195 // Diffusion: int kappa grad phi_i . grad phi_j
196 const auto diffusion = diffusivity_ * ( grad_i ).dot( grad_j );
197
198 K[wedge]( i, j ) += w * ( advection + diffusion ) * det;
199 }
200 }
201 }
202 }
203
204 // Local source vector (T_in restricted to this hex cell).
206 extract_local_wedge_scalar_coefficients( src, local_subdomain_id, x_cell, y_cell, r_cell, src_ );
207
208 // Local rate contribution (rate form: dst = -K * src).
210 dst[0] = K[0] * src[0];
211 dst[1] = K[1] * src[1];
212 for ( int i = 0; i < 6; i++ )
213 {
214 dst[0]( i ) = -dst[0]( i );
215 dst[1]( i ) = -dst[1]( i );
216 }
217
218 atomically_add_local_wedge_scalar_coefficients( dst_, local_subdomain_id, x_cell, y_cell, r_cell, dst );
219 }
220};
221
223
224} // namespace terra::fe::wedge::operators::shell
Matrix-free Galerkin rate operator for the unsteady advection-diffusion equation.
Definition centered_rk2_advection_diffusion.hpp:44
void operator()(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell) const
Definition centered_rk2_advection_diffusion.hpp:123
const ScalarT & diffusivity() const
Definition centered_rk2_advection_diffusion.hpp:92
Q1CenteredAdvDiffRateOperator(const grid::shell::DistributedDomain &domain, const grid::Grid3DDataVec< ScalarT, 3 > &grid, const grid::Grid2DDataScalar< ScalarT > &radii, const linalg::VectorQ1Vec< ScalarT, VelocityVecDim > &velocity, const ScalarT diffusivity, linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace, linalg::OperatorCommunicationMode operator_communication_mode=linalg::OperatorCommunicationMode::CommunicateAdditively)
Definition centered_rk2_advection_diffusion.hpp:71
ScalarT ScalarType
Definition centered_rk2_advection_diffusion.hpp:48
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition centered_rk2_advection_diffusion.hpp:94
ScalarT & diffusivity()
Definition centered_rk2_advection_diffusion.hpp:91
Parallel data structure organizing the thick spherical shell metadata for distributed (MPI parallel) ...
Definition spherical_shell.hpp:2518
Q1 scalar finite element vector on a distributed shell grid.
Definition vector_q1.hpp:21
const grid::Grid4DDataScalar< ScalarType > & grid_data() const
Get const reference to grid data.
Definition vector_q1.hpp:139
Static assertion: VectorQ1Scalar satisfies VectorLike concept.
Definition vector_q1.hpp:168
const grid::Grid4DDataVec< ScalarType, VecDim > & grid_data() const
Get const reference to grid data.
Definition vector_q1.hpp:288
Timer supporting RAII scope or manual stop.
Definition timer.hpp:342
void stop()
Stop the timer and record elapsed time.
Definition timer.hpp:364
Concept for types that behave like linear operators.
Definition operator.hpp:57
void unpack_and_reduce_local_subdomain_boundaries(const grid::shell::DistributedDomain &domain, const GridDataType &data, SubdomainNeighborhoodSendRecvBuffer< typename GridDataType::value_type, grid::grid_data_vec_dim< GridDataType >() > &boundary_recv_buffers, CommunicationReduction reduction=CommunicationReduction::SUM)
Unpacks and reduces local subdomain boundaries.
Definition communication.hpp:672
void pack_send_and_recv_local_subdomain_boundaries(const grid::shell::DistributedDomain &domain, const GridDataType &data, SubdomainNeighborhoodSendRecvBuffer< typename GridDataType::value_type, grid::grid_data_vec_dim< GridDataType >() > &boundary_send_buffers, SubdomainNeighborhoodSendRecvBuffer< typename GridDataType::value_type, grid::grid_data_vec_dim< GridDataType >() > &boundary_recv_buffers)
Packs, sends and recvs local subdomain boundaries using two sets of buffers.
Definition communication.hpp:242
Definition boundary_mass.hpp:14
constexpr void quad_felippa_3x2_quad_weights(T(&quad_weights)[quad_felippa_3x2_num_quad_points])
Definition wedge/quadrature/quadrature.hpp:93
constexpr int quad_felippa_3x2_num_quad_points
Definition wedge/quadrature/quadrature.hpp:66
constexpr void quad_felippa_3x2_quad_points(dense::Vec< T, 3 >(&quad_points)[quad_felippa_3x2_num_quad_points])
Definition wedge/quadrature/quadrature.hpp:70
constexpr int num_nodes_per_wedge_surface
Definition kernel_helpers.hpp:6
void atomically_add_local_wedge_scalar_coefficients(const grid::Grid4DDataScalar< T > &global_coefficients, const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const dense::Vec< T, 6 >(&local_coefficients)[2])
Performs an atomic add of the two local wedge coefficient vectors of a hex cell into the global coeff...
Definition kernel_helpers.hpp:407
void wedge_surface_physical_coords(dense::Vec< T, 3 >(&wedge_surf_phy_coords)[num_wedges_per_hex_cell][num_nodes_per_wedge_surface], const grid::Grid3DDataVec< T, 3 > &lateral_grid, const int local_subdomain_id, const int x_cell, const int y_cell)
Extracts the (unit sphere) surface vertex coords of the two wedges of a hex cell.
Definition kernel_helpers.hpp:26
constexpr int num_wedges_per_hex_cell
Definition kernel_helpers.hpp:5
void extract_local_wedge_scalar_coefficients(dense::Vec< T, 6 >(&local_coefficients)[2], const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const grid::Grid4DDataScalar< T > &global_coefficients)
Extracts the local vector coefficients for the two wedges of a hex cell from the global coefficient v...
Definition kernel_helpers.hpp:306
void extract_local_wedge_vector_coefficients(dense::Vec< T, 6 >(&local_coefficients)[2], const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int d, const grid::Grid4DDataVec< T, VecDim > &global_coefficients)
Extracts the local vector coefficients for the two wedges of a hex cell from the global coefficient v...
Definition kernel_helpers.hpp:356
constexpr int num_nodes_per_wedge
Definition kernel_helpers.hpp:7
constexpr dense::Vec< T, 3 > grad_shape(const int node_idx, const T xi, const T eta, const T zeta)
Gradient of the full shape function:
Definition integrands.hpp:228
constexpr T shape(const int node_idx, const T xi, const T eta, const T zeta)
(Tensor-product) Shape function.
Definition integrands.hpp:146
constexpr dense::Mat< T, 3, 3 > jac(const dense::Vec< T, 3 > &p1_phy, const dense::Vec< T, 3 > &p2_phy, const dense::Vec< T, 3 > &p3_phy, const T r_1, const T r_2, const T xi, const T eta, const T zeta)
Definition integrands.hpp:657
Kokkos::MDRangePolicy< Kokkos::Rank< 4 > > local_domain_md_range_policy_cells(const DistributedDomain &distributed_domain)
Definition spherical_shell.hpp:2739
Kokkos::View< ScalarType ***[VecDim], Layout > Grid3DDataVec
Definition grid_types.hpp:42
Kokkos::View< ScalarType ****, Layout > Grid4DDataScalar
Definition grid_types.hpp:27
Kokkos::View< ScalarType **, Layout > Grid2DDataScalar
Definition grid_types.hpp:21
OperatorApplyMode
Modes for applying an operator to a vector.
Definition operator.hpp:30
@ Replace
Overwrite the destination vector.
OperatorCommunicationMode
Modes for communication during operator application.
Definition operator.hpp:40
@ CommunicateAdditively
Communicate and add results.
Definition mat.hpp:10
SoA (Structure-of-Arrays) 4D vector grid data.
Definition grid_types.hpp:51