Loading...
Searching...
No Matches
inv_rho_grad_rho_dot_u.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "../../quadrature/quadrature.hpp"
5#include "dense/vec.hpp"
10#include "linalg/operator.hpp"
11#include "linalg/vector_q1.hpp"
12
14
15/// \brief Linear form for the TALA/PDA compressibility term in compressible Stokes.
16///
17/// Given a scalar FE function \f$\rho\f$ (density) and a vectorial FE function \f$\mathbf{u}\f$
18/// (velocity), this linear form evaluates
19/// \f[
20/// f_i = \int_\Omega \frac{1}{\rho} \nabla\rho \cdot \mathbf{u} \, \phi_i \, \mathrm{d}x
21/// \f]
22/// into a scalar finite element coefficient vector, where \f$\phi_i\f$ are the scalar Q1 test
23/// functions on the spherical shell mesh.
24///
25/// This term arises in the pressure equation of the Truncated Anelastic Liquid Approximation
26/// (TALA) and the Projected Density Approximation (PDA) for compressible Stokes flow in
27/// geodynamics. See the [Stokes documentation](@ref stokes-compressible) for the full context.
28///
29/// \note The sign convention at the call site depends on the (2,1) block of the Stokes operator.
30/// The `Divergence` block computes \f$-(q, \mathrm{div}\, u)\f$, so the mass conservation
31/// equation \f$-(q, \mathrm{div}\, u) = f_p\f$ requires
32/// \f$f_p = +\frac{1}{\rho}\nabla\rho\cdot\mathbf{u}\f$ term (positive sign).
33///
34/// \note \f$\rho\f$ must not vanish in the domain; no singular-value protection is applied.
35///
36/// **Concept.** This class satisfies \ref terra::linalg::LinearFormLike. Evaluation writes
37/// the assembled coefficient vector into \p dst via `linalg::apply`:
38///
39/// \code{.cpp}
40/// InvRhoGradRhoDotU< double > L( domain, grid, radii, rho, velocity );
41/// linalg::VectorQ1Scalar< double > g( domain );
42/// linalg::apply( L, g ); // fills g_i = ∫ (1/ρ) ∇ρ·u φ_i dx
43/// \endcode
44///
45/// The default `OperatorApplyMode::Replace` zeroes \p dst before accumulation. Pass
46/// `OperatorApplyMode::Add` to add into an existing vector instead.
47///
48template < typename ScalarT, int VelocityVecDim = 3 >
50{
51 public:
53 using ScalarType = ScalarT;
54
55 private:
57
60
63
64 linalg::OperatorApplyMode operator_apply_mode_;
65 linalg::OperatorCommunicationMode operator_communication_mode_;
66
69
70 // Kokkos views set in apply_impl() before the parallel launch.
74
75 public:
83 const linalg::OperatorCommunicationMode operator_communication_mode =
85 : domain_( domain )
86 , grid_( grid )
87 , radii_( radii )
88 , rho_( rho )
89 , velocity_( velocity )
90 , operator_apply_mode_( operator_apply_mode )
91 , operator_communication_mode_( operator_communication_mode )
92 , send_buffers_( domain )
93 , recv_buffers_( domain )
94 {}
95
97 {
98 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
99 {
100 assign( dst, 0 );
101 }
102
103 dst_ = dst.grid_data();
104 rho_grid_ = rho_.grid_data();
105 vel_grid_ = velocity_.grid_data();
106
107 Kokkos::parallel_for(
108 "inv_rho_grad_rho_dot_u", grid::shell::local_domain_md_range_policy_cells( domain_ ), *this );
109 Kokkos::fence();
110
111 if ( operator_communication_mode_ == linalg::OperatorCommunicationMode::CommunicateAdditively )
112 {
114 domain_, dst_, send_buffers_, recv_buffers_ );
116 }
117 }
118
119 /// \brief Kokkos kernel: per-cell contribution to
120 /// \f$ f_i = \int_E \frac{1}{\rho} \nabla\rho \cdot \mathbf{u} \, \phi_i \, \mathrm{d}x \f$.
121 KOKKOS_INLINE_FUNCTION void
122 operator()( const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell ) const
123 {
124 // -----------------------------------------------------------------------
125 // Geometry
126 // -----------------------------------------------------------------------
128 wedge_surface_physical_coords( wedge_phy_surf, grid_, local_subdomain_id, x_cell, y_cell );
129
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 // -----------------------------------------------------------------------
134 // Quadrature
135 // -----------------------------------------------------------------------
136 constexpr auto num_quad_points = quadrature::quad_felippa_3x2_num_quad_points;
137
138 dense::Vec< ScalarT, 3 > quad_points[num_quad_points];
139 ScalarT quad_weights[num_quad_points];
140
143
144 // -----------------------------------------------------------------------
145 // Extract local coefficients: rho (scalar) and u (vector per dimension)
146 // -----------------------------------------------------------------------
148 extract_local_wedge_scalar_coefficients( rho_coeffs, local_subdomain_id, x_cell, y_cell, r_cell, rho_grid_ );
149
150 dense::Vec< ScalarT, 6 > vel_coeffs[VelocityVecDim][num_wedges_per_hex_cell];
151 for ( int d = 0; d < VelocityVecDim; d++ )
152 {
154 vel_coeffs[d], local_subdomain_id, x_cell, y_cell, r_cell, d, vel_grid_ );
155 }
156
157 // -----------------------------------------------------------------------
158 // Per-wedge local contributions
159 // -----------------------------------------------------------------------
161
162 for ( int q = 0; q < num_quad_points; q++ )
163 {
164 const ScalarT w = quad_weights[q];
165
166 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
167 {
168 const auto J = jac( wedge_phy_surf[wedge], r_1, r_2, quad_points[q] );
169 const auto det = Kokkos::abs( J.det() );
170 const auto J_inv_transposed = J.inv().transposed();
171
172 // ----------------------------------------------------------------
173 // Interpolate rho and compute physical gradient of rho at quad pt
174 // ----------------------------------------------------------------
175 ScalarT rho_q = 0;
176 dense::Vec< ScalarT, 3 > grad_rho_q = {};
177
178 for ( int j = 0; j < num_nodes_per_wedge; j++ )
179 {
180 const ScalarT phi_j = shape( j, quad_points[q] );
181 const auto grad_phi_j_phy = J_inv_transposed * grad_shape( j, quad_points[q] );
182
183 rho_q += rho_coeffs[wedge]( j ) * phi_j;
184 grad_rho_q = grad_rho_q + rho_coeffs[wedge]( j ) * grad_phi_j_phy;
185 }
186
187 // ----------------------------------------------------------------
188 // Interpolate velocity at quad pt
189 // ----------------------------------------------------------------
191 for ( int d = 0; d < VelocityVecDim; d++ )
192 {
193 for ( int j = 0; j < num_nodes_per_wedge; j++ )
194 {
195 u_q( d ) += vel_coeffs[d][wedge]( j ) * shape( j, quad_points[q] );
196 }
197 }
198
199 // ----------------------------------------------------------------
200 // Integrand: (1/rho) * grad(rho) . u
201 // ----------------------------------------------------------------
202 ScalarT dot = 0;
203 for ( int d = 0; d < VelocityVecDim; d++ )
204 {
205 dot += grad_rho_q( d ) * u_q( d );
206 }
207 const ScalarT integrand = dot / rho_q;
208
209 // ----------------------------------------------------------------
210 // Accumulate test-function contributions
211 // ----------------------------------------------------------------
212 for ( int i = 0; i < num_nodes_per_wedge; i++ )
213 {
214 contrib[wedge]( i ) += w * integrand * shape( i, quad_points[q] ) * det;
215 }
216 }
217 }
218
219 atomically_add_local_wedge_scalar_coefficients( dst_, local_subdomain_id, x_cell, y_cell, r_cell, contrib );
220 }
221};
222
224
225} // namespace terra::fe::wedge::linearforms::shell
Linear form for the TALA/PDA compressibility term in compressible Stokes.
Definition inv_rho_grad_rho_dot_u.hpp:50
InvRhoGradRhoDotU(const grid::shell::DistributedDomain &domain, const grid::Grid3DDataVec< ScalarT, 3 > &grid, const grid::Grid2DDataScalar< ScalarT > &radii, const linalg::VectorQ1Scalar< ScalarT > &rho, const linalg::VectorQ1Vec< ScalarT, VelocityVecDim > &velocity, const linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace, const linalg::OperatorCommunicationMode operator_communication_mode=linalg::OperatorCommunicationMode::CommunicateAdditively)
Definition inv_rho_grad_rho_dot_u.hpp:76
void apply_impl(DstVectorType &dst)
Definition inv_rho_grad_rho_dot_u.hpp:96
void operator()(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell) const
Kokkos kernel: per-cell contribution to .
Definition inv_rho_grad_rho_dot_u.hpp:122
ScalarT ScalarType
Definition inv_rho_grad_rho_dot_u.hpp:53
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
Concept for types that behave like linear forms.
Definition linear_form.hpp:22
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 inv_rho_drho_dt.hpp:16
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.
SoA (Structure-of-Arrays) 4D vector grid data.
Definition grid_types.hpp:51