18template <
typename ScalarT >
45 : domain_coarse_( domain_coarse )
46 , grid_fine_( grid_fine )
47 , radii_fine_( radii_fine )
49 , send_buffers_( domain_coarse )
50 , recv_buffers_( domain_coarse )
53 grid_fine.extent( 1 ) - 1 )
55 throw std::runtime_error(
56 "Restriction: domain_coarse and grid_fine must have compatible number of cells." );
61 throw std::runtime_error(
62 "Restriction: domain_coarse and radii_fine must have compatible number of cells." );
76 if ( src_.extent( 0 ) != dst_.extent( 0 ) )
78 throw std::runtime_error(
"Restriction: src and dst must have the same number of subdomains." );
81 for (
int i = 1; i <= 3; i++ )
83 if ( src_.extent( i ) - 1 != 2 * ( dst_.extent( i ) - 1 ) )
85 throw std::runtime_error(
"Restriction: src and dst must have a compatible number of cells." );
92 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
107 domain_coarse_, dst_, send_buffers_, recv_buffers_ );
111 KOKKOS_INLINE_FUNCTION
void
112 operator()(
const int local_subdomain_id,
const int x_fine,
const int y_fine,
const int r_fine )
const
121 if ( x_fine % 2 == 0 && y_fine % 2 == 0 && r_fine % 2 == 0 )
123 const auto x_coarse = x_fine / 2;
124 const auto y_coarse = y_fine / 2;
125 const auto r_coarse = r_fine / 2;
128 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse ),
129 src_( local_subdomain_id, x_fine, y_fine, r_fine ) );
134 const auto r_coarse_bot = r_fine < src_.extent( 3 ) - 1 ? r_fine / 2 : r_fine / 2 - 1;
135 const auto r_coarse_top = r_coarse_bot + 1;
137 if ( x_fine % 2 == 0 && y_fine % 2 == 0 )
139 const auto x_coarse = x_fine / 2;
140 const auto y_coarse = y_fine / 2;
149 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse_bot ),
150 weights( 0 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine ) );
152 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse_top ),
153 weights( 1 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine ) );
164 if ( x_fine % 2 == 0 )
167 x_coarse_0 = x_fine / 2;
168 x_coarse_1 = x_fine / 2;
170 y_coarse_0 = y_fine / 2;
171 y_coarse_1 = y_fine / 2 + 1;
173 else if ( y_fine % 2 == 0 )
176 x_coarse_0 = x_fine / 2;
177 x_coarse_1 = x_fine / 2 + 1;
179 y_coarse_0 = y_fine / 2;
180 y_coarse_1 = y_fine / 2;
185 x_coarse_0 = x_fine / 2 + 1;
186 x_coarse_1 = x_fine / 2;
188 y_coarse_0 = y_fine / 2;
189 y_coarse_1 = y_fine / 2 + 1;
200 &dst_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_bot ),
201 weights( 0 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine ) );
203 &dst_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_bot ),
204 weights( 0 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine ) );
206 &dst_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_top ),
207 weights( 1 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine ) );
209 &dst_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_top ),
210 weights( 1 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine ) );
214 KOKKOS_INLINE_FUNCTION
void
215 operator()(
const int local_subdomain_id,
const int x_coarse,
const int y_coarse,
const int r_coarse )
const
217 const auto x_fine = 2 * x_coarse;
218 const auto y_fine = 2 * y_coarse;
219 const auto r_fine = 2 * r_coarse;
222 wedge::shell::prolongation_fine_grid_stencil_offsets_at_coarse_vertex( offsets );
224 for (
const auto& offset : offsets )
226 const auto fine_stencil_x = x_fine + offset( 0 );
227 const auto fine_stencil_y = y_fine + offset( 1 );
228 const auto fine_stencil_r = r_fine + offset( 2 );
230 if ( fine_stencil_x >= 0 && fine_stencil_x < src_.extent( 1 ) && fine_stencil_y >= 0 &&
231 fine_stencil_y < src_.extent( 2 ) && fine_stencil_r >= 0 && fine_stencil_r < src_.extent( 3 ) )
233 const auto weight = wedge::shell::prolongation_weight< ScalarType >(
234 fine_stencil_x, fine_stencil_y, fine_stencil_r, x_coarse, y_coarse, r_coarse );
236 const auto mask_weight =
238 mask_src_( local_subdomain_id, fine_stencil_x, fine_stencil_y, fine_stencil_r ),
239 grid::mask_owned() ) ?
244 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse ),
245 weight * mask_weight * src_( local_subdomain_id, fine_stencil_x, fine_stencil_y, fine_stencil_r ) );
252template <
typename ScalarT >
279 : domain_coarse_( domain_coarse )
280 , grid_fine_( grid_fine )
281 , radii_fine_( radii_fine )
283 , send_buffers_( domain_coarse )
284 , recv_buffers_( domain_coarse )
287 grid_fine.extent( 1 ) - 1 )
289 throw std::runtime_error(
290 "Restriction: domain_coarse and grid_fine must have compatible number of cells." );
295 throw std::runtime_error(
296 "Restriction: domain_coarse and radii_fine must have compatible number of cells." );
310 if ( src_.extent( 0 ) != dst_.extent( 0 ) )
312 throw std::runtime_error(
"Restriction: src and dst must have the same number of subdomains." );
315 for (
int i = 1; i <= 3; i++ )
317 if ( src_.extent( i ) - 1 != 2 * ( dst_.extent( i ) - 1 ) )
319 throw std::runtime_error(
"Restriction: src and dst must have a compatible number of cells." );
324 Kokkos::parallel_for(
326 Kokkos::MDRangePolicy< Kokkos::Rank< 4 > >(
341 domain_coarse_, dst_, send_buffers_, recv_buffers_ );
345 KOKKOS_INLINE_FUNCTION
void
346 operator()(
const int local_subdomain_id,
const int x_fine,
const int y_fine,
const int r_fine )
const
348 for (
int dim = 0; dim < 3; ++dim )
357 if ( x_fine % 2 == 0 && y_fine % 2 == 0 && r_fine % 2 == 0 )
359 const auto x_coarse = x_fine / 2;
360 const auto y_coarse = y_fine / 2;
361 const auto r_coarse = r_fine / 2;
364 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse, dim ),
365 src_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) );
370 const auto r_coarse_bot = r_fine < src_.extent( 3 ) - 1 ? r_fine / 2 : r_fine / 2 - 1;
371 const auto r_coarse_top = r_coarse_bot + 1;
373 if ( x_fine % 2 == 0 && y_fine % 2 == 0 )
375 const auto x_coarse = x_fine / 2;
376 const auto y_coarse = y_fine / 2;
385 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse_bot, dim ),
386 weights( 0 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) );
388 &dst_( local_subdomain_id, x_coarse, y_coarse, r_coarse_top, dim ),
389 weights( 1 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) );
400 if ( x_fine % 2 == 0 )
403 x_coarse_0 = x_fine / 2;
404 x_coarse_1 = x_fine / 2;
406 y_coarse_0 = y_fine / 2;
407 y_coarse_1 = y_fine / 2 + 1;
409 else if ( y_fine % 2 == 0 )
412 x_coarse_0 = x_fine / 2;
413 x_coarse_1 = x_fine / 2 + 1;
415 y_coarse_0 = y_fine / 2;
416 y_coarse_1 = y_fine / 2;
421 x_coarse_0 = x_fine / 2 + 1;
422 x_coarse_1 = x_fine / 2;
424 y_coarse_0 = y_fine / 2;
425 y_coarse_1 = y_fine / 2 + 1;
436 &dst_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_bot, dim ),
437 weights( 0 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) );
439 &dst_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_bot, dim ),
440 weights( 0 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) );
442 &dst_( local_subdomain_id, x_coarse_0, y_coarse_0, r_coarse_top, dim ),
443 weights( 1 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) );
445 &dst_( local_subdomain_id, x_coarse_1, y_coarse_1, r_coarse_top, dim ),
446 weights( 1 ) * src_( local_subdomain_id, x_fine, y_fine, r_fine, dim ) );
Definition restriction_linear.hpp:20
ScalarT ScalarType
Definition restriction_linear.hpp:24
void operator()(const int local_subdomain_id, const int x_fine, const int y_fine, const int r_fine) const
Definition restriction_linear.hpp:112
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition restriction_linear.hpp:66
RestrictionLinear(const grid::shell::DistributedDomain &domain_coarse, const grid::Grid3DDataVec< ScalarType, 3 > &grid_fine, const grid::Grid2DDataScalar< ScalarType > &radii_fine)
Definition restriction_linear.hpp:41
Definition restriction_linear.hpp:254
void apply_impl(const SrcVectorType &src, DstVectorType &dst)
Definition restriction_linear.hpp:300
ScalarT ScalarType
Definition restriction_linear.hpp:258
void operator()(const int local_subdomain_id, const int x_fine, const int y_fine, const int r_fine) const
Definition restriction_linear.hpp:346
RestrictionVecLinear(const grid::shell::DistributedDomain &domain_coarse, const grid::Grid3DDataVec< ScalarType, 3 > &grid_fine, const grid::Grid2DDataScalar< ScalarType > &radii_fine)
Definition restriction_linear.hpp:275
Parallel data structure organizing the thick spherical shell metadata for distributed (MPI parallel) ...
Definition spherical_shell.hpp:2498
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
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
const grid::Grid4DDataScalar< grid::NodeOwnershipFlag > & mask_data() const
Get const reference to mask data.
Definition vector_q1.hpp:142
Static assertion: VectorQ1Scalar satisfies VectorLike concept.
Definition vector_q1.hpp:162
const grid::Grid4DDataScalar< grid::NodeOwnershipFlag > & mask_data() const
Get const reference to mask data.
Definition vector_q1.hpp:285
const grid::Grid4DDataVec< ScalarType, VecDim > & grid_data() const
Get const reference to grid data.
Definition vector_q1.hpp:280
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 dense::Vec< ScalarType, 2 > prolongation_linear_weights(const dense::Vec< int, 4 > &idx_fine, const dense::Vec< int, 4 > &idx_coarse_bot, const grid::Grid3DDataVec< ScalarType, 3 > &subdomain_shell_coords_fine, const grid::Grid2DDataScalar< ScalarType > subdomain_radii_fine)
Computes prolongation weights for the spherical shell.
Definition grid_transfer_linear.hpp:14
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
constexpr bool has_flag(E mask_value, E flag) noexcept
Checks if a bitmask value contains a specific flag.
Definition bit_masking.hpp:43