Loading...
Searching...
No Matches
supg_rhs.hpp
Go to the documentation of this file.
1#pragma once
2#include "../../quadrature/quadrature.hpp"
4#include "dense/vec.hpp"
10#include "linalg/operator.hpp"
11#include "linalg/vector_q1.hpp"
12
14
15/// \brief Linear form to assemble part of the RHS vector for a SUPG-stabilized method-of-lines
16/// discretization of the advection-diffusion equation.
17///
18/// \note See \ref terra::fe::wedge::operators::shell::UnsteadyAdvectionDiffusionSUPG for notes
19/// on the discretization. This linear form evaluates what is therein called \f$F_{\mathrm{SUPG}}\f$.
20///
21/// Given finite element functions \f$f\f$ and \f$\mathbf{u}\f$, this linear form evaluates
22/// \f[
23/// (F_{\mathrm{SUPG}})_i = \sum_E \int_E \tau_E (\mathbf{u} \cdot \nabla \phi_i) f
24/// \f]
25/// into a finite element coefficient vector, where \f$\tau_E\f$ is the element-local SUPG stabilization
26/// parameter (computed on-the-fly, like in \ref terra::fe::wedge::operators::shell::UnsteadyAdvectionDiffusionSUPG).
27///
28template < typename ScalarT, int VelocityVecDim = 3 >
30{
31 public:
33 using ScalarType = ScalarT;
34
35 private:
37
40
43
44 ScalarT diffusivity_;
45
49
50 linalg::OperatorApplyMode operator_apply_mode_;
51 linalg::OperatorCommunicationMode operator_communication_mode_;
52
55
56 public:
63 const ScalarT diffusivity,
64
66 const linalg::OperatorCommunicationMode operator_communication_mode =
68 : domain_( domain )
69 , grid_( grid )
70 , radii_( radii )
71 , f_( f )
72 , velocity_( velocity )
73 , diffusivity_( diffusivity )
74 , operator_apply_mode_( operator_apply_mode )
75 , operator_communication_mode_( operator_communication_mode )
76 // TODO: we can reuse the send and recv buffers and pass in from the outside somehow
77 , send_buffers_( domain )
78 , recv_buffers_( domain )
79 {}
80
82 {
83 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
84 {
85 assign( dst, 0 );
86 }
87
88 dst_ = dst.grid_data();
89 vel_grid_ = velocity_.grid_data();
90 f_grid_ = f_.grid_data();
91
92 Kokkos::parallel_for( "matvec", grid::shell::local_domain_md_range_policy_cells( domain_ ), *this );
93
94 if ( operator_communication_mode_ == linalg::OperatorCommunicationMode::CommunicateAdditively )
95 {
97 domain_, dst_, send_buffers_, recv_buffers_ );
99 }
100 }
101
102 KOKKOS_INLINE_FUNCTION void
103 operator()( const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell ) const
104 {
105 // Gather surface points for each wedge.
107 wedge_surface_physical_coords( wedge_phy_surf, grid_, local_subdomain_id, x_cell, y_cell );
108
109 // Gather wedge radii.
110 const ScalarT r_1 = radii_( local_subdomain_id, r_cell );
111 const ScalarT r_2 = radii_( local_subdomain_id, r_cell + 1 );
112
113 // Quadrature points.
114 constexpr auto num_quad_points = quadrature::quad_felippa_3x2_num_quad_points;
115
116 dense::Vec< ScalarT, 3 > quad_points[num_quad_points];
117 ScalarT quad_weights[num_quad_points];
118
121
122 // Interpolating velocity into quad points.
123
125 dense::Vec< ScalarT, 6 > vel_coeffs[VelocityVecDim][num_wedges_per_hex_cell];
126
127 for ( int d = 0; d < VelocityVecDim; d++ )
128 {
130 vel_coeffs[d], local_subdomain_id, x_cell, y_cell, r_cell, d, vel_grid_ );
131 }
132
133 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
134 {
135 for ( int q = 0; q < num_quad_points; q++ )
136 {
137 for ( int i = 0; i < num_nodes_per_wedge; i++ )
138 {
139 const auto shape_i = shape( i, quad_points[q] );
140 for ( int d = 0; d < VelocityVecDim; d++ )
141 {
142 vel_interp[wedge][q]( d ) += vel_coeffs[d][wedge]( i ) * shape_i;
143 }
144 }
145 }
146 }
147
148 // Interpolating f into quad points.
149 ScalarT f_interp[num_wedges_per_hex_cell][num_quad_points] = {};
151
152 extract_local_wedge_scalar_coefficients( f_coeffs, local_subdomain_id, x_cell, y_cell, r_cell, f_grid_ );
153
154 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
155 {
156 for ( int q = 0; q < num_quad_points; q++ )
157 {
158 for ( int i = 0; i < num_nodes_per_wedge; i++ )
159 {
160 const auto shape_i = shape( i, quad_points[q] );
161 f_interp[wedge][q] += f_coeffs[wedge]( i ) * shape_i;
162 }
163 }
164 }
165
166 // Let's compute the streamline diffusivity.
167
168 ScalarT streamline_diffusivity[num_wedges_per_hex_cell] = {};
169
170 // Far from accurate but for now assume h = r.
171 const auto h = r_2 - r_1;
172
173 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
174 {
175 ScalarT tau_accum = 0.0;
176 ScalarT waccum = 0.0;
177
178 for ( int q = 0; q < num_quad_points; ++q )
179 {
180 // get velocity at this quad point
181 const auto& uq = vel_interp[wedge][q];
182 const ScalarT vel_norm_q = uq.norm();
183
184 const ScalarT tau_q = operators::shell::supg_tau< ScalarT >( vel_norm_q, diffusivity_, h, 1e-08 );
185
186 // quadrature weight for this point (if you have weights)
187 const ScalarT wq = quad_weights[q]; // if not available, use 1.0
188 tau_accum += tau_q * wq;
189 waccum += wq;
190 }
191
192 // final cell/wedge tau: volume-weighted average
193 ScalarT tau_cell = ( waccum > 0.0 ) ? ( tau_accum / waccum ) : 0.0;
194 streamline_diffusivity[wedge] = tau_cell;
195 }
196
197 // Local contributions
199
200 for ( int q = 0; q < num_quad_points; q++ )
201 {
202 const auto w = quad_weights[q];
203
204 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
205 {
206 const auto J = jac( wedge_phy_surf[wedge], r_1, r_2, quad_points[q] );
207 const auto det = Kokkos::abs( J.det() );
208 const auto J_inv_transposed = J.inv().transposed();
209
210 for ( int i = 0; i < num_nodes_per_wedge; i++ )
211 {
212 const auto shape_i = shape( i, quad_points[q] );
213 const auto grad_i = J_inv_transposed * grad_shape( i, quad_points[q] );
214
215 contrib[wedge]( i ) += w * streamline_diffusivity[wedge] * vel_interp[wedge][q].dot( grad_i ) *
216 f_interp[wedge][q] * det;
217 }
218 }
219 }
220
221 atomically_add_local_wedge_scalar_coefficients( dst_, local_subdomain_id, x_cell, y_cell, r_cell, contrib );
222 }
223};
224
226
227} // namespace terra::fe::wedge::linearforms::shell
Linear form to assemble part of the RHS vector for a SUPG-stabilized method-of-lines discretization o...
Definition supg_rhs.hpp:30
void apply_impl(DstVectorType &dst)
Definition supg_rhs.hpp:81
SUPGRHS(const grid::shell::DistributedDomain &domain, const grid::Grid3DDataVec< ScalarT, 3 > &grid, const grid::Grid2DDataScalar< ScalarT > &radii, const linalg::VectorQ1Scalar< ScalarT > &f, const linalg::VectorQ1Vec< ScalarT, VelocityVecDim > &velocity, const ScalarT diffusivity, const linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace, const linalg::OperatorCommunicationMode operator_communication_mode=linalg::OperatorCommunicationMode::CommunicateAdditively)
Definition supg_rhs.hpp:57
ScalarT ScalarType
Definition supg_rhs.hpp:33
void operator()(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell) const
Definition supg_rhs.hpp:103
Parallel data structure organizing the thick spherical shell metadata for distributed (MPI parallel) ...
Definition spherical_shell.hpp:2498
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:137
Static assertion: VectorQ1Scalar satisfies VectorLike concept.
Definition vector_q1.hpp:162
const grid::Grid4DDataVec< ScalarType, VecDim > & grid_data() const
Get const reference to grid data.
Definition vector_q1.hpp:280
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 supg_rhs.hpp:13
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:643
Kokkos::MDRangePolicy< Kokkos::Rank< 4 > > local_domain_md_range_policy_cells(const DistributedDomain &distributed_domain)
Definition spherical_shell.hpp:2668
Kokkos::View< ScalarType ***[VecDim], Layout > Grid3DDataVec
Definition grid_types.hpp:40
Kokkos::View< ScalarType ****[VecDim], Layout > Grid4DDataVec
Definition grid_types.hpp:43
Kokkos::View< ScalarType ****, Layout > Grid4DDataScalar
Definition grid_types.hpp:25
Kokkos::View< ScalarType **, Layout > Grid2DDataScalar
Definition grid_types.hpp:19
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.
T norm() const
Definition vec.hpp:76