Loading...
Searching...
No Matches
boundary_mass.hpp
Go to the documentation of this file.
1
2#pragma once
3
5#include "dense/vec.hpp"
10#include "linalg/operator.hpp"
11#include "linalg/vector.hpp"
12#include "linalg/vector_q1.hpp"
13
15
16template < typename ScalarT >
18{
19 public:
22 using ScalarType = ScalarT;
23
24 private:
26
29
31
32 grid::shell::ShellBoundaryFlag boundary_flag_;
33 ScalarT zeta_boundary_;
34
35 linalg::OperatorApplyMode operator_apply_mode_;
36 linalg::OperatorCommunicationMode operator_communication_mode_;
37
40
43
44 public:
50 const grid::shell::ShellBoundaryFlag boundary_flag,
52 linalg::OperatorCommunicationMode operator_communication_mode =
54 : domain_( domain )
55 , grid_( grid )
56 , radii_( radii )
57 , mask_( mask )
58 , boundary_flag_( boundary_flag )
59 , zeta_boundary_( boundary_flag == grid::shell::ShellBoundaryFlag::CMB ? -1.0 : 1.0 )
60 , operator_apply_mode_( operator_apply_mode )
61 , operator_communication_mode_( operator_communication_mode )
62 // TODO: we can reuse the send and recv buffers and pass in from the outside somehow
63 , send_buffers_( domain )
64 , recv_buffers_( domain )
65 {
67 {
68 Kokkos::abort( "BoundaryMass only implemented for 1 radial subdomain." );
69 }
70 }
71
72 void apply_impl( const SrcVectorType& src, DstVectorType& dst )
73 {
74 if ( operator_apply_mode_ == linalg::OperatorApplyMode::Replace )
75 {
76 assign( dst, 0 );
77 }
78
79 src_ = src.grid_data();
80 dst_ = dst.grid_data();
81
82 if ( boundary_flag_ == grid::shell::ShellBoundaryFlag::CMB )
83 {
84 Kokkos::parallel_for(
85 "matvec",
86 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
87 { 0, 0, 0, 0 },
88 { static_cast< long long >( domain_.subdomains().size() ),
91 1 } ),
92 *this );
93 }
94 else if ( boundary_flag_ == grid::shell::ShellBoundaryFlag::SURFACE )
95 {
96 Kokkos::parallel_for(
97 "matvec",
98 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
99 { 0, 0, 0, domain_.domain_info().subdomain_num_nodes_radially() - 2 },
100 { static_cast< long long >( domain_.subdomains().size() ),
103 domain_.domain_info().subdomain_num_nodes_radially() - 1 } ),
104 *this );
105 }
106
107 Kokkos::fence();
108
109 if ( operator_communication_mode_ == linalg::OperatorCommunicationMode::CommunicateAdditively )
110 {
111 std::vector< std::unique_ptr< std::array< int, 11 > > > expected_recvs_metadata;
112 std::vector< std::unique_ptr< MPI_Request > > expected_recvs_requests;
113
115 domain_, dst_, send_buffers_, recv_buffers_ );
117 }
118 }
119
120 KOKKOS_INLINE_FUNCTION void
121 operator()( const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell ) const
122 {
123 // First all the r-independent stuff.
124 // Gather surface points for each wedge.
125
127 wedge_surface_physical_coords( wedge_phy_surf, grid_, local_subdomain_id, x_cell, y_cell );
128
129 // Compute lateral part of Jacobian.
130
131 constexpr auto num_quad_points = triangle::quadrature::quad_triangle_3_num_quad_points;
132
133 dense::Vec< ScalarT, 2 > quad_points[num_quad_points];
134 ScalarT quad_weights[num_quad_points];
135
138
139 // Only now we introduce radially dependent terms.
140 const ScalarT r_1 = radii_( local_subdomain_id, r_cell );
141 const ScalarT r_2 = radii_( local_subdomain_id, r_cell + 1 );
142
143 // For now, compute the local element matrix. We'll improve that later.
145
146 // const ScalarT grad_r = grad_forward_map_rad( r_1, r_2 );
147
148 for ( int wedge = 0; wedge < num_wedges_per_hex_cell; wedge++ )
149 {
150 for ( int q = 0; q < num_quad_points; q++ )
151 {
152 const dense::Mat< ScalarT, 3, 3 > j_lat_3x3 = jac_lat(
153 wedge_phy_surf[wedge][0],
154 wedge_phy_surf[wedge][1],
155 wedge_phy_surf[wedge][2],
156 quad_points[q]( 0 ),
157 quad_points[q]( 1 ) );
158
160 j_lat( 0, 0 ) = j_lat_3x3( 0, 0 );
161 j_lat( 0, 1 ) = j_lat_3x3( 0, 1 );
162 j_lat( 1, 0 ) = j_lat_3x3( 1, 0 );
163 j_lat( 1, 1 ) = j_lat_3x3( 1, 1 );
164 j_lat( 2, 0 ) = j_lat_3x3( 2, 0 );
165 j_lat( 2, 1 ) = j_lat_3x3( 2, 1 );
166 j_lat = j_lat * forward_map_rad( r_1, r_2, zeta_boundary_ );
167
168 const auto det = Kokkos::sqrt( Kokkos::abs( ( j_lat.transposed() * j_lat ).det() ) );
169
170 for ( int i = 0; i < num_nodes_per_wedge; i++ )
171 {
172 for ( int j = 0; j < num_nodes_per_wedge; j++ )
173 {
174 const dense::Vec< ScalarT, 3 > qp_lat{
175 quad_points[q]( 0 ), quad_points[q]( 1 ), zeta_boundary_ };
176
177 const ScalarT shape_i = shape_lat( i, qp_lat ) * shape_rad( i, qp_lat );
178 const ScalarT shape_j = shape_lat( j, qp_lat ) * shape_rad( j, qp_lat );
179
180 A[wedge]( i, j ) += quad_weights[q] * ( shape_i * shape_j * det );
181 }
182 }
183 }
184 }
185
187 extract_local_wedge_scalar_coefficients( src, local_subdomain_id, x_cell, y_cell, r_cell, src_ );
188
190
191 dst[0] = A[0] * src[0];
192 dst[1] = A[1] * src[1];
193
194 atomically_add_local_wedge_scalar_coefficients( dst_, local_subdomain_id, x_cell, y_cell, r_cell, dst );
195 }
196};
197
200
201} // namespace terra::fe::wedge::operators::shell
ScalarT ScalarType
Definition boundary_mass.hpp:22
BoundaryMass(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::shell::ShellBoundaryFlag boundary_flag, linalg::OperatorApplyMode operator_apply_mode=linalg::OperatorApplyMode::Replace, linalg::OperatorCommunicationMode operator_communication_mode=linalg::OperatorCommunicationMode::CommunicateAdditively)
Definition boundary_mass.hpp:45
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition boundary_mass.hpp:72
void operator()(const int local_subdomain_id, const int x_cell, const int y_cell, const int r_cell) const
Definition boundary_mass.hpp:121
Parallel data structure organizing the thick spherical shell metadata for distributed (MPI parallel) ...
Definition spherical_shell.hpp:2498
const std::map< SubdomainInfo, std::tuple< LocalSubdomainIdx, SubdomainNeighborhood > > & subdomains() const
Definition spherical_shell.hpp:2580
const DomainInfo & domain_info() const
Returns a const reference.
Definition spherical_shell.hpp:2577
int subdomain_num_nodes_radially() const
Equivalent to calling subdomain_num_nodes_radially( subdomain_refinement_level() )
Definition spherical_shell.hpp:861
int subdomain_num_nodes_per_side_laterally() const
Equivalent to calling subdomain_num_nodes_per_side_laterally( subdomain_refinement_level() )
Definition spherical_shell.hpp:852
int num_subdomains_in_radial_direction() const
Definition spherical_shell.hpp:849
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
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
constexpr int quad_triangle_3_num_quad_points
Definition triangle/quadrature/quadrature.hpp:8
constexpr void quad_triangle_3_quad_points(dense::Vec< T, 2 >(&quad_points)[quad_triangle_3_num_quad_points])
Definition triangle/quadrature/quadrature.hpp:12
constexpr void quad_triangle_3_quad_weights(T(&quad_weights)[quad_triangle_3_num_quad_points])
Definition triangle/quadrature/quadrature.hpp:21
Definition boundary_mass.hpp:14
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
constexpr T shape_rad(const int node_idx, const T zeta)
Radial shape function.
Definition integrands.hpp:86
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 T shape_lat(const int node_idx, const T xi, const T eta)
Lateral shape function.
Definition integrands.hpp:118
constexpr T forward_map_rad(const T r_1, const T r_2, const T zeta)
Definition integrands.hpp:579
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
constexpr int num_nodes_per_wedge
Definition kernel_helpers.hpp:7
constexpr dense::Mat< T, 3, 3 > jac_lat(const dense::Vec< T, 3 > &p1_phy, const dense::Vec< T, 3 > &p2_phy, const dense::Vec< T, 3 > &p3_phy, const T xi, const T eta)
Definition integrands.hpp:620
ShellBoundaryFlag
FlagLike that indicates boundary types for the thick spherical shell.
Definition shell/bit_masks.hpp:12
Kokkos::View< ScalarType ***[VecDim], Layout > Grid3DDataVec
Definition grid_types.hpp:40
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.
Definition mat.hpp:10