Loading...
Searching...
No Matches
epsilon_divdiv_simple.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "../../quadrature/quadrature.hpp"
5#include "dense/vec.hpp"
9#include "linalg/operator.hpp"
10#include "linalg/vector.hpp"
11#include "linalg/vector_q1.hpp"
12#include "util/timer.hpp"
13
15
16template < typename ScalarT, int VecDim = 3 >
18{
19 public:
22 using ScalarType = ScalarT;
23
24 private:
25 bool storeLMatrices_ =
26 false; // set to let apply_impl() know, that it should store the local matrices after assembling them
27 bool single_quadpoint_ = false;
28
30
35
36
37 bool treat_boundary_;
38 bool diagonal_;
39
40 linalg::OperatorApplyMode operator_apply_mode_;
41 linalg::OperatorCommunicationMode operator_communication_mode_;
42
45
48
49 public:
56 bool treat_boundary,
57 bool diagonal,
59 linalg::OperatorCommunicationMode operator_communication_mode =
61 : domain_( domain )
62 , grid_( grid )
63 , radii_( radii ) , mask_( mask )
64 , k_( k )
65 , treat_boundary_( treat_boundary )
66 , diagonal_( diagonal )
67 , operator_apply_mode_( operator_apply_mode )
68 , operator_communication_mode_( operator_communication_mode )
69 // TODO: we can reuse the send and recv buffers and pass in from the outside somehow
70 , send_buffers_( domain )
71 , recv_buffers_( domain )
72 {}
73
75
76 /// @brief Getter for domain member
77 const grid::shell::DistributedDomain& get_domain() const { return domain_; }
78
79 /// @brief Getter for radii member
81
82 /// @brief Getter for grid member
84
85
86
87 /// @brief S/Getter for diagonal member
88 void set_diagonal( bool v ) { diagonal_ = v; }
89
90
91
93 const linalg::OperatorApplyMode operator_apply_mode,
94 const linalg::OperatorCommunicationMode operator_communication_mode )
95 {
96 operator_apply_mode_ = operator_apply_mode;
97 operator_communication_mode_ = operator_communication_mode;
98 }
99
100 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
101 {
102 util::Timer timer_apply( "vector_laplace_apply" );
103
104 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
105 {
106 assign( dst, 0 );
107 }
108
109 src_ = src.grid_data();
110 dst_ = dst.grid_data();
111
112 if ( src_.extent( 0 ) != dst_.extent( 0 ) || src_.extent( 1 ) != dst_.extent( 1 ) ||
113 src_.extent( 2 ) != dst_.extent( 2 ) || src_.extent( 3 ) != dst_.extent( 3 ) )
114 {
115 throw std::runtime_error( "VectorLaplace: src/dst mismatch" );
116 }
117
118 if ( src_.extent( 1 ) != grid_.extent( 1 ) || src_.extent( 2 ) != grid_.extent( 2 ) )
119 {
120 throw std::runtime_error( "VectorLaplace: src/dst mismatch" );
121 }
122
123 util::Timer timer_kernel( "vector_laplace_kernel" );
124 Kokkos::parallel_for( "matvec", grid::shell::local_domain_md_range_policy_cells( domain_ ), *this );
125 Kokkos::fence();
126 timer_kernel.stop();
127
128 if ( operator_communication_mode_ == linalg::OperatorCommunicationMode::CommunicateAdditively )
129 {
130 util::Timer timer_comm( "vector_laplace_comm" );
131
133 domain_, dst_, send_buffers_, recv_buffers_ );
135 }
136 }
137
138 KOKKOS_INLINE_FUNCTION void
139 operator()( const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell ) const
140 {
141 // Compute the local element matrix.
143
144
145 // Gather surface points for each wedge.
147 wedge_surface_physical_coords( wedge_phy_surf, grid_, local_subdomain_id, x_cell, y_cell );
148
149 // Gather wedge radii.
150 const ScalarT r_1 = radii_( local_subdomain_id, r_cell );
151 const ScalarT r_2 = radii_( local_subdomain_id, r_cell + 1 );
152
153 // Quadrature points.
154 constexpr auto num_quad_points = quadrature::quad_felippa_3x2_num_quad_points;
155
156 dense::Vec< ScalarT, 3 > quad_points[num_quad_points];
157 ScalarT quad_weights[num_quad_points];
158
161
163 extract_local_wedge_scalar_coefficients( k, local_subdomain_id, x_cell, y_cell, r_cell, k_ );
164
165 // FE dimensions: velocity coupling components of epsilon operator
166 for ( int dimi = 0; dimi < 3; ++dimi )
167 {
168 for ( int dimj = 0; dimj < 3; ++dimj )
169 {
170 if ( diagonal_ and dimi != dimj )
171 continue;
172
173 // spatial dimensions: quadrature points and wedge
174 for ( int q = 0; q < num_quad_points; q++ )
175 {
176 const auto w = quad_weights[q];
177
178 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
179 {
180 dense::Mat< ScalarT, 3, 3 > J = jac( wedge_phy_surf[wedge], r_1, r_2, quad_points[q] );
181 const auto det = J.det();
182 const auto abs_det = Kokkos::abs( det );
183 const auto J_inv_transposed = J.inv_transposed( det );
184 ScalarType k_eval = 0.0;
185 for ( int j = 0; j < num_nodes_per_wedge; j++ )
186 {
187 k_eval += shape( j, quad_points[q] ) * k[wedge]( j );
188 }
189 // FE dimensions: local DoFs/associated shape functions
190 for ( int i = 0; i < num_nodes_per_wedge; i++ )
191 {
192 // basis functions are vectors with VecDim components -> build tensorial gradients
195 grad_shape( i, quad_points[q] ), dimi );
196 dense::Mat< ScalarT, 3, 3 > sym_grad_i = ( grad_i + grad_i.transposed() );
197 ScalarType div_i = grad_i( dimi, dimi );
198
199 for ( int j = 0; j < num_nodes_per_wedge; j++ )
200 {
203 grad_shape( j, quad_points[q] ), dimj );
204
205 dense::Mat< ScalarT, 3, 3 > sym_grad_j = ( grad_j + grad_j.transposed() );
206
207 ScalarType div_j = grad_j( dimj, dimj );
208
209 A[wedge]( i + num_nodes_per_wedge * dimi, j + num_nodes_per_wedge * dimj ) +=
210 w * k_eval * abs_det *
211 ( 0.5 * sym_grad_i.double_contract( sym_grad_j ) - 2.0 / 3.0 * div_i * div_j );
212 }
213 }
214 }
215 }
216 }
217 }
218
219
220 if ( treat_boundary_ )
221 {
222 const bool at_bot_boundary =
223 util::has_flag( mask_( local_subdomain_id, x_cell, y_cell, r_cell ), grid::shell::ShellBoundaryFlag::CMB );
224 const bool at_top_boundary = util::has_flag(
225 mask_( local_subdomain_id, x_cell, y_cell, r_cell + 1 ), grid::shell::ShellBoundaryFlag::SURFACE );
226 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
227 {
228 dense::Mat< ScalarT, 18, 18 > boundary_mask;
229 boundary_mask.fill( 1.0 );
230
231 for ( int dimi = 0; dimi < 3; ++dimi )
232 {
233 for ( int dimj = 0; dimj < 3; ++dimj )
234 {
235
236
237 if ( at_bot_boundary )
238 {
239 // Inner boundary (CMB).
240 for ( int i = 0; i < 6; i++ )
241 {
242 for ( int j = 0; j < 6; j++ )
243 {
244 if ( ( dimi == dimj && i != j && ( i < 3 || j < 3 ) ) or
245 ( dimi != dimj && ( i < 3 || j < 3 ) ) )
246 {
247 boundary_mask(
248 i + num_nodes_per_wedge * dimi, j + num_nodes_per_wedge * dimj ) = 0.0;
249 }
250 }
251 }
252 }
253
254 if ( at_top_boundary )
255 {
256 // Outer boundary (surface).
257 for ( int i = 0; i < 6; i++ )
258 {
259 for ( int j = 0; j < 6; j++ )
260 {
261 if ( ( dimi == dimj && i != j && ( i >= 3 || j >= 3 ) ) or
262 ( dimi != dimj && ( i >= 3 || j >= 3 ) ) )
263 {
264 boundary_mask(
265 i + num_nodes_per_wedge * dimi, j + num_nodes_per_wedge * dimj ) = 0.0;
266 }
267 }
268 }
269 }
270 }
271 }
272
273
274 A[wedge].hadamard_product( boundary_mask );
275 }
276 }
277
278
279 if ( diagonal_ )
280 {
281 A[0] = A[0].diagonal();
282 A[1] = A[1].diagonal();
283 }
284
285
287 for ( int dimj = 0; dimj < 3; dimj++ )
288 {
291 src_d, local_subdomain_id, x_cell, y_cell, r_cell, dimj, src_ );
292
293 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
294 {
295 for ( int i = 0; i < num_nodes_per_wedge; i++ )
296 {
297 src[wedge]( dimj * num_nodes_per_wedge + i ) = src_d[wedge]( i );
298 }
299 }
300 }
301 //extract_local_wedge_vector_coefficients( src, local_subdomain_id, x_cell, y_cell, r_cell, dimj, src_ );
302
304
305 dst[0] = A[0] * src[0];
306 dst[1] = A[1] * src[1];
307
308 //atomically_add_local_wedge_vector_coefficients( dst_, local_subdomain_id, x_cell, y_cell, r_cell, dimi, dst );
309 for ( int dimi = 0; dimi < 3; dimi++ )
310 {
312 dst_d[0] = dst[0].template slice< 6 >( dimi * num_nodes_per_wedge );
313 dst_d[1] = dst[1].template slice< 6 >( dimi * num_nodes_per_wedge );
314
316 dst_, local_subdomain_id, x_cell, y_cell, r_cell, dimi, dst_d );
317 }
318
319 }
320};
321
324
325} // namespace terra::fe::wedge::operators::shell
Send and receive buffers for all process-local subdomain boundaries.
Definition communication.hpp:56
Definition epsilon_divdiv_simple.hpp:18
grid::Grid2DDataScalar< ScalarT > get_radii() const
Getter for radii member.
Definition epsilon_divdiv_simple.hpp:80
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition epsilon_divdiv_simple.hpp:100
grid::Grid3DDataVec< ScalarT, 3 > get_grid() const
Getter for grid member.
Definition epsilon_divdiv_simple.hpp:83
const grid::shell::DistributedDomain & get_domain() const
Getter for domain member.
Definition epsilon_divdiv_simple.hpp:77
EpsilonDivDivSimple(const grid::shell::DistributedDomain &domain, const grid::Grid3DDataVec< ScalarT, 3 > grid, const grid::Grid2DDataScalar< ScalarT > radii, const grid::Grid4DDataScalar< grid::shell::ShellBoundaryFlag > &mask, const grid::Grid4DDataScalar< ScalarT > k, bool treat_boundary, bool diagonal, linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace, linalg::OperatorCommunicationMode operator_communication_mode=linalg::OperatorCommunicationMode::CommunicateAdditively)
Definition epsilon_divdiv_simple.hpp:50
void set_diagonal(bool v)
S/Getter for diagonal member.
Definition epsilon_divdiv_simple.hpp:88
ScalarT ScalarType
Definition epsilon_divdiv_simple.hpp:22
void set_operator_apply_and_communication_modes(const linalg::OperatorApplyMode operator_apply_mode, const linalg::OperatorCommunicationMode operator_communication_mode)
Definition epsilon_divdiv_simple.hpp:92
const grid::Grid4DDataScalar< ScalarType > & k_grid_data()
Definition epsilon_divdiv_simple.hpp:74
void operator()(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell) const
Definition epsilon_divdiv_simple.hpp:139
Parallel data structure organizing the thick spherical shell metadata for distributed (MPI parallel) ...
Definition spherical_shell.hpp:2498
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
Timer supporting RAII scope or manual stop.
Definition timer.hpp:270
void stop()
Stop the timer and record elapsed time.
Definition timer.hpp:289
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 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
void atomically_add_local_wedge_vector_coefficients(const grid::Grid4DDataVec< T, VecDim > &global_coefficients, const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell, const int d, 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:465
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.
constexpr bool has_flag(E mask_value, E flag) noexcept
Checks if a bitmask value contains a specific flag.
Definition bit_masking.hpp:43
Definition mat.hpp:10
void fill(const T value)
Definition mat.hpp:201
constexpr Mat diagonal() const
Definition mat.hpp:377
constexpr Mat< T, Cols, Rows > transposed() const
Definition mat.hpp:187
static constexpr Mat from_single_col_vec(const Vec< T, Cols > &col, const int d)
Definition mat.hpp:66
Mat & hadamard_product(const Mat &mat)
Definition mat.hpp:213
T double_contract(const Mat &mat)
Definition mat.hpp:226